我们目前正在为我们的某个产品添加服务器端脚本功能。作为其中的一部分,我正在评估JSR 223脚本引擎。由于我们可能在服务器上运行大量脚本,因此我特别关注这些脚本引擎的内存使用情况。将Rhino(Apple JDK 1.6.0_65-b14-462-11M4609,Mac OS X 10.9.2)与Nashorn(Oracle JDK 1.8.0-b132)进行比较,每个ScriptEngine实例的内存使用量似乎存在巨大差异。
为了测试这个,我使用一个简单的程序,它会激活10个空白的ScriptEngine实例,然后阻止从stdin读取。然后我使用jmap进行堆转储(jmap -dump:format = b,file = heap.bin),然后在转储中搜索相关的脚本引擎实例:
import javax.script.*;
public class test {
public static void main(String...args) throws Exception {
ScriptContext context = new SimpleScriptContext();
context.setWriter(null);
context.setErrorWriter(null);
context.setReader(null);
ScriptEngine js[] = new ScriptEngine[10];
for (int i = 0; i < 10; ++i) {
js[i] = new ScriptEngineManager().getEngineByName("javascript");
js[i].setContext(context);
System.out.println(js[i].getClass().toString());
}
System.in.read();
}
}
在上下文中清空各种读取器/写入器字段的原因是因为我们不使用它们,并且Rhino的早期堆转储表明它们构成了每个实例开销的重要部分(并且似乎不是分享)。
在Eclipse MAT中分析这些堆转储然后我得到以下每个实例保留的堆大小:
Nashorn的规模是否会增加24倍?执行速度不是我们将要执行的脚本(主要是I / O绑定)的主要问题,因此我正在考虑将我们自己的Rhino副本用于Java 8 +。
答案 0 :(得分:0)
什么是 Nashorn?
Nashorn 是一个用于 JVM 的 JavaScript 引擎,随 Java 8 一起发布。Nashorn 包含一个嵌入式 JavaScript 解释器和一个命令行工具。 Nashorn 的目标是使用原生 JVM 用 Java 实现高性能的 JavaScript 运行时。使用 Nashorn,开发人员可以将 JavaScript 嵌入到 Java 应用程序中,还可以从 JavaScript 代码调用 Java 方法和类,从而在两种语言之间实现无缝集成。
为什么内存消耗高?
Nashorn 对象和属性图目前无法缩放到很多属性。使 PropertyMap 不可变的原因是允许通过比较 PropertyMap 引用来快速验证内联调用站点。这将导致 Nashorn 中的内存消耗很高。
一种解决方案是切换到pre-script-java-functions,因为在java服务器中它将具有用于特定任务和来自Nashorn引擎的java函数,您将调用该函数,它不会创建对象映射,并且它只会在 Java 中执行该函数并为您提供结果,因此内存消耗相对较低,而不是使用 JS 函数映射 Java 中的所有内容。这些类型的 pre-script-java-functions 用于 WSO2-Identity Server 自适应脚本功能。这是在 Nashorn 中处理高内存分配和内存消耗的一种方法。
答案 1 :(得分:-1)
https://seniorjava.wordpress.com也许此链接可以提供帮助。不确定你是否还在努力。