2010-04-21 1 views
33

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

Увидеть, как большинство методов классного загрузчика защищены, что является лучшим способом выполнить то, что я хочу?

Спасибо!

+1

Смотрите также: http://forums.sun.com/thread.jspa?threadID=341935&start=15 – finnw

ответ

27

Instrumentation.getInitiatedClasses(ClassLoader) может делать то, что вы хотите.

Согласно документации:

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

Я не уверен, что означает «инициирующий загрузчик». Если это не дает правильного результата, попробуйте использовать метод getAllLoadedClasses() и вручную фильтровать ClassLoader.


Как получить экземпляр Instrumentation

Только ЕАО агент (который отделен от JAR приложения) можно получить экземпляр интерфейса Instrumentation. Простым способом сделать его доступным для приложения является создание агента JAR, содержащего один класс, с помощью метода premain, который ничего не делает, кроме сохранения ссылки на экземпляр Instrumentation в свойствах системы.

Пример класс агента:

public class InstrumentHook { 

    public static void premain(String agentArgs, Instrumentation inst) { 
     if (agentArgs != null) { 
      System.getProperties().put(AGENT_ARGS_KEY, agentArgs); 
     } 
     System.getProperties().put(INSTRUMENTATION_KEY, inst); 
    } 

    public static Instrumentation getInstrumentation() { 
     return (Instrumentation) System.getProperties().get(INSTRUMENTATION_KEY); 
    } 

    // Needn't be a UUID - can be a String or any other object that 
    // implements equals().  
    private static final Object AGENT_ARGS_KEY = 
     UUID.fromString("887b43f3-c742-4b87-978d-70d2db74e40e"); 

    private static final Object INSTRUMENTATION_KEY = 
     UUID.fromString("214ac54a-60a5-417e-b3b8-772e80a16667"); 

} 

Пример манифест:

Manifest-Version: 1.0 
Premain-Class: InstrumentHook 

Полученный JAR должен быть затем ссылаться приложением и указанного в командной строке (с опцией -javaagent), когда запуск приложения. Он может быть загружен дважды в разные ClassLoader с, но это не проблема, так как система Properties является однопроцессорным процессом.

класс Пример применения

public class Main { 
    public static void main(String[] args) { 
     Instrumentation inst = InstrumentHook.getInstrumentation(); 
     for (Class<?> clazz: inst.getAllLoadedClasses()) { 
      System.err.println(clazz.getName()); 
     } 
    } 
} 
+0

Но как получить экземпляр инструментария? –

+1

@Arne Burmeister, см. Описание пакета: http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html – finnw

+0

, поэтому, если я получу его правильно, мне нужно напишите агент, который содержит метод signatured как «public static void premain (String agentArgs, Instrumentation inst)»; а затем вызвать методы Инструментария через inst ref? – Yaneeve

46

Попробуйте это. Это хакерское решение, но это будет сделано.

В поле classes в любом загрузчике классов (под имплантом Sun начиная с версии 1.0) содержится твердая ссылка на классы, определенные загрузчиком, поэтому они не будут GC'd. Вы можете извлечь выгоду из отражения.

Field f = ClassLoader.class.getDeclaredField("classes"); 
f.setAccessible(true); 

ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
Vector<Class> classes = (Vector<Class>) f.get(classLoader); 
+0

На Android я получаю 'Нет полевых классов в класс Ljava/lang/ClassLoader' –

+0

@NathanH, технически, Android даже не Java (пока он не получит OpenJDK), но, как я уже упоминал, это хакерское решение, основанное на том, как classloader был реализован уже более 17 лет. Нет гарантии, что предлагаемый хак будет работать и в будущем. Также на Android я не могу видеть, как работает промежуточное программное обеспечение (с динамической загрузкой классов), поэтому нет необходимости загружать загруженные классы. – bestsss

+0

Android может выполнять динамическую загрузку классов, я делаю это все время с помощью [JavaX] (http://javax.ai1.lol). На самом деле, я загружаю все мои основные программы таким образом (приложение просто заглушка). –

 Смежные вопросы

  • Нет связанных вопросов^_^