Java:JVM 占用类路径上的多个资源中的哪一个?

发布于 2024-11-19 08:55:44 字数 103 浏览 3 评论 0原文

如果我在类路径上有多个同名文件(例如,我有多个 .jarlog4j.properties),那么 JVM 选择一个文件时遵循什么规则?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烂人 2024-11-26 08:55:44

它是通过使用-classpath 选项指定资源(即通常是jar 文件)的顺序来指定的。类路径上“较早”的资源优先于在其之后指定的资源。这也可以在应用程序的清单文件中设置,然后您不需要提供 -classpath 选项。您可能需要查看这些文章了解如何使用清单文件。

关于“如何找到类”的详尽描述可以在此处找到,其中JAR-class-path Classes 部分描述了 JAR 文件搜索的逻辑。

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 articles on how to work with manifest files.

The exhaustive description of "how classes are found" can be found here, where the section on JAR-class-path Classes describes the logic of JAR-files searching.

灵芸 2024-11-26 08:55:44

ClassLoader 确定资源的位置(取自 ClassLoader JavaDoc):

ClassLoader 类使用委托模型来搜索类和资源。 ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例会将类或资源的搜索委托给其父类加载器,然后再尝试查找类或资源本身。虚拟机的内置类加载器称为“引导类加载器”,它本身没有父类加载器,但可以充当 ClassLoader 实例的父类加载器。

因此,无论在代码中调用 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:

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;
}

其中 ClassLoader#findResource 实际上会被 ClassLoader 实现覆盖。这意味着应用程序服务器、TomCat 上的行为是不同的,或者如果您从 jar 文件运行,则它取决于您当前所处环境的 ClassLoader 实现。

这里是一个示例,您可以使用它来跟踪特定情况下的幕后情况。

The ClassLoader determines where a resource will be located (taken from 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.

So wherever in your code Class#getResource or Class#getResourceAsStream is called, this happens (taken from 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:

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.

Here is an example that you may use to trace what's going under the hood in your particular case.

裸钻 2024-11-26 08:55:44

我正在提供一个经过验证的案例,如果类路径是一个文件夹中的所有 jar,并且您想要优先考虑其中一个(或某些),则这是行不通的:

Windows:

bin/prioritized.jar;bin/*

Linux:

bin/prioritized.jar:bin/*

看来第一个路径 bin/prioritized .jar 被忽略只是因为第二个带有通配符的将其包含在自己的范围内。这有效地破坏了类路径的指定顺序。

因此,为了让多个资源具有优先级(在 Java 10.0.1 上测试),您需要将它们放在不重叠的作用域中,然后它们才能工作。

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:

Windows:

bin/prioritized.jar;bin/*

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文