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

时间:2016-03-16 01:42:20

标签: java nashorn

我在1.8u60上使用Nashorn来创建模型对象以传回视图层(百日咳)。模型对象的一部分是一个有点大的字符串(不足以导致普通java中的任何问题)包含HTML。当尝试使用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)

...

谢谢,阿德里安

1 个答案:

答案 0 :(得分:1)

该行读取

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

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

这意味着您可能会在字符串上生成许多+个运算符的结果,这些ConsString对象的树被“展平”"立刻。线性化串联时间的权衡是需要保持这些ConsStrings,这需要超过字符串所需内存的两倍(超过两倍'因为ConsString对象拥有开销)。

解决此问题的一种方法是定期调用str.toString()。它似乎是一种无操作,但在内部它迫使连接树变平。尝试在某些时候将它介绍到您的代码中,看看它是否有帮助。