Как найти, какие банки и в каком порядке загружаются загрузчиком классов?
Я не мог найти четкого ответа на этот вопрос в другом месте, поэтому я попробую здесь:
Есть ли какой-то способ (программный или другой), чтобы получить список JAR/классов, загружаемых загрузчиком классов приложений, в том порядке, в котором они были загружены?
Посредством Application Classloader я подразумеваю загрузчик классов, который загружает приложение EAR на сервере приложений (WLS, WAS, JBoss...), но, очевидно, это относится к любому загрузчику классов.
Итак, чтобы обобщить, я хотел бы узнать список и порядок JAR, загруженные указанным загрузчиком классов. Не отдельные классы, которые достаточно легко узнать, вызывая classloader.getPackages(), но список файлов JAR, загруженных этим загрузчиком классов.
Ответы
Ответ 1
Короткий ответ - нет. Classloaders не обязаны раскрывать свою логику поиска.
Однако, если ваш экземпляр classloader оказывается URLClassLoader или подкласс, тогда у вас есть доступ к списку баннеров/каталогов, используя метод getURLs()
. В отношении документа для этого класса эти URL-адреса будут выполняться по порядку.
На практике, если вы пытаетесь выяснить, откуда загружается класс, ответ Стив скорее полезен.
Ответ 2
Вы пытались использовать опцию JVM -verbose:class
. Он отображает все загруженные файлы JAR и классы.
Пример:
[Opened C:\Program Files\JDK160~1\jre\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\JDK160~1\jre\lib\rt.jar]
Ответ 3
Пройдите через Защитный домен класса (комбинация местоположения/сертификата). например для PDFParser.class вы получите это как...
PDFParser.class.getProtectionDomain().getCodeSource().getLocation().toString()
Если он загружен из классов jre или из одобренных dirs, он выдает исключение, потому что эти классы загружаются без защиты...
Ответ 4
Как альтернативный способ, вы можете использовать этот фрагмент кода. Результатом является файл, который состоит из связанных файлов jar с файлами класса-загрузчика и класса, которые загружаются классом-загрузчиками объектов (цепочка классов-загрузчиков, включая его родителей, до корневого загрузчика классов). Класс-погрузчики разделены звездами.
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);
}