У меня есть проект Java 7, который запускает скрипты каждые n минут n процессами. Вот пример кода, который запускает скрипты.Обновление Groovy, вызывающее тонну мертвых GroovyClassLoaders в PermGen
ScheduledFuture scheduledFuture = scheduledService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try (GroovyClassLoader cl = new GroovyClassLoader()) {
// Load up reusable script modules in the class loader
Class scriptClass = cl.parseClass(scriptSource);
Foo script = optimizationClass.newInstance();
// Tell Groovy that we don't need class meta info
GroovySystem.getMetaClassRegistry().removeMetaClass(scriptClass);
script.run();
cl.clearCache();
} catch (IOException e) {
LOGGER.error("Failed to cleanup Groovy class loader, this will cause a memory leak", e);
}
}
}, 0, scheduledRun, TimeUnit.SECONDS);
scheduledFuture.get();
По какой-то причине с Groovy 2.1.7 нет никакой утечки памяти в Перми Бытии При обновлении до Groovy 2.3.8 или 2.2.0 Groovy, Пермь Gen продолжает получать заполненные мертвыми Groovy класса погрузчиков.
0x000000071ada2cd0 33 488160 0x000000071b2493c8 dead groovy/lang/[email protected] 0x00000007265883b8 33 488160 0x0000000725837270 dead groovy/lang/[email protected] 0x00000007157b5da0 26 370736 0x000000072326f468 live org/codehaus/groovy/runtime/callsite/[email protected] 0x000000071ada1fb0 32 423944 0x000000071af03a98 dead groovy/lang/[email protected] 0x0000000719d605b0 32 456520 0x000000071af04798 dead groovy/lang/[email protected] 0x0000000725b82500 0 0 0x000000072326f468 dead groovy/lang/[email protected] 0x00000007263eef80 34 532448 0x0000000726d5c678 dead groovy/lang/[email protected] 0x000000072687b3c8 33 485288 0x0000000726c36340 dead groovy/lang/[email protected] 0x0000000725d56db0 33 485288 0x000000072607bcc0 dead groovy/lang/[email protected]
Я жду, пока Full GC не происходит, но это, кажется, что любая версия после Groovy 2.2 причиняло Пермь Gen завалить. Я проверил примечания к выпуску между версией, на которой я находился, до обновленной версии, и я не заметил никаких изменений, которые могли бы вызвать это.
Я проверил здесь для подобных вопросов и попробовал несколько предложений, но не повезло. Любые идеи относительно причины?
Обновление:
Я сделал Diff на GrepCode на GroovyClassLoader с 2.1.7 до 2.2.0 и не было изменений. Я также взял файл дампа кучи при запуске приложения и не было никаких путей к корням GC для сильных ссылок.
Проблема, кажется, здесь:
Class scriptClass = cl.parseClass(scriptSource);
Foo script = scriptClass.newInstance();
Когда я не составляю сценарий, я получил 0 Groovy загрузчиков классов в Перми Ген Когда я компиляции сценария, но не запускайте его, я получаю Dead Groovy ClassLoaders.
Обновление:
Нашел код, вызывающий утечку.
Foo script = scriptClass.newInstance();
Не знаете, как это исправить, поскольку мне нужно создать новый экземпляр для запуска скрипта.
Разве Java 8 не устраняет проблемы PermGen? :) (на самом деле меня тоже интересует, почему это произойдет!) –
Java 8 заменила пространство PermGen на Metaspace, которое по умолчанию автоматически расширяет. Однако Java 8 ничего не делает о фактических утечках - вы все равно можете получить OutOfMemoryError: Metaspace. В случае, если вы хотите узнать, почему и как, не стесняйтесь ознакомиться с моей серией блога по теме: http://java.jiderhamn.se/2011/12/11/classloader-leaks-i-how -to-find-classloader-leaks-with-eclipse-memory-analyzer-mat/ –
Обновление до Java 8 сейчас не является жизнеспособным решением на данный момент.Также это не решит проблему, почему обновление Groovy вызывает эту утечку. – ColinMc