Nashorn OutOfMemoryError在构建大型js对象(字符串)时出错



我在 1.8u60 上使用 Nashorn 来创建模型对象以传递回视图层(百里香叶)。模型对象的一部分是一个包含HTML的有点大的字符串(不够大,不足以在纯java中引起任何问题)。当尝试使用ScriptObjectMirror方法将对象转换回Java时,我遇到了以下异常。更改最大堆大小似乎没有任何影响(从 900mb 更改为 1800mb,相同的错误)。我在网上找不到太多关于这个的信息,但是 Nashorn 对对象大小有什么限制吗?我现在要尝试最新的 1.8 JDK。

java.lang.OutOfMemoryError: Java heap space
    at jdk.nashorn.internal.runtime.ConsString.flatten(ConsString.java:105)
    at jdk.nashorn.internal.runtime.ConsString.flattened(ConsString.java:98)
    at jdk.nashorn.internal.runtime.ConsString.toString(ConsString.java:69)
    at jdk.nashorn.api.scripting.ScriptObjectMirror.wrap(ScriptObjectMirror.java:704)
    at jdk.nashorn.api.scripting.ScriptObjectMirror.wrapLikeMe(ScriptObjectMirror.java:721)
    at jdk.nashorn.api.scripting.ScriptObjectMirror.wrapLikeMe(ScriptObjectMirror.java:730)
    at jdk.nashorn.api.scripting.ScriptObjectMirror.access$300(ScriptObjectMirror.java:64)
    at jdk.nashorn.api.scripting.ScriptObjectMirror$13.call(ScriptObjectMirror.java:371)
    at jdk.nashorn.api.scripting.ScriptObjectMirror$13.call(ScriptObjectMirror.java:364)
    at jdk.nashorn.api.scripting.ScriptObjectMirror.inGlobal(ScriptObjectMirror.java:859)
    at jdk.nashorn.api.scripting.ScriptObjectMirror.entrySet(ScriptObjectMirror.java:364)

谢谢,阿德里安

那行是

        final char[] chars = new char[length];

因此,看起来确实没有足够的内存用于最终字符串。Nashorn 使用 ConsString 作为一种通过延迟串联直到使用结果来摊销串联成本的方法(大多数 JS 引擎使用此优化,否则例如,在一个循环中连接大量字符串将需要 O(n^2) 时间)。

这意味着,字符串上的许多+运算符的结果可能是一次"平展"的 ConsString 对象的树。线性化串联时间的权衡是需要保留这些 ConsString,这将需要两倍以上的字符串所需内存(超过 ConsString 对象自身开销的原因的两倍)。

解决此问题的一种方法是定期调用str.toString()。它似乎是一个无操作,但在内部它强制扁平化串联树。尝试在某个时候将其引入您的代码中,看看是否有帮助。

最新更新