Я пытаюсь найти обходной путь для ошибки JDK Nashorn JDK-8229011.
Я воспроизвел ошибку с помощью скрипта, указанного в сообщении об ошибке, и сделал несколько дампов кучи. Я использовал JProfiler и Eclipse Memory Analyzer, чтобы найти корень проблемы. Но я всегда оказываюсь на недоступных путях и не понимаю, почему объекты не собираются мусором. AFAIS нет никаких финализаторов, чтобы сохранить их живыми. Если я открою дамп кучи в JProfiler, не отключив полный сборщик мусора для дампа, JProfiler даже выбросит недостижимые объекты. Но сам GC не будет. Я тестировал G1 GC, но то же самое и с CMS.
Образец дампа можно получить за 1-2 минуты с любым JDK › 8, запустив следующий скрипт с настройками: -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
public class TestJsMemLeak
{
public static final class JsJavaUtil
{
private long counter = 0;
public long testFunc()
{
return counter++;
}
}
public static void main(final String[] args) throws Exception
{
System.setProperty("nashorn.args", "--no-java -doe -ot=false --language=es6 --no-deprecation-warning --lazy-compilation=false");
for (long i = 0; true; ++i)
{
final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
scriptEngine.put("JsJavaUtil", new JsJavaUtil());
scriptEngine.eval("for (var i = 0; i < 10; ++i) {\n" + " JsJavaUtil.testFunc();\n" + "}");
System.gc();
if (i % 100 == 0)
{
System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
}
}
}
}
Запуск этого приведет к дампу с недоступным java.lang.ClassValue$ClassValueMap размером около 6-7 МБ.
Я ищу подсказки, что поддерживает жизнь этих объектов.