我有一个使用Nashorn的应用程序。出于我的示例的目的,我创建了一个ScriptContext,我通过执行一些Javascript来创建一些全局变量,然后通过在紧密循环中调用NashornScriptEngine#eval(String, ScriptContext)
在一个线程中反复使用该上下文。我没有将结果存储在任何地方,据我所知,我的应用程序代码不会导致任何副作用。
使用默认的GC,这可以无限期地正常工作。但是,当我使用-XX:+UseConcMarkSweepGC
运行相同的应用程序时,性能会随着时间的推移而显着降低。程序启动时,运行1,000,000次迭代大约需要2分钟。但是2小时后,相同的1,000,000次迭代大约需要4分钟。它从那里开始变得更糟。
我还经常测试丢弃NashornScriptEngine实例和ScriptContext,完全从头开始。此时,我的应用程序没有引用上一次执行中的任何变量。这并没有改善这些性能问题。
知道发生了什么事吗?我需要使用-XX:+UseConcMarkSweepGC
运行,因为这只是一个较大的长期应用程序的一小部分。
我在下面的Java Mission Control中有一些截图(摘自Flight Recorder)。
谢谢!
在这里,我选择了两个GC,一个从录制开始,一个从最后开始。请注意“JNI弱参考”时间如何显着增加,“GC暂停”也是如此。
答案 0 :(得分:3)
有一个错误https://bugs.openjdk.java.net/browse/JDK-8177098。 你能尝试一下解决方法 - 每次都重新创建NashornScriptEngineFactory吗?
答案 1 :(得分:0)
正如您自己所说,它在JNI ref处理中花费了大量时间。默认情况下,这是单线程的。设置-XX:+ParallelRefProcEnabled
以使其并行运行。
由于您正在使用动态生成字节码的nashorn引擎,因此也可能是类卸载或缺少类的问题,但这在您的日志中并不明显。