为什么ClassLoader.getResourceAsStream()会返回null?

Wit*_*eld 6 java cxf jar classpath onejar

故意破坏下面的代码以识别NullPointerException的来源,这应该是非常简单的,但结果却让我疯狂:

Properties properties = new Properties();
Thread currentThread = Thread.currentThread();
ClassLoader contextClassLoader = currentThread.getContextClassLoader();
InputStream propertiesStream = contextClassLoader.getResourceAsStream("resource.properties");
if (propertiesStream != null) {
  properties.load(propertiesStream);
  // TODO close the stream
} else {
  // Properties file not found!
}
Run Code Online (Sandbox Code Playgroud)

我收到"未找到属性文件!" 错误,即contextClassLoader.getResourceAsStream("resource.properties"); 返回null.

这是一个基于CXF的客户端和我验证了"resource.properties"文件在当前目录中的客户端的jar驻留(和运行).

我还通过包含以下诊断代码验证了绝对路径:

            File file = new File("resource.properties");
            System.out.println(file.getAbsolutePath());
Run Code Online (Sandbox Code Playgroud)

绝对路径指向客户端jar的位置.

我也尝试使用以下方法找出类加载器的上下文:

  System.out.println(Thread.currentThread().getContextClassLoader());
Run Code Online (Sandbox Code Playgroud)

但相反,这里演示了一些目录结构,我得到的是:

com.simontuffs.onejar.JarClassLoader@1decdec

为什么ClassLoader.getResourceAsStream()会返回null?

我错过了什么?

Wit*_*eld 7

我解开了这个谜.

解决的关键是 propertiesStream为null 嵌入一​​些诊断日志记录:

String classpath = System.getProperty("java.class.path");
LOG.info("CLASSPATH: " + classpath);
ClassLoader loader = MyClientMain.class.getClassLoader();
System.out.println("ClassLoader resource path: " + loader.getResource("resource.properties"));                    
Run Code Online (Sandbox Code Playgroud)

所以当我用原版跑

contextClassLoader.getResourceAsStream("resource.properties")
Run Code Online (Sandbox Code Playgroud)

我收到空指针条件,打印:

  INFO: CLASSPATH: myproj.one-jar.jar
  ClassLoader resource path: null
Run Code Online (Sandbox Code Playgroud)

.

然后我开始怀疑与"jar中的jar"有关的东西,因为这就是com.simontuffs.onejar本质上做的事情(即将我的项目的jar包装在包含所有其他库jar的jar中),所以我打开了myproj.one-带有7-Zip的jar.jar并注意到"resource.properties"的完整(绝对)路径:

myproj.one-jar.jar\main\myproj.jar\webapp\WEB-INF\classes\resource.properties
Run Code Online (Sandbox Code Playgroud)

.

所以我修改getResource("resource.properties")为:

 getResource("/main/myproj.jar/webapp/WEB-INF/classes/resource.properties")
Run Code Online (Sandbox Code Playgroud)

这没有解决问题,但在空指针条件下打印了以下内容:

INFO: CLASSPATH: myproj.one-jar.jar
ClassLoader resource path: jar:file:/myproj.one-jar.jar!/main/myproj.jar!//main/myproj.jar/webapp/WEB-INF/classes/resource.properties
Run Code Online (Sandbox Code Playgroud)

.

然后......神圣的干预落在了我身上,我有了洞察力(没有阅读任何甚至可能暗示这一点的文件,我发誓!)我应该使用这条道路:

 getResource("/webapp/WEB-INF/classes/resource.properties")
Run Code Online (Sandbox Code Playgroud)

还有瞧!有用.

呼.