我在使用Java中的Groovy TemplateEngines而不在OOM中运行时遇到了一些麻烦。在创建许多不同的模板时,我觉得在堆上创建了很多脚本 - 然后它们永远不会是垃圾 集。
我使用java 8.使用-Xmx32M运行此代码时,可能有大约3000次迭代。之后是抛出OOM-Error。
这是我的代码:
import groovy.text.SimpleTemplateEngine;
import groovy.text.Template;
import groovy.text.TemplateEngine;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) throws Exception {
String groovy = "XX-${i}";
for (int i = 0; i < (1000000000); i++) {
TemplateEngine e = new SimpleTemplateEngine();
Template t = e.createTemplate(groovy);
Map<String, Object> binding = new HashMap<>();
binding.put("i", i);
String res = t.make(binding).toString();
if (i % 100 == 0) {
System.out.println("->" + res);
}
}
}
}
我也尝试了不同的变体和ClassLoaded - 但实际上结果总是相同的。由于我无法找到任何当前的问题,我想我错过了一些东西。
有人可以帮助启发我吗?
蒂诺
答案 0 :(得分:2)
以下是您的问题https://bugs.openjdk.java.net/browse/JDK-8037342。
每次解析器运行时,都会根据正在完成的解析次数创建一个新的唯一类。例如,一段时间后,类名看起来像
groovy.runtime.metaclass.SimpleTemplateScript4237MetaClass groovy.runtime.metaclass.SimpleTemplateScript4238MetaClass
一段时间后,ClassLoader的parallelLockMap
将填满堆,没有任何东西有资格成为GC&#39; d。这有点像OOM PermGen
错误。
答案 1 :(得分:0)
使用Apache Commons Text。快速高效的替代SimpleTemplateEngine的方法。
String templateString, Map binding;
StrSubstitutor sb = new StrSubstitutor(binding);
String value = sb.replace(templateString);
答案 2 :(得分:0)
我已经为这个问题苦苦挣扎了一段时间,现在我想出了解决方法。
只需在运行脚本后调用 clear 即可。
https://gist.github.com/jpozorio/38f26120e6346dfd74cecd7a147028aa