【问题标题】:Why can I load a class from a JAR but not a resource?为什么我可以从 JAR 加载类而不是资源?
【发布时间】:2017-11-21 22:05:44
【问题描述】:

我正在使用一个仅包含 ClassPath 元素的 JAR 来为我的 Java 应用程序构建类路径,但我遇到了一个奇怪的行为:我可以从 ClassPath 元素中提到的 JAR 中加载类,但有些(或所有)资源丢失。

示例:我的 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.jarMETA-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 加载类!当我手动构建整个类路径时它也可以工作。只有当我在full-classpath.jar 中使用ClassPath 元素时它才会失败。

任何想法可能是错误的或我如何调试它?

我正在使用 Java 8。

【问题讨论】:

    标签: java classpath manifest.mf resource-loading


    【解决方案1】:

    清单属性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 加载类,但删除索引可以解决资源加载问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 1970-01-01
      • 2016-08-21
      相关资源
      最近更新 更多