Yan*_*eve 40 java hierarchy classloader
出于调试原因和好奇心,我希望列出加载到特定类加载器的所有类.
看到类加载器的大多数方法都受到保护,实现我想要的最佳方法是什么?
谢谢!
bes*_*sss 57
试试这个.这是一个黑客的解决方案,但它会做.
classes任何类加载器中的字段(在1.0之后的Sun的impl下)都保存了对加载器定义的类的硬引用,因此它们不会是GC.您可以从via反射中获益.
Field f = ClassLoader.class.getDeclaredField("classes");
f.setAccessible(true);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Vector<Class> classes = (Vector<Class>) f.get(classLoader);
Run Code Online (Sandbox Code Playgroud)
fin*_*nnw 32
Instrumentation.getInitiatedClasses(ClassLoader) 可以做你想做的事.
根据文件:
返回所有类的数组,其中loader是启动加载器.
我不确定"启动装载机"是什么意思.如果没有给出正确的结果,请尝试使用该getAllLoadedClasses()方法并通过ClassLoader手动过滤.
如何获得一个实例 Instrumentation
只有代理JAR(与应用程序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");
}
Run Code Online (Sandbox Code Playgroud)
示例清单:
Manifest-Version: 1.0
Premain-Class: InstrumentHook
Run Code Online (Sandbox Code Playgroud)
然后,应用程序将引用生成的JAR,并-javaagent在启动应用程序时在命令行(使用选项)上指定.它可能在不同的ClassLoaders中加载两次,但这不是问题,因为系统Properties是一个单进程单例.
示例应用程序类
public class Main {
public static void main(String[] args) {
Instrumentation inst = InstrumentHook.getInstrumentation();
for (Class<?> clazz: inst.getAllLoadedClasses()) {
System.err.println(clazz.getName());
}
}
}
Run Code Online (Sandbox Code Playgroud)