防止 Java Nashorn 在动态创建地图时过度占用内存

Preventing Java Nashorn from super excessive memory usage when dynamically creating a map

这段微不足道的代码,当 运行 Nashorn 时,会导致完整的 GC

var x = {}; 
for (var i = 0; i < 10000; i++) { 
  var key = "key-" + i; 
  x[key] = i; 
} 

通读 Nashorn 实现,我相信每次添加对象(使用 PropertyMap class)都会克隆一个对象,添加新键,将其链接到先前版本的 "history" 作为弱对象参考,等等等等。

这使得上面的代码在内存和时间上都是二次的。

有什么办法可以避免吗?

您尝试过使用原型吗? 我不确定(没有与 Nashorn 合作),但也许这可以帮助你:

var x = function() {};
for (var i = 0; i < 10000; i++) { 
  var key = "key-" + i; 
  x.prototype[key] = i; 
} 
console.log(new x());

您的分析是正确的,Nashorn 对象和 属性 地图当前无法扩展到很多属性。使 PropertyMap 不可变的原因是允许通过比较 PropertyMap 引用来快速验证内联调用站点。

一种解决方案是在属性数量超过某个阈值时切换到每个 ScriptObject,可变 属性 映射。我们可能会在 Nashorn 的未来版本中实现这一点,但我现在不能做出任何承诺。

作为解决方法,您可以使用 Java 映射来存储大量键值对。此外,在 JDK 9 中,Nashorn 将获得一些 ECMAScript 6 功能,其中包括新的 Map、Set、WeakMap 和 WeakSet 集合。