[
https://issues.apache.org/jira/browse/GROOVY-9329?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17469145#comment-17469145
]
Robin edited comment on GROOVY-9329 at 1/7/22, 2:18 AM:
--------------------------------------------------------
Hi, I found the patch Not Really Cached the compiled class.
If we run the next groovy script:
{code:java}
def gcl = new GroovyClassLoader()
def scriptText = 'def x = 1'
gcl.parseClass(scriptText)
def begin = [email protected]()
def clazz = [email protected]().iterator().next()
println clazz.toString() + ", hashCode=" + clazz.hashCode()
3.times { gcl.parseClass(scriptText) }
def end = [email protected]()
def clazz_2 = [email protected]().iterator().next()
println clazz_2.toString() + ", hashCode=" + clazz_2.hashCode()
println(end == begin)
println(clazz == clazz_2)
{code}
The result is:
{code:java}
class Script_281961721d66605f3d1f24d294f28232, hashCode=1976401987
class Script_281961721d66605f3d1f24d294f28232, hashCode=1201004240
true
false {code}
clazz != clazz_2, so it means that every time of calling
"parseClass(scriptText) ", script will be compiled again, then the new class
put to classCache to replacing the old one.
The fix is: Remove the "gcs.setCachable(false);" line of parseClass(text,
fileName) in GroovyClassLoader.java
{code:java}
public Class parseClass(final String text, final String fileName) throws
CompilationFailedException {
GroovyCodeSource gcs =
AccessController.doPrivileged((PrivilegedAction<GroovyCodeSource>) () -> new
GroovyCodeSource(text, fileName, "/groovy/script"));
gcs.setCachable(false); <----- Remove the line
return parseClass(gcs);
} {code}
Thanks.
was (Author: JIRAUSER283079):
Hi, I found the patch Not Really Cached the compiled class.
If we run the next groovy script:
{code:java}
def gcl = new GroovyClassLoader()
def scriptText = 'def x = 1'
gcl.parseClass(scriptText)def begin = [email protected]()
def clazz = [email protected]().iterator().next()
println clazz.toString() + ", hashCode=" + clazz.hashCode()
3.times { gcl.parseClass(scriptText) }
def end = [email protected]()
def clazz_2 = [email protected]().iterator().next()
println clazz_2.toString() + ", hashCode=" + clazz_2.hashCode()
println(end == begin)
println(clazz == clazz_2)
{code}
The result is:
{code:java}
class Script_281961721d66605f3d1f24d294f28232, hashCode=1976401987
class Script_281961721d66605f3d1f24d294f28232, hashCode=1201004240
true
false {code}
clazz != clazz_2, so it means that every time of calling
"parseClass(scriptText) ", script will be compiled again, then the new class
put to classCache to replacing the old one.
The fix is: Remove the "gcs.setCachable(false);" line of parseClass(text,
fileName) in GroovyClassLoader.java
{code:java}
public Class parseClass(final String text, final String fileName) throws
CompilationFailedException {
GroovyCodeSource gcs =
AccessController.doPrivileged((PrivilegedAction<GroovyCodeSource>) () -> new
GroovyCodeSource(text, fileName, "/groovy/script"));
gcs.setCachable(false); <----- Remove the line
return parseClass(gcs);
} {code}
Thanks.
> OOME raised while `parseClass(scriptText)`
> ------------------------------------------
>
> Key: GROOVY-9329
> URL: https://issues.apache.org/jira/browse/GROOVY-9329
> Project: Groovy
> Issue Type: Bug
> Reporter: Daniel Sun
> Assignee: Daniel Sun
> Priority: Critical
> Fix For: 3.0.0-rc-3
>
> Time Spent: 1h 20m
> Remaining Estimate: 0h
>
> Many groovy users have encountered the OOME while {{parseClass(scriptText)}}
> even if the {{scriptText}} has not been changed.
> The cause of the issue is the script file name is generated via
> {{System.currentTimeMillis()}}, so the script file name will change even if
> the script text is not changed. As a result, many class instances are created
> and cached in {{groovy.lang.GroovyClassLoader#classCache}}, the classes can
> not be GCed, which causes OOME.
> The solution is very simple, the script file name could be generated via md5,
> which will not change if the script text is not changed.
> {code:java}
> def gcl = new GroovyClassLoader()
> while (true) {
> gcl.parseClass('def x = 1')
> }
> {code}
> Error message:
> {code:java}
> java.lang.OutOfMemoryError: Compressed class space
> at ConsoleScript6.run(ConsoleScript6:4)
> at
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> {code}
--
This message was sent by Atlassian Jira
(v8.20.1#820001)