如何列出特定类加载器中加载的所有类

发布于 2024-08-29 11:37:02 字数 95 浏览 3 评论 0原文

出于调试原因和好奇心,我希望列出加载到特定类加载器的所有类。

鉴于类加载器的大多数方法都受到保护,那么完成我想要的事情的最佳方法是什么?

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

走过海棠暮 2024-09-05 11:37:02

试试这个。这是一个黑客解决方案,但它可以。

任何类加载器中的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);

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.

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

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Vector<Class> classes =  (Vector<Class>) f.get(classLoader);
街道布景 2024-09-05 11:37:02

Instrumentation.getInitiatedClasses(ClassLoader) 可能会做你想做的事。

根据文档:

返回加载程序作为启动加载程序的所有类的数组。

我不确定“启动加载程序”是什么意思。如果这没有给出正确的结果,请尝试使用 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");

}

清单示例:

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());
        }
    }
}

Instrumentation.getInitiatedClasses(ClassLoader) may do what you want.

According to the docs:

Returns an array of all classes for which loader is an initiating 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.


How to get an instance of 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.

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 and specified on the command line (with the -javaagent option) when launching the application. It might be loaded twice in different ClassLoaders, but that is not a problem since the system Properties is a per-process singleton.

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());
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文