Java空路径约定,特别是在类加载器中使用的。获取资源
今天,我惊讶地(可能是因为缺乏经验)发现,您可以,而且实际上,将一个空路径(字面上是一个空字符串)传递给ClassLoader.getResources
,即。
ClassLoader.getSystemClassLoader().getResources("")
。通过一些测试,这将返回我的应用程序.class
文件所在的一个或两个目录(不包括第三方软件包的目录)。(示例用法:Get all of the Classes in the Classpath。)
这大概是因为Java系统类加载器是加载我自己的应用程序类(c.f.http://www.oracle.com/technetwork/articles/javase/classloaders-140370.html)的三个类加载器之一,所以URL返回指向我的应用程序类文件目录也就不足为奇了
但为什么,以及如何,空字符串实现了这一点?我没有发现文件。这个空路径是更常见的Java约定的派生吗?它当然不是Linux——你不能在bash中进入一个空路径。如果有人能帮我理解这一点,我将不胜感激
在另一个注释中,我注意到getResources(".")
实现了同样的效果
添加评论讨论
public class myTest {
public static void main(String[] args) throws Exception {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader) classLoader).getURLs();
for (int n = 0; n < urls.length; n++)
System.out.println(urls[n]); //lists external.jar
Enumeration<URL> roots = classLoader.getResources(".");
while (roots.hasMoreElements()) {
URL url = roots.nextElement();
System.out.println("getResources: " + url); //does not list external.jar
}
}
}
要执行的命令:java -cp ".:external.jar" myTest
# 1 楼答案
当资源名为“”或“”时,
getResources(String)
调用为什么会匹配作为目录的所有类路径项我只能猜测。对于它的价值,我认为这是特定的^ ^ {CD2}}的实现细节。“和”的方式然而,从文件系统用户的角度来看,资源名称的处理有些直观
。。。怎么做
默认的OpenJDK应用程序} ,该方法执行以下操作:
ClassLoader
(也称为系统ClassLoader
),sun.misc.Launcher$AppClassLoader
是一个URLClassLoader
子体,其URL搜索路径包含“java.class.path”系统属性的值。它的getResources
(getResource
)方法最终委托给^{撇开所有的URL解析不谈,资源名基本上被视为一个相对的文件系统路径,并根据加载程序的搜索路径条目“绝对化”。因此,
name
参数为“or”匹配搜索路径条目本身。换句话说,所有顶级类路径条目都被匹配并返回,就好像它们都位于同一根目录下一样。注意,这不适用于JAR类路径条目,而是由sun.misc.URLClassPath$JarLoader
处理为什么这些
getResources
调用也不匹配JAR类路径条目?为什么URLClassLoader.getURLs()
返回的数组中包含这样的类路径条目API方面
这是两种不相关的方法,每种方法都有不同的用途。有时,它们“碰巧”产生相同或相似的输出,但它们的规范并不意味着行为上的任何形式的相互一致性
根据
URLClassLoader
对术语“资源”的具体定义,指定getResources
返回其搜索路径下的文件、目录或JAR条目。当搜索路径条目表示目录时,它本身也会返回搜索路径条目,这一事实并没有在其规范中得到解决,因此应该被视为一个实现细节(可能还有一个小的违反规范的情况),而不应被依赖。同样,它不返回JAR搜索路径条目,尽管与前者不一致,但这并不违背其规范另一方面
getURLs
返回实例化时提供的确切的1搜索路径条目执行方面
与
sun.misc.URLClassPath$FileLoader
不同,正如前面所看到的,它根据每个搜索路径条目的文件系统路径解析资源名称,sun.misc.URLClassPath$JarLoader
尝试通过JarFile.getEntry(name)
进行直接匹配,这对于“”和最有可能的“,条目名,显然失败了。但是,即使两个URLClassPath.Loader
以相同的方式解释资源名称,事情也不会像预期的那样进行,因为嵌入式JAR文件系统不支持根目录的概念那么我应该如何检索所有类路径条目呢
要独立于系统
ClassLoader
执行此操作,请使用,最好是在
main
方法的早期,在任何第三方代码有机会修改属性之前ClassLoader.getSystemClassLoader()
的返回类型为java.lang.ClassLoader
。我们如何(确定地)知道返回的实例是sun.misc.Launcher$AppClassLoader
我们真的没有。系统类加载器依赖于实现,是可替换的。我们所能做的,一如既往,就是测试,例如
,并据此采取行动。
1这可能并不总是正确的,例如,当搜索路径条目“重叠”(一个是另一个的父项)或应用安全约束时;有关详细信息,请参阅
sun.misc.URLClassPath
的源代码