GroovyCategorySupport和" system"内存泄漏

时间:2016-09-11 08:57:06

标签: groovy memory-leaks jvm java-memory-leaks

当我运行以下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中的错误有关,我正在寻找一种方法来缓解这个问题:

  • 我的测试可能错了?怎么可能泄漏&#34;系统&#34;内存没有泄漏堆空间或permgen空间?
  • 是否已知&#34; Groovy和JRE 1.7之间的错误或不兼容?
  • 如何使用1.7 jre的groovy类别而不会遭受此内存泄漏?

修改

我可以通过调用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}}就够了。

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。

因此,您可以使用以下选项来解决内存泄漏问题:

  • 使用JRE 8(推荐)
  • 使用JRE 7u91 +
  • 在classpath中包含VMPluginFactory补丁