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

时间:2014-04-09 18:31:57

标签: java jar classpath cxf 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!
}

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

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

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

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

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

我也尝试使用:

找出类加载器的上下文
  System.out.println(Thread.currentThread().getContextClassLoader());

,而是一些目录结构as demonstrated here,我得到的是:

  

com.simontuffs.onejar.JarClassLoader@1decdec

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

我错过了什么?

2 个答案:

答案 0 :(得分:7)

我解开了这个谜。

解决的关键是在 propertiesStream为空时嵌入一些诊断记录

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"));                    

所以当我使用原始

运行时
contextClassLoader.getResourceAsStream("resource.properties")

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

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

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

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

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

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

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

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

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

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

而且瞧!它有效。

呼。

答案 1 :(得分:2)

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

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