Comportement étrange de la classe.getResource () et ClassLoader.getResource () dans jar exécutable

Je comprends de Quelle est la différence entre la classe.getResource () et ClassLoader.getResource()? et à partir de son propre code, que

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

Est identique à

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

L'affichage ne peut pas lire une image dans le fichier jar montre un problème où l'utilisation de

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

Dans un fichier JAR exécutable renvoie null, tandis que

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

Renvoie L'URL correcte.

Since Class.getResource() délégués à ClassLoader.getResource() après avoir supprimé la barre oblique principale, je m'attendrais à ce que ces appels soient identiques, mais évidemment ils ne sont pas dans ce cas. Même lorsqu'un chargeur de classe spécial est attaché à la classe particulière, il doit toujours être le même pour chaque appel, ce qui entraîne le même comportement.

Donc, la question Est: y a-t-il des circonstances évidentes dans lesquelles les éléments suivants le code renvoie null pour le premier appel mais l'URL appropriée pour le second appel?

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();
   }
}
26
demandé sur Community 2012-11-07 16:12:09

1 réponses

Je pensais que cette question était déjà posée et répondue!

getClass().getResource() recherches relatives à la .fichier de classe tout en getClass().getClassLoader().getResource() Recherche par rapport au chemin de classe racine.

S'il y a un SSCCE ici, Je ne comprends pas pourquoi ce n'est pas le cas

1) Affiche l'organisation du répertoire dans le .jar et...

2) Prendre le paquet dans examen

Q: Ce qui (le cas échéant) n'a pas déjà été répondu par Quelle est la différence entre la classe.getResource () et ClassLoader.getResource()? (et les liens qu'il cite)?

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

Je ne suis toujours pas sûr de ce qui n'est pas clair, mais cet exemple pourrait aider:

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

Voici l'arborescence correspondante. Il se trouve que c'est un projet Eclipse, mais les répertoires sont les mêmes peu importe si C'est Eclipse, Netbeans ... ou une .fichier jar:

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

Le fichier en cours d'ouverture est " subdir / readme.txt "


Additif 11/9/12:

Salut -

J'ai copié votre code textuellement à partir de github, recompilé et réexécuté:

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

Si pas la sortie que vous obtenez ... Je suis perplexe.

Pour ce que ça vaut, Je cours:

  • Eclipse Indigo (ça ne devrait pas avoir d'importance)

  • Courir à l'intérieur de L'IDE (il peu importe si c'est le système de fichiers ou .pot, à l'intérieur ou à l'extérieur d'un IDE)

  • Mon JRE est 1.6 (Si quoi que ce soit, c'est probablement le biggie)

Désolé, nous n'avons pas été en mesure de résoudre ce que je pensé était un problème simple: (


Additif 11/21/12 (Andreas):

Comme il n'y a pas eu d'activité récente sur cette question, je voudrais résumer ce que nous avons trouvé:

  • de notre compréhension commune, la réponse à ce qui précède la question Est: "Non, il n'est pas possible que Class.getResource("/path/image.png") renvoie une URL valide, tandis que ClassLoader.getResource("path/image.png") renvoie null" :
    • Nous sommes complètement clairs sur la différence entre ClassLoader.getResource () et Class.getResource ()
    • nos exemples de sorties correspondent, à la fois pour "SUCCESS "et pour"null"
    • les sorties de l'échantillon correspondent à ce que nous attendons
    • Conclusion: soit nous avons supervisé quelque chose, soit quelque chose de différent a fait fonctionner la "solution" décrite dans la question liée. Je pense que nous ne peut pas actuellement prouver l'un ou l'autre.
34
répondu paulsm4 2017-05-23 11:54:37