[
https://issues.apache.org/jira/browse/GROOVY-10773?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17611646#comment-17611646
]
Val E commented on GROOVY-10773:
--------------------------------
Here is a standalone script that demonstrates the problem further, structured
closer to your code. And shows how its retaining the last hit per
method+class. There are two differently named methods getItems and getItems2
and they both produce 10000 new objects in the MemLeakContainer2 class. Loop 10
times create a new container object, and call both methods once. VisualVM shows
20000 items retained in memory at the end, not being GC'd, 10000 items from
getItems() and 10000 items from getItems2()
!image-2022-09-30-11-05-57-860.png|width=399,height=264!
{code:java}
class MemLeakItem2 {
String name = "I take up memory space"
Double value = Math.random();
}
class MemLeakContainer2 {
/**create and return 10000 new items in a map**/
Map getItems(){
Map result =[:]
for(int i=0; i<10000;i++){
MemLeakItem2 item = new MemLeakItem2()
result.put(item.value, item)
}
return result
}
/**create and return 10000 new items in a map,same as above but different
method name**/
Map getItems2(){
Map result =[:]
for(int i=0; i<10000;i++){
MemLeakItem2 item = new MemLeakItem2()
result.put(item.value, item)
}
return result
}
}
10.times{
def container = new MemLeakContainer2()
container.getItems()
container.getItems2()
container = null
}
println "Execution paused check heap for MemLeakItem objects"
def input = System.in.newReader().readLine(){code}
> 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, 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)