Java Groovy模板引擎和OutOfMemory。可能的内存泄漏?

Java Groovy模板引擎和OutOfMemory。可能的内存泄漏?,java,groovy,Java,Groovy,我在Java中使用Groovy TemplateEngines而不在OOM中运行时遇到了一些问题。在我看来,当创建许多不同的模板时,堆上创建了许多脚本,这些脚本永远不会是垃圾 收集 我使用Java8。当使用-Xmx32M运行此代码时,大约有3000次迭代。然后抛出一个OOM错误 这是我的密码: import groovy.text.SimpleTemplateEngine; import groovy.text.Template; import groovy.text.TemplateEngin

我在Java中使用Groovy TemplateEngines而不在OOM中运行时遇到了一些问题。在我看来,当创建许多不同的模板时,堆上创建了许多脚本,这些脚本永远不会是垃圾 收集

我使用Java8。当使用-Xmx32M运行此代码时,大约有3000次迭代。然后抛出一个OOM错误

这是我的密码:

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);
            }
        }
    }
}
导入groovy.text.SimpleTemplateEngine;
导入groovy.text.Template;
导入groovy.text.TemplateEngine;
导入java.util.HashMap;
导入java.util.Map;
公开课考试{
公共静态void main(字符串[]args)引发异常{
字符串groovy=“XX-${i}”;
对于(int i=0;i<(100000000);i++){
TemplateEngine=新的SimpleTemplateEngine();
模板t=e.createTemplate(groovy);
映射绑定=新的HashMap();
绑定。放入(“i”,i);
String res=t.make(binding.toString();
如果(i%100==0){
系统输出打印项次(“->”+res);
}
}
}
}
我还尝试了不同的变体和类加载,但本质上结果总是一样的。因为我找不到任何当前的问题,我想我遗漏了一些东西

谁能帮我开导一下吗

蒂诺这是你的问题

每次解析器运行时,它都会根据正在执行的解析数量创建一个新的唯一类。例如,一段时间后,类名看起来像

groovy.runtime.metaclass.SimpleTemplateScript4237元类 groovy.runtime.metaclass.SimpleTemplateScript4238元类


一段时间后,类加载器的
parallelLockMap
将填充堆,并且没有任何内容符合GC的条件。这有点像一个
OOM PermGen
错误。

使用apachecommons文本。SimpleTemplateEngine的快速高效替代品

String templateString, Map binding;
StrSubstitutor sb = new StrSubstitutor(binding);
String value = sb.replace(templateString);

我与这个问题斗争了一段时间,现在我想出了解决办法

运行脚本后只需调用clear


为了好玩,试着运行
System.gc()
。我见过线程本地创建内存不足的奇怪行为,奇怪的是这迫使GC。我只是尝试了一下——正如我所怀疑的那样,它并没有改变这种行为。事实上,我正在一个长时间运行的应用程序中使用TemplateEngine,因此GC经常运行。现在尝试一下,迭代次数>10000次,没有错误。除了
-Xmx32M
,您还有其他参数吗?还有,您使用的是哪一版本的groovy模板?噢,是32000引起的,我来看看堆。达到的
GC开销限制是一种非常特殊的OOM类型,这意味着一些资源没有被取消引用。我添加的相当小的32M堆只是为了得到一个相当快的错误,因此不必等待数小时错误发生。我使用的是OracleJDK1.8_91——如果有任何问题的话。但我也认为我应该“关闭”有些东西。是的-我在堆转储中看到过这些类。你有什么建议或提示如何纠正这种情况吗?我看到的唯一解决方案是创建自己的
类加载器的实例,并允许它在运行模板后进行GC。我已经尝试过使用GroovyClassLoader的实例,但没有根本改变这种行为。当我在Groovy中查看模板类的源代码时,我认为他们正在尝试这样做。无论如何,谢谢你的努力。很抱歉,但是你运气不好。您需要自己派生一个实现,并更改为使用您想要的类加载器。