简体   繁体   English

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

[英]Strange behavior of Class.getResource() and ClassLoader.getResource() in executable jar

I understand from What is the difference between Class.getResource() and ClassLoader.getResource()? 我理解Class.getResource()和ClassLoader.getResource()之间有什么区别? and from own code, that 从自己的代码,那

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

is identical to 是完全相同的

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

The posting Cannot read an image in jar file shows an issue where using 发布无法读取jar文件中的图像显示使用的问题

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

in an executable jar file returns null, while 在可执行jar文件中返回null,而

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

returns the correct URL. 返回正确的URL。

Since Class.getResource() delegates to ClassLoader.getResource() after removing the leading slash, I would expect that these calls are identical, but obviously they are not in this case. Since Class.getResource()在删除前导斜杠后委托给ClassLoader.getResource() ,我希望这些调用是相同的,但显然它们不是这种情况。 Even when a special class loader is attached to the particular class, it should still be the same one for each call, again resulting in the same behavior. 即使特殊类加载器附加到特定类,每次调用它仍然应该是相同的,再次导致相同的行为。

So, the question is: are there any obvious circumstances under which the following code returns null for the first call but the proper URL for the second call? 所以,问题是: 是否存在以下代码在第一次调用时返回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();
   }
}

I thought this question was already asked and answered! 我以为这个问题已经被问到并回答了!

getClass().getResource() searches relative to the .class file while getClass().getClassLoader().getResource() searches relative to the classpath root. getClass().getResource()相对于.class文件进行搜索,而getClass().getClassLoader().getResource()相对于类路径根进行搜索。

If there's an SSCCE here, I don't understand why it doesn't 如果这里有SSCCE,我不明白为什么不这样做

1) Show the directory organization in the .jar, and... 1)在.jar中显示目录组织,并...

2) Take package into consideration 2)考虑包装

Q: What (if anything) hasn't already been answered by What is the difference between Class.getResource() and ClassLoader.getResource()? 问: Class.getResource()和ClassLoader.getResource()之间有什么区别 (如果有的话)? (and the links it cites)? (以及它引用的链接)?

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

I'm still not sure what isn't clear, but this example might help: 我还不确定什么不清楚,但这个例子可能会有所帮助:

/*
  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");
    }
}

Here's the corresponding directory tree. 这是相应的目录树。 It happens to be an Eclipse project, but the directories are the same regardless if it's Eclipse, Netbeans ... or a .jar file: 它恰好是一个Eclipse项目,但无论是Eclipse,Netbeans还是.jar文件,目录都是相同的:

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

The file being opened is "subdir/readme.txt" 正在打开的文件是“subdir / readme.txt”


ADDENDUM 11/9/12: ADDENDUM 11/9/12:

Hi - 嗨 -

I copied your code verbatim from github, re-compiled and re-ran: 我从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

If that's not the output you're getting ... I'm baffled. 如果这不是你得到的输出......我很困惑。

For whatever it's worth, I'm running: 无论它值多少,我都在跑:

  • Eclipse Indigo (it shouldn't matter) Eclipse Indigo(应该没关系)

  • Running inside the IDE (it shouldn't matter if it's filesystem or .jar, inside or outside an IDE) 在IDE内部运行(无论是文件系统还是.jar,在IDE内部或外部都无关紧要)

  • My JRE is 1.6 (if anything, this is probably the biggie) 我的JRE是1.6(如果有的话,这可能是个大问题)

Sorry we haven't been able to resolve what I thought was a straightforward issue :( 对不起,我们无法解决我认为是一个简单的问题:(


ADDENDUM 11/21/12 (Andreas): ADDENDUM 11/21/12(Andreas):

Since there was no recent activity on this question, I would like to summarize what we found: 由于此问题最近没有活动,我想总结一下我们发现的内容:

  • From our common understanding, the answer to the above question is: "No, it is not possible that Class.getResource("/path/image.png") returns a valid URL, while ClassLoader.getResource("path/image.png") returns null" : 根据我们的共同理解,上述问题的答案是: “不, Class.getResource("/path/image.png")返回有效的URL,而ClassLoader.getResource("path/image.png")返回null”
    • We're completely clear on the difference between ClassLoader.getResource() and Class.getResource() 我们完全清楚ClassLoader.getResource()和Class.getResource()之间的区别
    • Our sample outputs match, for both "SUCCESS" and for "null" 我们的样本输出匹配“SUCCESS”和“null”
    • The sample outputs match what we'd expect 样本输出符合我们的预期
    • Conclusion: Either we oversaw something, or something different caused the "solution" described in the linked question to work. 结论:要么我们监督某些东西,要么是不同的东西导致链接问题中描述的“解决方案”起作用。 I think we can not currently prove one or the other. 我想我们目前无法证明这一个或另一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM