如何列出在特定的类加载器中加载的所有类
出于debugging的原因和好奇心,我希望列出加载到特定类加载器的所有类。
看到类加载器的大多数方法都受到保护,那么完成我所需要的最佳方法是什么?
谢谢!
Instrumentation.getInitiatedClasses(ClassLoader)
可以做你想做的。
根据文件:
返回装载器是启动加载器的所有类的数组。
我不确定“启动加载器”是什么意思。 如果没有给出正确的结果,请尝试使用getAllLoadedClasses()
方法并通过ClassLoader手动过滤。
如何获得Instrumentation
实例
只有代理JAR(与应用程序JAR分开)才能获得Instrumentation
接口的实例。 让应用程序可用的简单方法是创build一个代理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()); } } }
尝试这个。 这是一个黑客的解决scheme,但它会做的。
任何类加载器中的字段classes
(在Sun的impl 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);