为什么在Java中创建URL对象(带有错误的URL)需要很长时间?

时间:2012-01-20 13:29:04

标签: java

编辑:事实证明这个问题被错误地问了 - 请参阅my answer below。请投票关闭它。

对于单元测试,我需要让new java.net.URL(String)构造函数抛出MalformedURLException,但它需要花费很长时间才能完成 - 2.5秒。

我理解这可能与尝试创建协议处理程序有关,因此我尝试不指定协议处理程序,例如:

new URL(null);
new URL("://");
new URL("/abc");

我简要介绍了实现,似乎是在预先准备URL字符串以消除明显的错误。为什么需要这么长时间,即使是“null”?

5 个答案:

答案 0 :(得分:3)

因为URL类的长度相当长,并尝试了几种不同的尝试来解析给定(非法)的Url。它甚至尝试加载使用Urls内容解析的不同系统包。

确切的程序在URL constructor的Javadoc中列出。

由于这些操作涉及访问和加载不同的类和文件,因此首次访问此类非法Url可能需要相当长的时间。

答案 1 :(得分:1)

也许您可以使用URI来提高性能?

  

注意,URI类确实执行其组件字段的转义   某些情况下。管理编码和推荐的方法   URL的解码是使用URI,并在这两者之间进行转换   使用toURI()和URI.toURL()的类。

     

也可以使用URLEncoder和URLDecoder类,但仅限于   HTML表单编码,与编码方案不同   在RFC2396中定义。

来自http://java.sun.com/j2se/1.5.0/docs/api/java/net/URL.html

  

“鼓励人们使用URI进行解析和URI比较,以及   保留用于访问URI本身的URL类,获取协议   处理程序,与协议等交互。所以,目前,我们没有   计划更改URL.equals / hashCode行为,我们将离开   当我们重新调查我们的选择时,这个错误一直持续到Tiger。“

来自http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4434494,2001。

答案 2 :(得分:1)

这可能是导致延迟的其他原因吗?我不能重现这个:

public class UrlTest {

    static public void urltest(String s) {
        long start = System.currentTimeMillis();
        try {
            new URL(s);
            System.out.println("successfully created URL after "+(System.currentTimeMillis()-start)+" milliseconds. URL: "+s);
        } catch(Exception e) {
            System.out.println(e.toString()+" after "+(System.currentTimeMillis()-start)+" milliseconds. URL: "+s);         
        }
    }

    static public void main(String[] args) {
        System.out.println(System.getProperty("java.version"));
        urltest(null);
        urltest("://");
        urltest("/abc");

    }
}

输出:

1.6.0_18-ea
java.net.MalformedURLException after 0 milliseconds. URL: null
java.net.MalformedURLException: no protocol: :// after 1 milliseconds. URL: ://
java.net.MalformedURLException: no protocol: /abc after 0 milliseconds. URL: /abc

关于equals(),这来自javadoc

  

如果两个主机名都可以解析为相同的IP地址,则认为两台主机是等效的。否则,如果无法解析任何一个主机名,则主机名必须相等而不考虑大小写;或两个主机名都等于​​null。

     

由于主机比较需要名称解析,因此此操作是阻止操作。

     

注意:已知已定义的equals行为与HTTP中的虚拟主机不一致。

答案 3 :(得分:1)

感谢您分享您的单元测试结果 - 您说得对,URL创建几乎没有。比较导致麻烦:

Assert.assertThat(url, equalTo(new URL("http://aa"))); // about 2 seconds

似乎真的打电话给http://aa !似乎只有“localhost”它很快:

Assert.assertThat(url, equalTo(new URL("http://localhost"))); // a few ms

解决方案是比较字符串表示:

Assert.assertThat(url.toExternalForm(), equalTo(new URL("http://aa").toExternalForm()));

答案 4 :(得分:0)

单步执行它,看看它花费的时间!

我预计它会尝试进行DNS查找,并且您的DNS客户端或服务器配置错误。