为什么Java要求“该方法在给定的Java虚拟机中最多只能被调用一次”?

6
在Java静态方法URL.setURLStreamHandlerFactory的文档中,有一个警告:“在给定的Java虚拟机中,此方法最多只能调用一次”。

http://docs.oracle.com/javase/7/docs/api/java/net/URL.html#setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory)

我简要地查看了源代码,并且在URL类中有一个静态实例变量:

static URLStreamHandlerFactory factory;

而 setURLStreamHandlerFactory 仅仅是将工厂分配给这个变量:

public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
    synchronized (streamHandlerLock) {
        if (factory != null) {
            throw new Error("factory already defined");
        }

        SecurityManager security = System.getSecurityManager();

        if (security != null) {
            security.checkSetFactory();
        }

        handlers.clear();

        factory = fac;
    }
}

允许多次调用此方法将导致覆盖此工厂实例变量,但我不明白为什么Java要阻止这种行为。
为什么Java要求每个JVM只能调用一次此方法?

1
我们怎么知道呢?不过这是有道理的 - 通常情况下,当在JVM初始化时定义时,你不希望用户应用程序能够覆盖这些东西。 - eis
setURLStreamHandlerFactory方法应该由用户应用程序调用(我假设),但这是一个奇怪的要求,即用户应用程序只能调用此方法一次。 - SHH
2
也许这与URLClassLoader类的存在和普遍使用有关。假设URLClassLoader最终依赖于URL来检索数据,我可以想象一旦设置后允许重新定义流处理程序工厂将会为颠覆应用程序提供一个可能的向量。 - John Bollinger
1个回答

5

似乎没有确切的原因。

有趣的是,Eclipse的“Runnable JAR文件导出器”功能注册了一个名为RsrcURLStreamHandlerFactory的自定义URLStreamHandlerFactoryURLStreamHandlerFactory本身包装了另一个URLStreamHandlerFactory并提供了一个setURLStreamHandlerFactory方法来覆盖它。引用该方法的docs

允许添加另一个URLStreamHandler。 URL.setURLStreamHandlerFactory不允许 添加多个工厂。 对于所有其他协议,都将调用链接的工厂, 除了“rsrc”。使用null清除先前设置的处理程序。

这个setURLStreamHandlerFactory可以被多次调用,并应该提供一些证据表明更改处理程序不会导致任何奇怪的行为。

更有趣的是,我发现在1998年的JDK 功能请求 中提到了一个问题,即允许调用setURLStreamHandlerFactory多次以便将多个处理程序链接在一起。该功能请求被标记为未来项目,但显然从未实现。

3
更像是1998年Sun JVM的功能请求 ;) +1 - uraimo
2
@uraimo,我其实在想这怎么可能是一个OpenJDK的功能请求...事实上它并不是:) 我已经更新了帖子和链接,感谢你指出来! - mziccard
看起来他们在2012年左右进行了所有open jdk bug的大规模导入。 - uraimo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接