[
https://issues.apache.org/jira/browse/GROOVY-8113?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18135283#comment-18135283
]
ASF GitHub Bot commented on GROOVY-8113:
----------------------------------------
daniellansun opened a new pull request, #3109:
URL: https://github.com/apache/groovy/pull/3109
## GROOVY-8113: stop retaining generated script class names in parent class
loaders
Repeated evaluation through `GroovyShell`, `GroovyScriptEngine` and the
template engines asked parallel-capable parent loaders for BeanInfo, Customizer
and MetaClass companions that are not present. Those loaders keep every
requested name. Skip companions that cannot be resolved, and do not delegate an
inner-class name that no parent can define.
### Jira
https://issues.apache.org/jira/browse/GROOVY-8113
### Testing
- `bugs.Groovy8113`
- `groovy.text.Groovy8113`
- `:lintGate` and `:groovy-templates:lintGate`
> Groovy script/template engine produce memory leak
> --------------------------------------------------
>
> Key: GROOVY-8113
> URL: https://issues.apache.org/jira/browse/GROOVY-8113
> Project: Groovy
> Issue Type: Bug
> Components: groovy-templates, GroovyScriptEngine
> Affects Versions: 2.4.8
> Environment: Groovy 2.4.8, Oracle Java JDK 8u121
> Reporter: Artyom Kravchenko
> Priority: Critical
> Attachments: merged_path.png, object_explorer.png
>
>
> There is a simple way to produce OutOfMemoryException if run infinite
> numbers of groovy scripts or evaluate groovy templates.
> Simple test to reproduce a memory leak(run groovy script and make template
> inside the script):
> set max heap size: -Xmx7m
> {code:java}
> import javax.script.*;
> import java.util.HashMap;
> import java.util.Map;
> public class OutOfMemoryTest {
> private static String TEMPLATE = "Dear ${fullName} please go away at
> ${time}";
> private static String SCRIPT = "def run(args) {\n" +
> "def bindings = ['fullName' : 'Ali Baba', 'time' : new Date()]\n"
> +
> "println
> args.templateEngine.createTemplate(args.template).make(bindings).toString()\n"
> +
> "}";
> public static void main(String... args) {
> //
> GroovySystem.getMetaClassRegistry().getMetaClassCreationHandler().setDisableCustomMetaClassLookup(true);
> while(true) {
> ScriptEngineManager engineManager = new ScriptEngineManager();
> ScriptEngine engine = engineManager.getEngineByName("groovy");
> try {
> engine.eval(SCRIPT);
> } catch (ScriptException e) {
> throw new RuntimeException(e);
> }
> groovy.text.SimpleTemplateEngine templateEngine = new
> groovy.text.SimpleTemplateEngine();
> Invocable inv = (Invocable) engine;
> Map<String, Object> params = new HashMap<>();
> params.put("template", TEMPLATE);
> params.put("templateEngine", templateEngine);
> Object[] runArgs = { params };
> try {
> inv.invokeFunction("run", runArgs);
> } catch (ScriptException | NoSuchMethodException e) {
> e.printStackTrace();
> }
> }
> }
> }
> {code}
> The main cause of issue is Java class loader. Two instances:
> sun.misc.Launcher.AppClassLoader and sun.misc.Launcher.ExtClassLoader
> (parent for first one), each of them has a strong reference:
> {code:java}
> ConcurrentHashMap<String, Object> parallelLockMap
> {code}
> It collects all loaded classes (and never releases their) for application
> including newly created script/template classes.
> The main reason of introduction of this reference described here:
> https://blogs.oracle.com/dholmes/entry/parallel_classloading_revisited_fully_concurrent
> For each iteration of my test I see that parallelLockMap grows with 6 new
> entries:
> {code:java}
> groovy.runtime.metaclass.Script94MetaClass
> Script94BeanInfo
> Script94Customizer
> groovy.runtime.metaclass.SimpleTemplateScript94MetaClass
> SimpleTemplateScript94BeanInfo
> SimpleTemplateScript94Customizer
> {code}
> See memory snapshots(attached): objects_explorer, merged_path.
> I have found a partial solution of the issue, if I add this code line to my
> test:
> {code:java}
>
> GroovySystem.getMetaClassRegistry().getMetaClassCreationHandler().setDisableCustomMetaClassLookup(true);
> {code}
> I see that classes like:
> {code:java}
> groovy.runtime.metaclass.Script94MetaClass
> groovy.runtime.metaclass.SimpleTemplateScript94MetaClass
> {code}
> goes away (groovy engine don't ask ClassLoader to find this classes on class
> path therefore such classes are not collected by ClassLoader) but classes
> like
> {code:java}
> Script94BeanInfo
> Script94Customizer
> SimpleTemplateScript94BeanInfo
> SimpleTemplateScript94Customizer
> {code}
> still has affect on memory.
> Dear developers, could you please point me any advice/workarounds for this
> issue. It will be fine to get rig this issue in future releases.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)