[ https://issues.apache.org/jira/browse/GROOVY-9742?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17939420#comment-17939420 ]
ASF GitHub Bot commented on GROOVY-9742: ---------------------------------------- codecov-commenter commented on PR #2168: URL: https://github.com/apache/groovy/pull/2168#issuecomment-2763568264 ## [Codecov](https://app.codecov.io/gh/apache/groovy/pull/2168?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report All modified and coverable lines are covered by tests :white_check_mark: > Project coverage is 68.8651%. Comparing base [(`ae138bc`)](https://app.codecov.io/gh/apache/groovy/commit/ae138bc5e1478fa20263e295021b8c656b88ea11?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) to head [(`df8235a`)](https://app.codecov.io/gh/apache/groovy/commit/df8235a9403ef9ca32caa7c3a180aea27c0b19ce?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache). > Report is 1 commits behind head on master. <details><summary>Additional details and impacted files</summary> [](https://app.codecov.io/gh/apache/groovy/pull/2168?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) ```diff @@ Coverage Diff @@ ## master #2168 +/- ## ============================================= Coverage 68.8651% 68.8651% + Complexity 29524 29523 -1 ============================================= Files 1421 1421 Lines 113400 113400 Branches 19606 19606 ============================================= Hits 78093 78093 Misses 28756 28756 Partials 6551 6551 ``` | [Files with missing lines](https://app.codecov.io/gh/apache/groovy/pull/2168?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | | |---|---|---| | [src/main/java/groovy/lang/GroovyClassLoader.java](https://app.codecov.io/gh/apache/groovy/pull/2168?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Fgroovy%2Flang%2FGroovyClassLoader.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9ncm9vdnkvbGFuZy9Hcm9vdnlDbGFzc0xvYWRlci5qYXZh) | `72.8682% <100.0000%> (ø)` | | </details> <details><summary> :rocket: New features to boost your workflow: </summary> - :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems. - :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges. </details> > GroovyClassLoader.parseClass() StampedCommonCache.getAndPut() hang > ------------------------------------------------------------------ > > Key: GROOVY-9742 > URL: https://issues.apache.org/jira/browse/GROOVY-9742 > Project: Groovy > Issue Type: Bug > Components: groovy-runtime > Affects Versions: 3.0.5 > Environment: Java version AdoptOpenJDK (build 25.262-b10, mixed mode) > Gradle version 6.6.1 > Groovy version 3.0.5 > Reporter: Chiang Seng Chang > Priority: Major > Attachments: g3cl.tar.gz > > > We have an IDE-like app which allows our coders to develop groovy scripts and > classes. > Essentially, the coders would write groovy sources and test them in the app. > We made a CustomClassLoader which is created and destroyed for each test run, > so that the app need no be restarted every time there is code change. > In Groovy 3.0.5, the GroovyClassLoader's cache is refactored to use > StampedCommonCache, which does not support recursion. > This is the distilled simplified version of our CustomClassLoader: > {noformat} > public class CustomGroovyClassLoader extends ClassLoader { > public CustomGroovyClassLoader(ClassLoader parent) { > super(parent); > groovyClassLoader = new GroovyClassLoader(this); > } > private final File srcDir = new File("./src/main/groovy"); > private final GroovyClassLoader groovyClassLoader; > @Override > protected Class<?> loadClass(String name, boolean resolve) > throws ClassNotFoundException { > synchronized (getClassLoadingLock(name)) { > Class<?> c = doFindClass(name); > if (c != null) { > if (resolve) { > resolveClass(c); > } > return c; > } > } > return super.loadClass(name, resolve); > } > private Class<?> doFindClass(String name) { > File classFile = new File(srcDir, name.replace('.', '/') + ".groovy"); > if (classFile.exists()) { > try { > System.out.println("PARSE\t: " + name); > Class<?> clz = groovyClassLoader.parseClass(classFile); > System.out.println("PARSED\t: " + clz); > return clz; > } > catch (IOException e) { > throw new RuntimeException(e); > } > } > return null; > } > } > {noformat} > Essentially, it uses the GroovyClassLoader.parseClass() for our test classes. > Here are the 2 classes to demonstrate the issue: > {noformat} > package foo > import groovy.transform.CompileStatic > @CompileStatic > interface Bar {} > {noformat} > {noformat} > package foo > import groovy.transform.CompileStatic > @CompileStatic > class Foo implements Bar {} > {noformat} > And the test harness: > {noformat} > package foo; > public class TestHarness { > public static void main(String[] args) throws Exception { > ClassLoader pcl = TestHarness.class.getClassLoader(); > CustomGroovyClassLoader ccl = new CustomGroovyClassLoader(pcl); > Class<?> clz = ccl.loadClass("foo.Foo"); > System.out.println("DONE\t: " + clz); > } > } > {noformat} > The harness attempt to load Foo.groovy. > The sequence of events would be: > # CustomClassLoader.loadClass(Foo) > # GroovyClassLoader.parseClass(Foo.groovy) > # sourceCache.getAndPut(Foo) > # Since Foo implements Bar, CustomClassLoader is called to load Bar > # which in turn calls GroovyClassLoader.parseClass(Bar.groovy) > # and sourceCache.getAndPut(Bar) > # Since StampedCommonCache does not support recursion, the loading hangs. > The attached project can be run using ./gradlew run to demonstrate the > hanging. > It seems to me that the GroovyClassLoader needs to support recursion for this > use case. > Or perhaps the CustomClassLoader is implemented wrongly? > Groovy 2.5.12 does not have this issue because its GroovyClassLoader uses > ConcurrentCommonCache. > > > -- This message was sent by Atlassian Jira (v8.20.10#820010)