为什么Java抛出java.lang.OutOfMemoryError:Metaspace但是有很多免费的元空间?

时间:2016-12-07 07:58:19

标签: java out-of-memory metaspace

在我的应用程序中,我使用javassist库在运行时创建了许多java类。在某些时候抛出java.lang.OutOfMemoryError: Metaspace但是java进程监视(基于java.lang.management.MemoryPoolMXBean)报告有足够的空闲元空间。这是为什么?以及如何使用100%的元空间内存池?

我创建了一个可以重现问题的最小应用程序https://github.com/vlkv/java_metaspace_oom

下载它,cd到项目目录然后执行' ant run'。在这个应用程序中,我设置了-XX:MaxMetaspaceSize = 100m,但在某个点上抛出了OOM,大约使用了23564Kb的元空间。

错误的调用堆栈是:

javassist.CannotCompileException: by java.lang.OutOfMemoryError: Metaspace
    at javassist.ClassPool.toClass(ClassPool.java:1170)
    at javassist.CtClass.toClass(CtClass.java:1316)
    at com.tradingview.Main.generateRandomClass(Main.java:53)
    at com.tradingview.Main.main(Main.java:24)
Caused by: java.lang.OutOfMemoryError: Metaspace
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at javassist.ClassPool.toClass2(ClassPool.java:1183)
    at javassist.ClassPool.toClass(ClassPool.java:1164)
    ... 3 more

1 个答案:

答案 0 :(得分:-1)

哇,我刚刚找到答案。 问题是在我的应用程序中,我为每个生成的类创建一个单独的新ClassLoader。我在我的示例应用程序中做了一个修改,它将所有生成的类放到一个ClassLoader中,之后,当自由元空间几乎为零时,OOM被抛出。此修复程序位于https://github.com/vlkv/java_metaspace_oom/commit/d6bcade51f79758e2413d1852c771f163392c294分支fix_of_the_problem

有人知道java进程中类加载器的限制是什么?以及如何增加它们?

还找到了Why MetaSpace Size is twice as big as Used MetaSpace?