Class.getResource()和ClassLoader.getResource()在可执行jar中的奇怪行为

时间:2012-11-07 12:12:09

标签: java classloader embedded-resource executable-jar

我从What is the difference between Class.getResource() and ClassLoader.getResource()?了解到 从自己的代码,

getClass().getResource("/path/image.png")

相同
getClass().getClassLoader().getResource("path/image.png")

发布Cannot read an image in jar file显示使用

的问题
getClass().getClassLoader().getResource("path/image.png")
可执行jar文件中的

返回null,而

getClass().getResource("/path/image.png")

返回正确的网址。

删除前导斜杠后,

Since Class.getResource()委托给ClassLoader.getResource(),我希望这些调用是相同的,但显然它们不是这种情况。即使特殊类加载器附加到特定类,每次调用它仍然应该是相同的,再次导致相同的行为。

所以,问题是:是否存在以下任何明显的情况 代码在第一次调用时返回null,但第二次调用返回正确的URL?

package com.example;

import java.net.URL;

public class ResourceTest {

   public void run() {
      URL iconUrl1 = getClass().getClassLoader().getResource("path/image.png");
      System.out.println("ClassLoader.getResource(\"path/image.png\"): " + iconUrl1);

      URL iconUrl2 = getClass().getResource("/path/image.png");
      System.out.println("Class.getResource(\"/path/image.png\"): " + iconUrl2);
   }

   public static void main(String[] args) {
      ResourceTest app = new ResourceTest();
      app.run();
   }
}

1 个答案:

答案 0 :(得分:38)

我认为这个问题已经被问到并回答了!

        

getClass().getResource()搜索相对于.class文件   getClass().getClassLoader().getResource()搜索相对于   classpath root。

如果这里有SSCCE,我不明白它为什么不

1)在.jar中显示目录组织,然后......

2)考虑包装

问:What is the difference between Class.getResource() and ClassLoader.getResource()?(及其引用的链接)尚未回答什么(如果有的话)?

=============================================== ==========================

我仍然不确定什么不清楚,但这个例子可能会有所帮助:

/*
  SAMPLE OUTPUT:
  ClassLoader.getResource(/subdir/readme.txt): NULL
  Class.getResource(/subdir/readme.txt): SUCCESS

  ClassLoader.getResource(subdir/readme.txt): SUCCESS
  Class.getResource(subdir/readme.txt): NULL
 */
package com.so.resourcetest;

import java.net.URL;

public class ResourceTest {

    public static void main(String[] args) {
        ResourceTest app = new ResourceTest ();
    }

    public ResourceTest () {
        doClassLoaderGetResource ("/subdir/readme.txt");
        doClassGetResource ("/subdir/readme.txt");
        doClassLoaderGetResource ("subdir/readme.txt");
        doClassGetResource ("subdir/readme.txt");
    }

    private void doClassLoaderGetResource (String sPath) {
        URL url  = getClass().getClassLoader().getResource(sPath);
        if (url == null)
            System.out.println("ClassLoader.getResource(" + sPath + "): NULL");
        else
            System.out.println("ClassLoader.getResource(" + sPath + "): SUCCESS");
    }

    private void doClassGetResource (String sPath) {
        URL url  = getClass().getResource(sPath);
        if (url == null)
            System.out.println("Class.getResource(" + sPath + "): NULL");
        else
            System.out.println("Class.getResource(" + sPath + "): SUCCESS");
    }
}

这是相应的目录树。它碰巧是一个Eclipse项目,但无论是Eclipse,Netbeans还是.jar文件,目录都是一样的:

C:.
├───.settings
├───bin
│   ├───com
│   │   └───so
│   │       └───resourcetest
│   └───subdir
└───src
    ├───com
    │   └───so
    │       └───resourcetest
    └───subdir

正在打开的文件是“subdir / readme.txt”


ADDENDUM 11/9/12:

嗨 -

我从github逐字复制你的代码,重新编译并重新运行:

ClassLoader.getResource(/subdir/readme.txt): NULL
Class.getResource(/subdir/readme.txt): SUCCESS
ClassLoader.getResource(subdir/readme.txt): SUCCESS
Class.getResource(subdir/readme.txt): NULL

如果你得到的输出......我很困惑。

无论价值多少,我都在跑步:

  • Eclipse Indigo(无所谓)

  • 在IDE内部运行(无论是文件系统还是.jar,在IDE内部或外部都无关紧要)

  • 我的JRE是1.6(如果有的话,这可能是个大问题)

很抱歉,我们无法解决我以为这个简单明了的问题:(


ADDENDUM 11/21/12(Andreas):

由于此问题最近没有活动,我想总结一下我们发现的内容:

  • 根据我们的共识,上述问题的答案是:“不,Class.getResource("/path/image.png")无法返回有效的网址,而ClassLoader.getResource("path/image.png")则返回空”
    • 我们完全清楚ClassLoader.getResource()和Class.getResource()之间的区别
    • 我们的示例输出与“SUCCESS”和“null”
    • 相匹配
    • 样本输出符合我们的预期
    • 结论:要么我们监督某些事情,要么不同的事情导致链接问题中描述的“解决方案”起作用。我想我们现在无法证明这一个。