Java 如何列出特定类加载器中加载的所有类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2681459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I list all classes loaded in a specific class loader
提问by Yaneeve
For debug reasons, and curiosity, I wish to list all classes loaded to a specific class loader.
出于调试原因和好奇心,我希望列出加载到特定类加载器的所有类。
Seeing as most methods of a class loader are protected, what is the best way to accomplish what I want?
鉴于类加载器的大多数方法都受到保护,完成我想要的最佳方法是什么?
Thanks!
谢谢!
采纳答案by finnw
Instrumentation.getInitiatedClasses(ClassLoader)
may do what you want.
Instrumentation.getInitiatedClasses(ClassLoader)
可以做你想做的。
According to the docs:
根据文档:
Returns an array of all classes for which loader is an initiating loader.
返回所有类的数组,其中 loader 是其启动加载器。
I'm not sure what "initiating loader" means though. If that does not give the right result try using the getAllLoadedClasses()
method and manually filtering by ClassLoader.
我不确定“启动加载器”是什么意思。如果这没有给出正确的结果,请尝试使用该getAllLoadedClasses()
方法并通过 ClassLoader 手动过滤。
How to get an instance of Instrumentation
如何获取实例 Instrumentation
Only the agent JAR (which is separate from the application JAR) can get an instance of the Instrumentation
interface. A simple way to make it available to the application is to create an agent JAR containing one class with a premain
method that does nothing but save a reference to the Instrumentation
instance in the system properties.
只有代理 JAR(与应用程序 JAR 分开)才能获得Instrumentation
接口的实例。使其对应用程序可用的一种简单方法是创建一个包含一个类的代理 JAR,该类的premain
方法除了Instrumentation
在系统属性中保存对实例的引用外什么也不做。
Example agent class:
示例代理类:
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");
}
Example manifest:
示例清单:
Manifest-Version: 1.0
Premain-Class: InstrumentHook
The resulting JAR must then be referenced by the application andspecified on the command line (with the -javaagent
option) when launching the application. It might be loaded twice in different ClassLoader
s, but that is not a problem since the system Properties
is a per-process singleton.
然后,生成的 JAR 必须由应用程序引用,并-javaagent
在启动应用程序时在命令行上指定(使用选项)。它可能会在不同的ClassLoader
s 中加载两次,但这不是问题,因为系统Properties
是每个进程的单例。
Example application class
示例应用程序类
public class Main {
public static void main(String[] args) {
Instrumentation inst = InstrumentHook.getInstrumentation();
for (Class<?> clazz: inst.getAllLoadedClasses()) {
System.err.println(clazz.getName());
}
}
}
回答by bestsss
Try this. It's a hackerish solution but it will do.
尝试这个。这是一个黑客解决方案,但它会做。
The field classes
in any classloader (under Sun's impl since 1.0) holds hard reference to the classes defined by the loader so they won't be GC'd. You can take a benefit from via reflection.
classes
任何类加载器中的字段(自 1.0 起在 Sun 的 impl 下)都包含对加载器定义的类的硬引用,因此它们不会被 GC 处理。您可以从反射中受益。
Field f = ClassLoader.class.getDeclaredField("classes");
f.setAccessible(true);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Vector<Class> classes = (Vector<Class>) f.get(classLoader);