web-dev-qa-db-fra.com

Comment trouver quels pots et dans quel ordre sont chargés par un chargeur de classe?

Je n'ai pas pu trouver de réponse claire à cette question ailleurs, alors je vais essayer ici:

Existe-t-il un moyen (programmatique ou autre) d'obtenir une liste des fichiers JAR/classes chargés par un chargeur de classes d'application dans l'ordre précis où ils ont été chargés? Par Application Classloader, j'entends le chargeur de classe qui charge une application EAR dans un serveur d'applications (WLS, WAS, JBoss ...), mais évidemment, il s'applique à tout chargeur de classe.

Donc, pour généraliser, ce que je voudrais savoir, c'est la liste et l'ordre des fichiers JAR chargés par un chargeur de classe spécifié. Pas des classes individuelles, c'est assez facile à trouver en appelant le classloader.getPackages (), mais une liste de fichiers JAR qui ont été chargés par ce chargeur de classe.

42
Marina

La réponse courte est non. Les chargeurs de classe ne sont pas tenus d'exposer leur logique de recherche.

Cependant, si votre instance de chargeur de classe se trouve être RLClassLoader ou une sous-classe, alors vous avez accès à la liste des fichiers/répertoires, via la méthode getURLs(). Selon le document de cette classe, ces URL seront recherchées dans l'ordre.

En pratique, si vous essayez de savoir d'où une classe est chargée, la réponse de Steve est probablement plus utile.

14
kdgregory

Avez-vous essayé d'utiliser l'option JVM -verbose:class. Il affiche tous les fichiers et classes JAR chargés.

Exemple:

[Opened C:\Program Files\JDK160~1\jre\lib\rt.jar]
[Loaded Java.lang.Object from C:\Program Files\JDK160~1\jre\lib\rt.jar]
74
Steve

Parcourez le domaine de protection de la classe (la combinaison emplacement/certificat). par exemple. pour PDFParser.class vous obtenez comme ça ...

PDFParser.class.getProtectionDomain().getCodeSource().getLocation().toString()

S'il est chargé à partir des classes jre ou des répertoires approuvés, il lèvera une exception car ces classes se chargent sans protection ...

1
gmournos

Vous pouvez également utiliser cet extrait de code. Le résultat est un fichier composé de fichiers jar associés à un chargeur de classe et de fichiers de classe qui sont chargés par les chargeurs de classe d'un objet (chaîne de chargeurs de classe, y compris ses parents jusqu'au chargeur de classe racine). Les chargeurs de classe sont séparés par des étoiles.

Object obj = this;
ClassLoader classLoader = obj.getClass().getClassLoader();
File file = new File("classlodersClassesJars.txt");
if(file.exists()) {
    file.delete();
}
if(classLoader != null) { // to escape from system classes that are loaded by bootstrap class-loader such as String.
    do {
        try {
            Class clClass = classLoader.getClass();
            while(clClass != ClassLoader.class){
                    clClass = clClass.getSuperclass();
            }
            Java.lang.reflect.Field domainField = clClass.getDeclaredField("domains");
            Java.lang.reflect.Field classesField = clClass.getDeclaredField("classes");
            domainField.setAccessible(true);
            classesField.setAccessible(true);
            HashSet domains = (HashSet<String>) domainField.get(classLoader);
            Vector classes = (Vector) classesField.get(classLoader);
            FileOutputStream fos = new FileOutputStream("classlodersClassesJars.txt", true);
            fos.write(("\n******************** " + classLoader.toString() + "\n").getBytes());
            fos.write(Arrays.toString(classes.toArray()).getBytes());
            Object[] reverseDomains = domains.toArray();
            org.Apache.commons.lang.ArrayUtils.reverse(reverseDomains);
            fos.write(Arrays.toString(reverseDomains).getBytes());
            fos.close();
            classLoader = classLoader.getParent();
        } catch (Exception exception) {
            exception.printStackTrace();
            // TODO
        }
    } while (classLoader.getParent() != null);
}
0
MMKarami