当Java Instrumentation多次重新转换类时,JVM崩溃/ OutOfMemory

时间:2016-08-25 13:16:12

标签: instrumentation agent javaagents

我编写了一个Java代理,其中一个实例在下面的方法中实现components.xml

ClassFileTransformer

为了能够重新转换已加载的类,我使用下面的方法添加上面的转换器:

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

它在功能上有效,但有一个问题

使用Oracle JDK1.8.0_102(在Linux 64位上)进行测试时,通过在JVM启动参数中添加以下参数来启用类加载和卸载的跟踪 inst.addTransformer(new MyTransformer(), true); 。调用-XX:+TraceClassLoading -XX:+TraceClassUnloading时,我可以看到类加载的跟踪日志,例如 inst.retransform(aClass)

这对于类加载很好,但是当我再次重新转换同一个类时,我可以看到这个' loading'再次跟踪日志,但无法看到与卸载相关的任何跟踪。

所以问题是,如果我将[Loaded myapp.MyClass from __VM_RedefineClasses__]调用一定次数,JVM崩溃!当我增加inst.retransform()的设置时,我可以在JVM崩溃之前增加调用次数。这两个数字高度相关,。

那么,问题这是一个JVM错误,还是代理开发人员卸载正在转换的类的工作?

注意:即使我的变换器没有通过返回-XX:MetaspaceSize进行任何转换,JVM也会崩溃(或抱怨元空间内存不足)。

1 个答案:

答案 0 :(得分:0)

当使用类的功能但是无法以类似的方式执行卸载时,加载的类是默认行为。卸载类由GC完成。 GC在卸载类之前执行一些启发式检查。这不是一个错误。 JVM正在按设计工作。