我在 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()
。它似乎是一个无操作,但在内部它强制扁平化串联树。尝试在某个时候将其引入您的代码中,看看是否有帮助。