0
votes

I wrote a Java agent, with a instance that implements ClassFileTransformer's below method:

class MyTransformer { public byte[] transform(ClassLoader loader, String classNameWithSlash, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { return null; } }

In order to be able to retransform a loaded class, I used below method to add the above transformer:

inst.addTransformer(new MyTransformer(), true);

It functionally works, however, there is a problem:

When testing using Oracle JDK1.8.0_102 (on Linux 64bit), and enable tracing of class loading and unloading by adding below arguments to JVM startup arguments -XX:+TraceClassLoading -XX:+TraceClassUnloading. I can see trace logs for class loading when a inst.retransform(aClass) is invoked, e.g. [Loaded myapp.MyClass from __VM_RedefineClasses__]

This is fine for class loading, but when I retransform the same class again, I can see this 'loading' trace log again but can't see any trace related to 'unloading'.

So the problem is, if I call inst.retransform() to a certain number of times, the JVM crashes! When I increase the setting for -XX:MetaspaceSize, the number of calls I can make increases before the JVM crashes. These two numbers are highly correlated, .

So, the questions: Is this a JVM bug, or it is the agent developer's job to unload a class being transformed?

Note: The JVM crashes (or complains about out of memory in meta space) even if my transformer does not do any transformation by returning null.

1

1 Answers

0
votes

Classes loaded are default behavior when functionality of the classes are used but unloading cannot be performed similar way. Classes unloading are done by GC. GC performs some heuristics checks before unloading classes. This is not a bug. JVM is working as designed.