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

我从Class.getResource()和ClassLoader.getResource()之间的区别是什么?以及从自己的代码中了解到,

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

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

帖子无法读取jar文件中的图像显示使用

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

在可执行 jar 文件中返回 null,而

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

返回正确的 URL。

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

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

getClass().getResource()相对于.class文件进行搜索,同时相对于类路径根目录进行搜索。getClass().getClassLoader().getResource()

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

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

2)考虑包装

问:Class.getResource() 和 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”


增编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(如果有的话,这可能是大问题)

很抱歉,我们无法解决我认为是一个简单的问题:(


增编11/21/12(安德烈亚斯):

由于最近没有关于这个问题的活动,我想总结一下我们的发现:

  • 根据我们的共同理解,上述问题的答案是:“不,Class.getResource(”/path/image.png“)不可能返回有效的URL,而ClassLoader.getResource(”path/image.png“)返回null”
    • 我们完全清楚ClassLoader.getResource()和Class.getResource()之间的区别。
    • 我们的样本输出匹配,用于“成功”和“空”
    • 示例输出符合我们的预期
    • 结论:要么我们监督了一些东西,要么不同的东西导致了链接问题中描述的“解决方案”起作用。我认为我们目前无法证明其中一个。

答案 2

推荐