Я хотел бы получить список всех классов, принадлежащих определенному пакету, а также всем их детям. Классы могут или не могут быть уже загружены в JVM.
Что ж, я просто перечислил все файлы в пути к классам. Возможно, это не лучшее решение, но оно работает надежно и дает мне все, что я хочу, и даже больше.
Я также предлагаю вам написать агент -javagent
, но использовать метод getAllLoadedClasses вместо преобразования любые занятия.
Для синхронизации с клиентским кодом (Обычный код Java),создать сокет и общаться с агентом через него. Затем вы можете запускать метод «перечислить все классы», когда вам нужно.
Вы можете получить список классов, которые загружаются через загрузчик классов, но он не будет включать классы, которые вы еще не загрузили, но которые находятся на вашем путь к классам.
Чтобы получить ВСЕ классы в вашем пути к классам, вы должны сделать что-то вроде вашего второго решения. Если вам действительно нужны классы, которые в настоящее время являются «загруженными» (другими словами, классы, на которые вы уже ссылались, к которым вы обращались или создавали экземпляры), вам следует уточнить свой вопрос, чтобы указать это.
Это не программное решение, но вы можете запустить
java -verbose:class ....
и JVM выдаст, что она загружает и откуда.
[Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jsse.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jce.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar]
[Loaded java.lang.Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.io.Serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
Более подробную информацию смотрите здесь.
Альтернативный подход к описанному выше - создание внешнего агента, использующего java.lang.instrument
, чтобы узнать, какие классы загружены, и запустить вашу программу с помощью -javaagent
switch:
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class SimpleTransformer implements ClassFileTransformer {
public SimpleTransformer() {
super();
}
public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException {
System.out.println("Loading class: " + className);
return bytes;
}
}
У этого подхода есть дополнительное преимущество, заключающееся в предоставлении вам информации о том, какой ClassLoader загрузил данный класс.