Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

How to get an application class loader in Java Agent method

In Java Agent method, such as premain() or agentmain(), class loader is system classloader, not application class loader.

If you intent to change bytecode of class loaded by application class loader, you will need an application class loader.

To get this, I think there is only one way. Get from Instrument API, as shown below.

public static void agentmain(String agentArgs, Instrumentation inst) throws Exception {
  Class[] classArray = inst.getAllLoadedClasses();
}

getAllLoadedClasses() returns an array of all classes currently loaded by the JVM. So, we need to seek the application class loader from these.

Map<String, Class> classMap = Arrays
                .stream(
                   inst
                     .getAllLoadedClasses()
                )
                .collect(
                  Collectors
                    .toMap(
                      c -> c.getName(), c -> c, (c1, c2) -> c1
                    )
                );

String target = "com.example.HelloWorld";
ClassLoader classLoader = classMap.get(target).getClassLoader();

It works well, but Agent class need to know the application class name. Is this okay?