How can I list all classes loaded in a specific class loader

心不动则不痛 提交于 2019-11-26 17:37:04
finnw

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

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

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Vector<Class> classes =  (Vector<Class>) f.get(classLoader);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!