[
https://issues.apache.org/jira/browse/GROOVY-10773?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17611588#comment-17611588
]
Val E edited comment on GROOVY-10773 at 9/30/22 3:57 PM:
---------------------------------------------------------
Yes I believe it caches the "last hit" per class+method. The name of the field
'lastHitMethodHandleWrapper' supports that theory. So what you did above would
only retain the 10_000_000's iterations result. If however you have many
classes, methods that produce different results, or in our case many dynamic
user generated scripts, the leak is actually very severe.
_The assumption "in addition to the method handle it is also storing the
results of the method execution in
org.codehaus.groovy.vmplugin.v8.CacheableCallSite.latestHitMethodHandleWrapper"
is afaik wrong._
The heap dump image definitely shows a 5000 item map retained in the memory.
That could have just as easily been a million item map, with objects that
contain objects, that contain objects..... But you may be right that its
binding method arguments not the results. Although my code doesn't directly use
that map as an argument anywhere.
GROOVY-10772 does look very closely related. I also confirmed my problem is not
present in 4.0.2 and only appears in 4.0.3 and later, just like GROOVY-10772
describes.
_"... it should bind the argument classes, not the arguments.""_
was (Author: JIRAUSER296342):
Yes I believe it caches the "last hit" per class+method. The name of the field
'lastHitMethodHandleWrapper' supports that theory. So what you did above would
only retain the 10_000_000's iterations result. If however you have many
classes, methods that produce different results, or in our case many dynamic
user generated scripts, the leak is actually very severe.
_The assumption "in addition to the method handle it is also storing the
results of the method execution in
org.codehaus.groovy.vmplugin.v8.CacheableCallSite.latestHitMethodHandleWrapper"
is afaik wrong._
The heap dump image definitely shows a 5000 item map retained in the memory.
That could have just as easily been a million item map, with objects that
contain objects, that contain objects..... But you may be right that its
binding method arguments not the results. Although my code doesn't directly use
that map as an argument anywhere.
GROOVY-10772 does look very closely related.
_"... it should bind the argument classes, not the arguments.""_
> Groovy 4 memory leak due to presumptuous caching in
> org.codehaus.groovy.vmplugin.v8.CacheableCallSite
> -----------------------------------------------------------------------------------------------------
>
> Key: GROOVY-10773
> URL: https://issues.apache.org/jira/browse/GROOVY-10773
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 4.0.5
> Environment: Java 1.8, 11, 14
> Groovy 4.0.4, 4.0.5
> Reporter: Val E
> Priority: Major
> Attachments: MemLeakContainer.groovy, MemLeakItem.groovy,
> MemLeakTest.zip, TestScript.groovy, build.gradle, heapdump.png,
> image-2022-09-29-13-21-57-256.png, image-2022-09-30-11-01-13-234.png,
> image-2022-09-30-11-05-57-860.png, image-2022-09-30-11-24-49-168.png,
> visualvm_mem_sampler.png
>
>
> It looks like method handles caching is creating memory leaks in Groovy 4,
> because in addition to the method handle it is also storing the results of
> the method execution in
> *_org.codehaus.groovy.vmplugin.v8.CacheableCallSite.latestHitMethodHandleWrapper_*
>
> These cached method handles are not subject to garbage collection. Since the
> cached handler is also storing the result of the method execution, which can
> be any arbitrary object, it will also prevent the object itself and any of
> its transitive properties from being garbage collected. In our case the
> method execution often produced very large maps which caused our prod servers
> to very quickly bog down and need restarts.
>
> I have tried this with Groovy 4.0.4 and 4.0.5, as well as Java 1.8, 11, and
> 14; all produced this memory leaks.
> However Groovy 3.0.5 did *NOT* produce this leak.
>
> I have attached a very simple Gradle project. It produces 5000 MemoryLeakItem
> objects. Nothing special about these objects themselves, just easy to find in
> VisualVM and heap dumps. A container object that does some basic dynamic
> method resolution via a methodMissing and a TestScript to run and pause
> execution, so a heap dump can be created or VisualVM inspected.
>
> To reproduce the leak:
> Run TestScript.groovy, and when it pauses for keyboard input, check VisualVM
> or a heap dump.
> !image-2022-09-29-13-21-57-256.png|width=471,height=421!
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)