如果这个问题的答案很简单,我会提前道歉。我似乎对Java中的类加载知之甚少。
假设我的应用程序中有一个名为“properties”的文件。我的应用程序使用外部JAR,在JAR中,还有一个名为“properties”的文件。
问题:
如果外部JAR文件尝试使用getClass().getClassLoader().getResourceAsStream("properties")
打开该文件,为什么不从我的应用程序加载该文件。不是我想要它,但在这种情况下ClassLoader不会是加载我的应用程序的那个吗?我认为该方法将使用绝对路径来查找资源。外部JAR中的类是否加载了不同的类加载器?
答案 0 :(得分:2)
类加载机制对于类和资源是相同的(但找到的字节的处理方式不同)。
有关官方解释,请参阅http://docs.oracle.com/javase/tutorial/ext/basics/load.html。
这是第一个实际问的类加载器,它拥有获胜的资源。如果类加载器没有其资源,请再次使用父级。
(请注意,对于Web应用程序 - WAR文件 - 对于首先询问哪一个,故意略有不同。)
答案 1 :(得分:0)
不,它会加载该类中的第一个'类加载器。如果要使用绝对路径打开文件,请打开指向该文件的InputStream
。
可以使用不同的类加载器(例如,在Java EE容器中)加载外部JAR中的类,但是需要链接类加载器以便您查看它们。
答案 2 :(得分:0)
Th ClassLoader#getResourceAsStream(String)
调用getResource(String)
,并将其作为父级的getResource()。如果没有找到任何内容,那么它会询问类加载器findResource(String)
。
它依赖于此实现它返回的内容,如果URLClassLoader
这将是URLClassPath.findResource()
,它将遍历所有加载器(每个搜索路径条目一个加载器)并返回第一个查找。
在正常的应用程序中,JAR和所有库都由相同的(Application)类加载器加载。如果是太阳发射器,则sun.misc.Launcher$AppClassLoader
延伸URLClassLoader
。它将类路径中的所有JAR和类放在搜索列表中。
最好将资源设置为唯一(将它们放入包中)或检索所有资源并选择正确的资源(或全部)。后者例如在ServiceLoader找到给定服务的所有实现时使用。