You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Jonathan Baxter (Jira)" <ji...@apache.org> on 2022/06/14 02:46:00 UTC

[jira] [Updated] (GROOVY-10657) Generated code for overloaded assignment operator prevents garbage collection

     [ https://issues.apache.org/jira/browse/GROOVY-10657?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jonathan Baxter updated GROOVY-10657:
-------------------------------------
    Description: 
The groovy code 
{code:java}
obj["lhs"] = "rhs"{code}
ostensibly converts to 
{code:java}
obj.putAt("lhs","rhs")
{code}
if {{obj}} has the appropriate {{putAt}} method.

However , in the process of tracking down a memory leak, I discovered that assignment is not exactly equivalent to invocation of the {{putAt}} method. Specifically, the code generated by the compiler is equivalent to creating an additional temporary variable to hold the rhs of the assignment, and then invoking the {{putAt}} method with that temporary variable as its second argument:
{code:java}
String string = "rhs"
obj.putAt("lhs",string){code}
The problem with this is that since {{"rhs"}} now has a live reference ({{{}string{}}}), it is not eligible for garbage collection. 

In my particular use case, {{"rhs"}} is a very large object that I would like to be automatically garbage collected after the assignment is executed, but before the script has finished. But that means I have to use the underlying {{putAt}} method rather than the assignment operator, which rather negates the benefits of overloading the assignment operator.

One potential fix would be to simply null out any temporary variables constructed by the compiler, so that 
{code:java}
obj["lhs"] = "rhs"
{code}
 becomes
{code:java}
String string = "rhs" 
obj.putAt("lhs",string) 
string = null <----- "rhs" is now eligible for garbage-collection{code}

  was:
The groovy code 
{code:java}
a["1"] = "1"{code}


> Generated code for overloaded assignment operator prevents garbage collection
> -----------------------------------------------------------------------------
>
>                 Key: GROOVY-10657
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10657
>             Project: Groovy
>          Issue Type: Bug
>          Components: Compiler
>            Reporter: Jonathan Baxter
>            Priority: Major
>
> The groovy code 
> {code:java}
> obj["lhs"] = "rhs"{code}
> ostensibly converts to 
> {code:java}
> obj.putAt("lhs","rhs")
> {code}
> if {{obj}} has the appropriate {{putAt}} method.
> However , in the process of tracking down a memory leak, I discovered that assignment is not exactly equivalent to invocation of the {{putAt}} method. Specifically, the code generated by the compiler is equivalent to creating an additional temporary variable to hold the rhs of the assignment, and then invoking the {{putAt}} method with that temporary variable as its second argument:
> {code:java}
> String string = "rhs"
> obj.putAt("lhs",string){code}
> The problem with this is that since {{"rhs"}} now has a live reference ({{{}string{}}}), it is not eligible for garbage collection. 
> In my particular use case, {{"rhs"}} is a very large object that I would like to be automatically garbage collected after the assignment is executed, but before the script has finished. But that means I have to use the underlying {{putAt}} method rather than the assignment operator, which rather negates the benefits of overloading the assignment operator.
> One potential fix would be to simply null out any temporary variables constructed by the compiler, so that 
> {code:java}
> obj["lhs"] = "rhs"
> {code}
>  becomes
> {code:java}
> String string = "rhs" 
> obj.putAt("lhs",string) 
> string = null <----- "rhs" is now eligible for garbage-collection{code}



--
This message was sent by Atlassian Jira
(v8.20.7#820007)