防止Java Nashorn在动态创建映射时过度使用内存

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

本文关键字:内存 映射 Nashorn Java 动态 创建 防止      更新时间:2023-09-26

这段琐碎的代码,在使用Nashorn运行时,会导致完整的gc

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

通读Nashorn的实现,我相信每次添加一个对象(使用PropertyMap类)都会克隆一个对象,添加新键,将其作为弱引用链接到上一个版本的"历史",等等。

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

有什么办法可以避免吗?

你的分析是正确的,Nashorn对象和属性映射目前不能缩放到很多属性。使PropertyMap不可变的原因是允许通过比较PropertyMap引用来快速验证内联调用站点。

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

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

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

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