Why does Java throw java.lang.OutOfMemoryError: Metaspace but there is plenty of free metaspace?
Why does Java throw java.lang.OutOfMemoryError: Metaspace but there is plenty of free 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,但在使用的元空间 23564Kb 左右的某个时间点抛出 OOM。
错误的调用堆栈是:
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
哇,我刚刚找到了答案。
问题是在我的应用程序中,我为每个生成的 Class 创建了一个单独的新 ClassLoader。我在我的示例应用程序中做了一个修改,将所有生成的 classes 放入一个 ClassLoader 之后,在可用元空间几乎为零时抛出 OOM。修复在这里 https://github.com/vlkv/java_metaspace_oom/commit/d6bcade51f79758e2413d1852c771f163392c294 分支 fix_of_the_problem
有人知道 java 进程中 class 加载器的限制是什么吗?以及如何增加它们?
也找到了这个
在我的应用程序中,我在运行时使用 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,但在使用的元空间 23564Kb 左右的某个时间点抛出 OOM。
错误的调用堆栈是:
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
哇,我刚刚找到了答案。 问题是在我的应用程序中,我为每个生成的 Class 创建了一个单独的新 ClassLoader。我在我的示例应用程序中做了一个修改,将所有生成的 classes 放入一个 ClassLoader 之后,在可用元空间几乎为零时抛出 OOM。修复在这里 https://github.com/vlkv/java_metaspace_oom/commit/d6bcade51f79758e2413d1852c771f163392c294 分支 fix_of_the_problem
有人知道 java 进程中 class 加载器的限制是什么吗?以及如何增加它们?
也找到了这个