Java - получить список всех классов, загруженных в JVM - PullRequest
62 голосов
/ 31 марта 2010

Я хотел бы получить список всех классов, принадлежащих к определенному пакету, а также всех их детей. Классы могут быть загружены или не загружены в JVM.

Ответы [ 11 ]

100 голосов
/ 31 марта 2010

Это не программное решение, но вы можете запустить

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]

Подробнее см. здесь .

28 голосов
/ 09 марта 2013

с использованием библиотеки Reflections , это просто как:

Reflections reflections = new Reflections("my.pkg", new SubTypesScanner(false));

Это отсканирует все классы в url / s, которые содержат пакет my.pkg.

  • параметр false означает - не исключайте класс Object, который по умолчанию исключен.
  • В некоторых сценариях (разных контейнерах) вы можете передать classLoader, а также параметр.

Итак, получение всех классов - это эффективное получение всех подтипов Object, транзитивно:

Set<String> allClasses = 
    reflections.getStore().getSubTypesOf(Object.class.getName());

(Обычный способ reflections.getSubTypesOf(Object.class) вызовет загрузку всех классов в PermGen и, вероятно, вызовет OutOfMemoryError. Вы не хотите делать это ...)

Если вы хотите получить все прямые подтипы объекта (или любого другого типа), не получая его транзитивные подтипы все сразу, используйте это:

Collection<String> directSubtypes = 
    reflections.getStore().get(SubTypesScanner.class).get(Object.class.getName());
17 голосов
/ 01 декабря 2014

Существует несколько ответов на этот вопрос, отчасти из-за неоднозначного вопроса - в заголовке говорится о классах, загружаемых JVM, тогда как содержание вопроса говорит, что «может или не может быть загружено JVM».

Предполагая, что OP нужны классы, которые загружаются JVM заданным загрузчиком классов, и только те классы, в которых я тоже нуждаюсь, есть решение (, разработанное здесь ), которое выглядит так:

import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

public class CPTest {

    private static Iterator list(ClassLoader CL)
        throws NoSuchFieldException, SecurityException,
        IllegalArgumentException, IllegalAccessException {
        Class CL_class = CL.getClass();
        while (CL_class != java.lang.ClassLoader.class) {
            CL_class = CL_class.getSuperclass();
        }
        java.lang.reflect.Field ClassLoader_classes_field = CL_class
                .getDeclaredField("classes");
        ClassLoader_classes_field.setAccessible(true);
        Vector classes = (Vector) ClassLoader_classes_field.get(CL);
        return classes.iterator();
    }

    public static void main(String args[]) throws Exception {
        ClassLoader myCL = Thread.currentThread().getContextClassLoader();
        while (myCL != null) {
            System.out.println("ClassLoader: " + myCL);
            for (Iterator iter = list(myCL); iter.hasNext();) {
                System.out.println("\t" + iter.next());
            }
            myCL = myCL.getParent();
        }
    }

}

Одна из приятных вещей в этом заключается в том, что вы можете выбрать произвольный загрузчик классов, который хотите проверить. Однако он может сломаться при изменении внутренних классов загрузчика классов, поэтому его следует использовать как одноразовый диагностический инструмент.

7 голосов
/ 31 марта 2010

Я бы также предложил вам написать агент -javagent, но вместо преобразования любых классов используйте метод getAllLoadedClasses .

Для синхронизации с вашим клиентским кодом (нормальный код Java) создайте сокет и через него свяжитесь с агентом. Затем вы можете запускать метод «перечислить все классы» всякий раз, когда вам нужно.

6 голосов
/ 31 марта 2010

Альтернативный подход к описанному выше заключается в создании внешнего агента с использованием java.lang.instrument, чтобы выяснить, какие классы загружены, и запустить вашу программу с ключом -javaagent:

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 загрузил данный класс.

3 голосов
/ 28 августа 2012

Один из способов, если вы уже знаете путь к пакету верхнего уровня, - это использовать OpenPojo

final List<PojoClass> pojoClasses = PojoClassFactory.getPojoClassesRecursively("my.package.path", null);

Затем вы можете просмотреть список и выполнить любую функцию, какую пожелаете.

2 голосов
/ 11 ноября 2011

Запустите ваш код под Jock JRockit, затем используйте JRCMD <PID> print_class_summary

Это выведет все загруженные классы, по одному в каждой строке.

2 голосов
/ 31 марта 2010

Возможно, вы сможете получить список классов, которые загружаются через загрузчик классов, но это не будет включать классы, которые вы еще не загрузили, но находятся в вашем пути к классам.

Чтобы получить ВСЕ классы на вашем пути к классам, вы должны сделать что-то вроде вашего второго решения. Если вы действительно хотите, чтобы классы, которые в данный момент были «загружены» (другими словами, классы, на которые вы уже ссылались, обращались или создавали их), вам следует уточнить свой вопрос, чтобы указать это.

1 голос
/ 30 марта 2019

Из Oracle doc вы можете использовать опцию -Xlog, которая имеет возможность записи в файл.

java -Xlog:class+load=info:classloaded.txt
0 голосов
/ 15 октября 2017

Эта программа напечатает все классы с их физическим путем. Использование может просто скопировать это в любой JSP, если вам нужно проанализировать загрузку классов с любого сервера веб / приложений.

import java.lang.reflect.Field;
import java.util.Vector;

public class TestMain {

    public static void main(String[] args) {
        Field f;
        try {
            f = ClassLoader.class.getDeclaredField("classes");
            f.setAccessible(true);
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Vector<Class> classes =  (Vector<Class>) f.get(classLoader);

            for(Class cls : classes){
                java.net.URL location = cls.getResource('/' + cls.getName().replace('.',
                '/') + ".class");
                System.out.println("<p>"+location +"<p/>");
            }
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...