Странное поведение Class.getResource() и ClassLoader.getResource() в исполняемой банке

Я понимаю из В чем разница между 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() выполняет поиск относительно classpath root.

Если здесь есть 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:

Привет -

Я скопировал ваш код verbatim из 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)

  • My JRE - 1.6 (во всяком случае, это, вероятно, biggie)

Извините, мы не смогли решить то, что, по моему мнению, было простой проблемой: (


ДОБАВЛЕНИЕ 11/21/12 (Andreas):

Поскольку недавнего действия по этому вопросу не было, я хотел бы суммировать то, что мы нашли:

  • Из нашего общего понимания ответ на указанный выше вопрос: "Нет, невозможно, чтобы Class.getResource("/path/image.png") вернул действительный URL-адрес, а ClassLoader.getResource("path/image.png") возвращает null" :
    • Мы полностью понимаем разницу между ClassLoader.getResource() и Class.getResource()
    • Наши результаты выборки соответствуют как для "УСПЕХА", так и для "нулевого"
    • Выходные данные выборки соответствуют ожидаемым
    • Заключение: либо мы что-то наблюдали, либо что-то другое заставляло "решение", описанное в связанном вопросе, работать. Я думаю, мы не можем в настоящее время доказать то или другое.