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.