Trouver où la classe Java est chargée depuis

Est-ce que quelqu’un sait comment déterminer par programme où le chargeur de classe Java charge réellement la classe?

Je travaille souvent sur de grands projets où le classpath est très long et la recherche manuelle n’est pas vraiment une option. J’ai récemment eu un problème où le chargeur de classe chargeait une version incorrecte d’une classe car elle se trouvait sur le classpath à deux endroits différents.

Alors, comment puis-je obtenir le classloader pour me dire d’où vient le fichier de classe sur le disque?

Edit: Qu’en est-il si le chargeur de classe ne parvient pas à charger la classe en raison d’une incompatibilité de version (ou autre chose), existe-t-il de toute façon un fichier qu’il essaie de lire avant de le lire?

Voici un exemple:

package foo; public class Test { public static void main(Ssortingng[] args) { ClassLoader loader = Test.class.getClassLoader(); System.out.println(loader.getResource("foo/Test.class")); } } 

Ceci imprimé:

 file:/C:/Users/Jon/Test/foo/Test.class 

Une autre façon de savoir d’où une classe est chargée (sans manipuler la source) consiste à démarrer la machine virtuelle Java avec l’option: -verbose:class

 getClass().getProtectionDomain().getCodeSource().getLocation(); 

C’est ce que nous utilisons:

 public static Ssortingng getClassResource(Class klass) { return klass.getClassLoader().getResource( klass.getName().replace('.', '/') + ".class").toSsortingng(); } 

Cela fonctionnera selon l’implémentation de ClassLoader: getClass().getProtectionDomain().getCodeSource().getLocation()

La version de Jon échoue lorsque le ClassLoader l’object est enregistré comme null ce qui semble impliquer qu’il a été chargé par Boot ClassLoader .

Cette méthode traite de cette question:

 public static Ssortingng whereFrom(Object o) { if ( o == null ) { return null; } Class c = o.getClass(); ClassLoader loader = c.getClassLoader(); if ( loader == null ) { // Try the bootstrap classloader - obtained from the ultimate parent of the System Class Loader. loader = ClassLoader.getSystemClassLoader(); while ( loader != null && loader.getParent() != null ) { loader = loader.getParent(); } } if (loader != null) { Ssortingng name = c.getCanonicalName(); URL resource = loader.getResource(name.replace(".", "/") + ".class"); if ( resource != null ) { return resource.toSsortingng(); } } return "Unknown"; } 

Modifier juste la 1ère ligne: Main .class

 Class c = Main.class; Ssortingng path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", ""); System.out.println(path); 

Sortie:

 /C:/Users/Test/bin/ 

Peut-être un mauvais style mais ça marche bien!

Jetez un oeil à cette question similaire. Outil pour découvrir la même classe ..

Je pense que l’obstacle le plus important est si vous avez un classloader personnalisé (chargement depuis une firebase database ou un LDAP)

En règle générale, nous ne soaps pas quoi utiliser. Nous pouvons d’abord obtenir className, puis utiliser ClassLoader pour obtenir l’URL de la classe.

  Ssortingng className = MyClass.class.getName().replace(".", "/")+".class"; URL classUrl = MyClass.class.getClassLoader().getResource(className); Ssortingng fullPath = classUrl==null ? null : classUrl.getPath(); 

Cette approche fonctionne à la fois pour les fichiers et les fichiers JAR:

 Class clazz = Class.forName(nameOfClassYouWant); URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class"); InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish 

En supposant que vous travaillez avec une classe nommée MyClass , les éléments suivants devraient fonctionner:

 MyClass.class.getClassLoader(); 

Que vous puissiez ou non obtenir l’emplacement sur le disque du fichier .class dépend du chargeur de classes lui-même. Par exemple, si vous utilisez quelque chose comme BCEL, une classe donnée peut ne pas avoir de représentation sur disque.