Java:类路径 JVM 上的多个资源中的哪一个?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6644440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Which of multiple resources on classpath JVM takes?
提问by Ondra ?i?ka
If I have multiple files of the same name on classpath (e.g. I have multiple .jar
with log4j.properties
), what are the rules JVM follows to chose one?
如果我在类路径上有多个同名文件(例如,我有多个.jar
with log4j.properties
),JVM 选择一个的规则是什么?
采纳答案by mouser
It is specified by the order in which the resources (i.e. usually jar files) are specified using -classpath
option. Resources 'earlier' on the classpath take precedence over resources that are specified after them. This can be also set in the manifest file of your application and then you don't need to provide -classpath
option. You may want to check these articleson how to work with manifest files.
它由使用-classpath
选项指定资源(即通常为 jar 文件)的顺序指定。类路径上“更早”的资源优先于在它们之后指定的资源。这也可以在您的应用程序的清单文件中设置,然后您不需要提供-classpath
选项。您可能需要查看这些关于如何使用清单文件的文章。
The exhaustive description of "how classes are found" can be found here, where the section on JAR-class-path Classesdescribes the logic of JAR-files searching.
“如何找到类”的详尽描述可以在这里找到,其中JAR-class-path 类部分描述了 JAR 文件搜索的逻辑。
回答by emboss
The ClassLoader determines where a resource will be located (taken from ClassLoader JavaDoc):
ClassLoader 确定资源的位置(取自 ClassLoader JavaDoc):
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
ClassLoader 类使用委托模型来搜索类和资源。ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例会将类或资源的搜索委托给其父类加载器,然后再尝试查找类或资源本身。虚拟机的内置类加载器,称为“引导类加载器”,它本身没有父级,但可以作为 ClassLoader 实例的父级。
So wherever in your code Class#getResource or Class#getResourceAsStream is called, this happens (taken from Class.java)
所以在你的代码 Class#getResource 或 Class#getResourceAsStream 中的任何地方,都会发生这种情况(取自 Class.java)
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResource(name);
}
return cl.getResource(name);
}
ClassLoader.java:
类加载器.java:
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
where ClassLoader#findResource is actually to be overwritten by the ClassLoader implementation. This implies that the behavior is different on an application server, a TomCat or if you are running from a jar file, it depends on the ClassLoader implementations of the environment you are currently in.
其中 ClassLoader#findResource 实际上会被 ClassLoader 实现覆盖。这意味着行为在应用程序服务器、TomCat 上是不同的,或者如果您从 jar 文件运行,则取决于您当前所处环境的 ClassLoader 实现。
Hereis an example that you may use to trace what's going under the hood in your particular case.
这是一个示例,您可以使用它来跟踪特定情况下的幕后情况。
回答by S-t-x
I am contributing a proven case that if classpath is, say, all jars in a folder, and you want to prioritize one (or some) of them, this does not work:
我提供了一个经过验证的案例,如果 classpath 是一个文件夹中的所有 jars,并且您想优先考虑其中一个(或一些),这不起作用:
Windows:
视窗:
bin/prioritized.jar;bin/*
Linux:
Linux:
bin/prioritized.jar:bin/*
It appears that the first path bin/prioritized.jar is ignored just because the second one with a wildcard includes it in its own scope. This is what effectivelly breaks the specified order of classpaths.
似乎第一个路径 bin/prioritized.jar 被忽略了,因为第二个带有通配符的路径将它包含在它自己的范围内。这就是有效打破类路径指定顺序的原因。
Therefore, in order to have multiple resources prioritized (tested on Java 10.0.1), you need to put them in non-overlapping scopes and then they will work.
因此,为了优先考虑多个资源(在 Java 10.0.1 上测试),您需要将它们放在不重叠的范围内,然后它们才能工作。