【问题标题】:getClassLoader().getResourceAsStream() not work in modular java project (openjdk 11)?getClassLoader().getResourceAsStream() 在模块化 Java 项目(openjdk 11)中不起作用?
【发布时间】:2020-04-20 07:07:05
【问题描述】:

这是一个ma​​ven项目,并且在资源目录中有一张图片:

├─ src
   ├─ main
       ├─ java
       └─ resources  
          └─imgs
            └─logo.png

代码:

public class Test {
    public static void main(String[] args) {
        InputStream stream = Test.class.getClassLoader().getResourceAsStream("/imgs/logo.png");
        InputStream stream1 = Test.class.getClassLoader().getResourceAsStream("imgs/logo.png");
        System.out.println(stream == null ? "stream is null!" : "stream is not null!");
        System.out.println(stream1 == null ? "stream1 is null!" : "stream1 is not null!");
    }
}

当我添加 module-info.java 到项目时,将打印:

stream is null!
stream1 is null!

但是当我从项目中删除 module-info.java 时,会打印:

stream is null!
stream1 is not null!

为什么?以及如何使用ClassLoader在模块化java项目中加载资源?

【问题讨论】:

  • 当你从ClassLoader获取资源时,你已经是从root开始了,所以你不应该在前面使用/,所以第二个是正确的。模块是另一回事。

标签: java maven classloader java-11 java-module


【解决方案1】:

资源应该通过Test.class 加载,而不是它的ClassLoader。通过在类上加载资源,您可以为资源所在的位置建立上下文(JAR、模块、依赖项)。

对于在同一个包中的资源,使用相对路径:

Test.class.getResource("logo.png")

如果 Test 的限定名称是 org.foo.Test,它将在 JAR 中(或在构建 JAR 之前在资源文件夹中)中查找 org/foo/logo.png 中的资源。

对于同一模块中的资源,使用绝对路径,以斜杠开头:

Test.class.getResource("/logo.png")

^ 这是你最想使用的。

无需检查类加载器。当开发人员不知道如何正确寻址资源并使用相对路径通过类加载器加载资源时,我经常看到这种情况,这在大多数情况下都有效,但不太适合模块化项目/类加载器,例如 Java9 和 OSGI。

【讨论】:

  • 我知道Test.class.getResource("/logo.png")这种方式来获取资源,但是我想知道如何使用ClassLoader来加载资源。
  • @Guo 如果要使用 ClassLoader 可以查看 OpenJDK 源代码中getResourceAsStream 的源代码:github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/…
  • ClassLoader API 文档是更好的资源,特别是它只在命名模块的包中查找资源然后无条件打开包的声明。 Class::getResourceAsStream 是模块中的代码在其自己的模块中打开资源的正确 API。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 2016-02-10
  • 1970-01-01
  • 2012-10-05
  • 1970-01-01
  • 2010-10-03
  • 2010-11-22
相关资源
最近更新 更多