为什么我可以从JAR加载类而不是资源?

时间:2017-06-19 15:45:22

标签: java classpath manifest.mf resource-loading

我使用仅包含ClassPath元素的JAR来构建我的Java应用程序的类路径,并且我遇到了一个奇怪的行为:我可以从中提到的JAR中加载类。 ClassPath元素,但缺少部分(或全部)资源。

示例:我的full-classpath.jar只包含META-INF/MANIFEST.MF一般内容和此行:

ClassPath: foo-service.jar bar-service.jar service-main.jar

service-main.jar包含com.pany.project.Main

当我运行java -cp full-classpath.jar com.pany.project.Main时,就可以了。

foo-service.jarbar-service.jar包含META-INF/services/....

中的服务定义

当我从Maven单元测试中调用java.util.ServiceLoader时,它可以看到foobar服务。当我java -cp full-classpath.jar com.pany.project.Main -service foo时,我在日志中看到一个空的服务列表。

更糟糕的是,当我致电Main.class.getClassLoader().getResources("META-INF/MANIFEST.MF")时,我只会获得full-classpath.jar的清单。其他三个JAR中的清单文件丢失了,因为我可以从这些JAR中加载类,所以没有意义。当我手动构建整个类路径时,它也有效。它只在我使用ClassPath中的full-classpath.jar元素时失败。

任何想法可能出错或如何调试?

我正在使用Java 8.

1 个答案:

答案 0 :(得分:0)

清单属性Class-Pathsun.misc.URLClassPath.JarLoader.parseClassPath(URL, String)中处理。此方法从sun.misc.URLClassPath.JarLoader.getClassPath()调用一次。在getClassPath()开头,您可以找到以下代码:

        if (index != null) {
            return null;
        }

        if (metaIndex != null) {
            return null;
        }

表示:如果您的类路径JAR包含索引或"元索引" (不管是什么),Class-Path属性被忽略。

我无法说明为什么Java仍然可以从Class-Path属性中提到的JAR加载类,但删除索引可以解决资源加载问题。