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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22971088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 19:42:11  来源:igfitidea点击:

Why would ClassLoader.getResourceAsStream() return null?

javajarclasspathcxfonejar

提问by Withheld

Having the following code broken deliberately to identify the source of a NullPointerException in something that should have been very simple but turns out to drive me nuts:

故意破坏以下代码以识别 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!
}

I get the "Properties file not found!" error, i.e. contextClassLoader.getResourceAsStream("resource.properties"); returns null.

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

This is a CXF-based client and I verified that the "resource.properties" file isin the current directory in which the client's jar resides (and runs).

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

I also verified the absolute path by including the following diagnostic code:

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

            File file = new File("resource.properties");
            System.out.println(file.getAbsolutePath());

The absolute path points to where the client's jar is.

绝对路径指向客户端的 jar 所在的位置。

I also tried finding out the context of the class loader, using:

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

  System.out.println(Thread.currentThread().getContextClassLoader());

but instead some directory structure as demonstrated here, all I get is:

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

com.simontuffs.onejar.JarClassLoader@1decdec

com.simonuffs.onejar.JarClassLoader@1decdec

Why would ClassLoader.getResourceAsStream() return null?

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

What am I missing?

我错过了什么?

采纳答案by Withheld

I solved the mystery.

我解开了谜团。

The key to solving was embedding some diagnostic logging whenpropertiesStreamis null:

解决的关键是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"));                    

So when I run with the original

所以当我用原来的

contextClassLoader.getResourceAsStream("resource.properties")

I receive the null pointer condition, printing:

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

  INFO: CLASSPATH: myproj.one-jar.jar
  ClassLoader resource path: null

.

.

I then started suspecting something related to the "jar within a jar"as this is what the com.simontuffs.onejaressentially does (i.e. wrapping my project's jar inside a jar that contains all other library jars), so I opened myproj.one-jar.jar with 7-Zip and noted the full (absolute) path of "resource.properties":

然后我开始怀疑与“罐子里的罐子”有关的东西,因为这就是com.simantuffs.onejar 的本质(即将我的项目的罐子包装在一个包含所有其他库罐子的罐子里),所以我打开了 myproj.one- jar.jar 与 7-Zip 并记下“resource.properties”的完整(绝对)路径:

myproj.one-jar.jar\main\myproj.jar\webapp\WEB-INF\classes\resource.properties

.

.

So I modified getResource("resource.properties")to:

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

 getResource("/main/myproj.jar/webapp/WEB-INF/classes/resource.properties")

which didn't fix the problem but printed the following upon the null pointer condition:

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

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

.

.

Then... divine intervention fell upon me and I had the insight (not reading any documentation that could even hint this, I swear!) that I should be using this path instead:

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

 getResource("/webapp/WEB-INF/classes/resource.properties")

And Voila! It works.

瞧!有用。

Whew.

哇。

回答by Kayaman

As EJP pointed out, it means that the resource isn't available via the classpath for this particular classloader (different classloaders can have different classpaths).

正如 EJP 所指出的,这意味着资源不能通过这个特定类加载器的类路径使用(不同的类加载器可以有不同的类路径)。

Since the classloader is a JarClassLoader, it will only be able to load resources that are included insidethe jar file. It won't see files that are in the same directory as the jar file.

由于类加载器是一个JarClassLoader,它只能加载包含jar 文件中的资源。它不会看到与 jar 文件位于同一目录中的文件。