Почему Java выбрасывает java.lang.OutOfMemoryError: Metaspace, но есть много свободного метапространства?
В моем приложении я создаю много классов Java во время выполнения с библиотекой Javassist. В какой-то момент java.lang.OutOfMemoryError: Metaspace
выбрасывается, но мониторинг процесса Java (основанный на java.lang.management.MemoryPoolMXBean) сообщает, что имеется большое количество свободного метапространства. Это почему? А как использовать 100% пула памяти метаскала?
Я создал минимальное приложение, которое воспроизводит проблему https://github.com/vlkv/java_metaspace_oom
Загрузите его, перейдите в директорию проекта и выполните команду ant run. В этом приложении я установил -XX:MaxMetaspaceSize=100 м, но OOM выбрасывается в какой-то момент около 23564 КБ используемого метапространства.
Стек вызовов ошибки:
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
2 ответа
Вау, я только что нашел ответ. Проблема в том, что в моем приложении я создаю отдельный новый ClassLoader для каждого сгенерированного класса. Я сделал модификацию в моем примере приложения, которая помещает все сгенерированные классы в один ClassLoader, и после этого OOM выбрасывается в тот момент, когда свободное метапространство почти равно нулю. Исправление здесь https://github.com/vlkv/java_metaspace_oom/commit/d6bcade51f79758e2413d1852c771f163392c294 филиал fix_of_the_problem
Кто-нибудь знает о том, каковы ограничения для загрузчиков классов в процессе Java? И как их увеличить?
Также нашел это Почему MetaSpace Size в два раза больше, чем Используемое MetaSpace?
добавьте эту строку в свои свойства gradle org.gradle.jvmargs=-Xmx1536m