当我运行以下JUnit测试时,java进程的内存不断增加。几个小时后,它使用超过2go。但是,当我使用jvisualvm时,堆和permgen大小是稳定的,我没有看到任何泄漏。测试使用-Xmx32m
public class TestCat {
public static class A { }
@Test
public void testCategory() {
for(;;) {
GroovyCategorySupport.use(A.class, new Closure<Object>(null) {
public Object call() { return null; }
});
}
}
}
我已经使用Groovy 2.4.7,Windows和JRE1.7_80,MacOS和JRE1.7_60进行了测试。 我无法使用MacOS和JRE 1.8.0_91
重现此错误我认为这与JRE1.7中的错误有关,我正在寻找一种方法来缓解这个问题:
修改
我可以通过调用VMPluginFactory.getPlugin().invalidateCallSites()
来重现这个错误,public class TestSwitchPoint {
@Test
public void testSP() {
SwitchPoint switchPoint = new SwitchPoint();
for(;;) {
SwitchPoint old = switchPoint;
switchPoint = new SwitchPoint();
SwitchPoint.invalidateAll(new SwitchPoint[]{old});
}
}
}
转换为这个&#34;纯java&#34;单元测试:
new SwitchPoint()
事实上,只有{{1}}就够了。
答案 0 :(得分:2)
是的,JRE中存在错误。 JVM内部发生本机内存泄漏:
paddingEnd
这是MemberNameTable的一个已知问题:JDK-8152271。遗憾的是,它仅在JDK 9中得到修复。幸运的是,由于在JDK-8050166中完成了MethodHandles重构,因此在JDK 8上看不到您的问题。虽然仍然存在MemberNameTable probem,但(VM)
- os::malloc(unsigned long, unsigned short, unsigned char*)
- CHeapObj<(unsigned short)1792>::operator new(unsigned long, unsigned char*)
- JNIHandleBlock::allocate_block(Thread*)
- JNIHandleBlock::allocate_handle(oopDesc*)
- JNIHandles::make_weak_global(Handle)
- instanceKlass::add_member_name(int, Handle)
- MethodHandles::init_method_MemberName(Handle, methodOopDesc*, bool, KlassHandle)
- MethodHandles::init_method_MemberName(Handle, CallInfo&, Thread*)
- MethodHandles::resolve_MemberName(Handle, KlassHandle, Thread*)
- MHN_resolve_Mem
(JAVA)
- java.lang.invoke.MethodHandleNatives.resolve(MemberName, Class)
- java.lang.invoke.MemberName$Factory.resolve(byte, MemberName, Class)
- java.lang.invoke.MemberName$Factory.resolveOrNull(byte, MemberName, Class)
- java.lang.invoke.DirectMethodHandle.maybeRebind(Object)
- java.lang.invoke.DirectMethodHandle.bindReceiver(Object)
- java.lang.invoke.CallSite.makeDynamicInvoker()
- java.lang.invoke.MutableCallSite.dynamicInvoker()
- java.lang.invoke.SwitchPoint.<init>()
- Test.main(java.lang.String[])
不再创建新的MemberNames。后一个修复程序也被移植到JDK 7u91。
如果Groovy运行时检测到Java 7+,则它使用MethodHandles。您可以通过修补VMPluginFactory
来使用Java 6插件来解决此问题。这是patch。如果在Groovy库之前包含在类路径中,它将强制Groovy运行时使用与Java 6兼容的VMPlugin。
因此,您可以使用以下选项来解决内存泄漏问题: