You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2026/07/09 04:15:40 UTC
(groovy) branch master updated (07adcb35b9 -> aa30a69065)
This is an automated email from the ASF dual-hosted git repository.
paulk-asert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
from 07adcb35b9 GROOVY-12134: @Delegate regression: fails to skip a final method inherited from a precompiled superclass
new 49fb716307 Close GroovyClassLoader created for one-off compilation
new aa30a69065 Close per-test GroovyClassLoader in contracts BaseTestClass
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../org/codehaus/groovy/ant/GenerateStubsTask.java | 58 ++++++++--------
.../main/java/org/codehaus/groovy/ant/Groovy.java | 4 ++
.../java/org/codehaus/groovy/ant/GroovycTask.java | 78 +++++++++++-----------
.../console/ui/AstNodeToScriptAdapter.groovy | 32 +++++----
.../contracts/tests/basic/BaseTestClass.groovy | 7 ++
5 files changed, 100 insertions(+), 79 deletions(-)
(groovy) 01/02: Close GroovyClassLoader created for one-off compilation
Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
paulk-asert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 49fb716307b969179ac9946b69dd41fc2e2644c5
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu Jul 9 13:36:45 2026 +1000
Close GroovyClassLoader created for one-off compilation
The Groovyc and GenerateStubs Ant tasks and the console AstNodeToScriptAdapter
each created a GroovyClassLoader for a single compilation and then discarded it
without closing, leaking the loader's open file handles. Wrap each so the loader
is closed once the compilation completes. The AST adapter only closes the loader
it creates itself, leaving a caller-supplied loader untouched.
---
.../org/codehaus/groovy/ant/GenerateStubsTask.java | 58 ++++++++--------
.../main/java/org/codehaus/groovy/ant/Groovy.java | 4 ++
.../java/org/codehaus/groovy/ant/GroovycTask.java | 78 +++++++++++-----------
.../console/ui/AstNodeToScriptAdapter.groovy | 32 +++++----
4 files changed, 93 insertions(+), 79 deletions(-)
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GenerateStubsTask.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GenerateStubsTask.java
index 87fc6c052c..25fa09ed06 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GenerateStubsTask.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GenerateStubsTask.java
@@ -25,6 +25,7 @@ import org.codehaus.groovy.control.Phases;
import org.codehaus.groovy.tools.javac.JavaStubCompilationUnit;
import java.io.File;
+import java.io.IOException;
/**
* Generates Java stubs from Groovy sources.
@@ -34,45 +35,46 @@ public class GenerateStubsTask extends CompileTaskSupport {
* Generates Java stubs for the configured source roots.
*/
@Override
- protected void compile() {
- GroovyClassLoader gcl = createClassLoader();
- JavaStubCompilationUnit cu = new JavaStubCompilationUnit(config, gcl, destdir);
+ protected void compile() throws IOException {
+ try (GroovyClassLoader gcl = createClassLoader()) {
+ JavaStubCompilationUnit cu = new JavaStubCompilationUnit(config, gcl, destdir);
- int count = 0;
+ int count = 0;
- for (String srcPath : src.list()) {
- File srcDir = getProject().resolveFile(srcPath);
- if (!srcDir.exists()) {
- throw new BuildException("Source directory does not exist: " + srcDir, getLocation());
- }
+ for (String srcPath : src.list()) {
+ File srcDir = getProject().resolveFile(srcPath);
+ if (!srcDir.exists()) {
+ throw new BuildException("Source directory does not exist: " + srcDir, getLocation());
+ }
- DirectoryScanner scanner = getDirectoryScanner(srcDir);
+ DirectoryScanner scanner = getDirectoryScanner(srcDir);
- log.debug("Including files from: " + srcDir);
+ log.debug("Including files from: " + srcDir);
- for (String includeName : scanner.getIncludedFiles()) {
- log.debug(" " + includeName);
+ for (String includeName : scanner.getIncludedFiles()) {
+ log.debug(" " + includeName);
- File file = new File(srcDir, includeName);
+ File file = new File(srcDir, includeName);
- if (isSource(includeName)) {
- cu.addSource(file);
- }
+ if (isSource(includeName)) {
+ cu.addSource(file);
+ }
- // Increment the count for each groovy src we found
- // TODO support config.getScriptExtensions()?
- if (includeName.endsWith(config.getDefaultScriptExtension())) {
- count++;
+ // Increment the count for each groovy src we found
+ // TODO support config.getScriptExtensions()?
+ if (includeName.endsWith(config.getDefaultScriptExtension())) {
+ count++;
+ }
}
}
- }
- if (count > 0) {
- log.info("Generating " + count + " Java stub" + (count > 1 ? "s" : "") + " to " + destdir);
- cu.compile(Phases.CONVERSION); // Generate the stubs
- log.info("Generated " + cu.getStubCount() + " Java stub(s)");
- } else {
- log.info("No sources found for stub generation");
+ if (count > 0) {
+ log.info("Generating " + count + " Java stub" + (count > 1 ? "s" : "") + " to " + destdir);
+ cu.compile(Phases.CONVERSION); // Generate the stubs
+ log.info("Generated " + cu.getStubCount() + " Java stub(s)");
+ } else {
+ log.info("No sources found for stub generation");
+ }
}
}
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
index c62eb29ca7..7d23896e5b 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
@@ -599,6 +599,10 @@ public class Groovy extends Java {
groovy.resetLoadedClasses();
groovy.getClassLoader().clearCache();
if (contextClassLoader || maven) thread.setContextClassLoader(savedLoader);
+ try {
+ classLoader.close();
+ } catch (IOException ignore) {
+ }
}
}
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GroovycTask.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GroovycTask.java
index 648246efbb..b6d6d78336 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GroovycTask.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/GroovycTask.java
@@ -27,6 +27,7 @@ import org.apache.tools.ant.util.SourceFileScanner;
import org.codehaus.groovy.control.CompilationUnit;
import java.io.File;
+import java.io.IOException;
/**
* Compiles Groovy source files.
@@ -52,7 +53,7 @@ public class GroovycTask
* Compiles the configured Groovy sources.
*/
@Override
- protected void compile() {
+ protected void compile() throws IOException {
Path path = getClasspath();
if (path != null) {
config.setClasspath(path.toString());
@@ -60,58 +61,59 @@ public class GroovycTask
config.setTargetDirectory(destdir);
- GroovyClassLoader gcl = createClassLoader();
- CompilationUnit compilation = new CompilationUnit(config, null, gcl);
+ try (GroovyClassLoader gcl = createClassLoader()) {
+ CompilationUnit compilation = new CompilationUnit(config, null, gcl);
- GlobPatternMapper mapper = new GlobPatternMapper();
- mapper.setFrom("*.groovy");
- mapper.setTo("*.class");
+ GlobPatternMapper mapper = new GlobPatternMapper();
+ mapper.setFrom("*.groovy");
+ mapper.setTo("*.class");
- int count = 0;
- String[] list = src.list();
+ int count = 0;
+ String[] list = src.list();
- for (String s : list) {
- File basedir = getProject().resolveFile(s);
+ for (String s : list) {
+ File basedir = getProject().resolveFile(s);
- if (!basedir.exists()) {
- throw new BuildException("Source directory does not exist: " + basedir, getLocation());
- }
+ if (!basedir.exists()) {
+ throw new BuildException("Source directory does not exist: " + basedir, getLocation());
+ }
- DirectoryScanner scanner = getDirectoryScanner(basedir);
- String[] includes = scanner.getIncludedFiles();
+ DirectoryScanner scanner = getDirectoryScanner(basedir);
+ String[] includes = scanner.getIncludedFiles();
- if (force) {
- log.debug("Forcefully including all files from: " + basedir);
+ if (force) {
+ log.debug("Forcefully including all files from: " + basedir);
- for (String include : includes) {
- File file = new File(basedir, include);
- log.debug(" " + file);
+ for (String include : includes) {
+ File file = new File(basedir, include);
+ log.debug(" " + file);
- compilation.addSource(file);
- count++;
- }
- } else {
- log.debug("Including changed files from: " + basedir);
+ compilation.addSource(file);
+ count++;
+ }
+ } else {
+ log.debug("Including changed files from: " + basedir);
- SourceFileScanner sourceScanner = new SourceFileScanner(this);
- File[] files = sourceScanner.restrictAsFiles(includes, basedir, destdir, mapper);
+ SourceFileScanner sourceScanner = new SourceFileScanner(this);
+ File[] files = sourceScanner.restrictAsFiles(includes, basedir, destdir, mapper);
- for (File file : files) {
- log.debug(" " + file);
+ for (File file : files) {
+ log.debug(" " + file);
- compilation.addSource(file);
- count++;
+ compilation.addSource(file);
+ count++;
+ }
}
}
- }
- if (count > 0) {
- log.info("Compiling " + count + " source file" + (count > 1 ? "s" : "") + " to " + destdir);
+ if (count > 0) {
+ log.info("Compiling " + count + " source file" + (count > 1 ? "s" : "") + " to " + destdir);
- compilation.compile();
- }
- else {
- log.info("No sources found to compile");
+ compilation.compile();
+ }
+ else {
+ log.info("No sources found to compile");
+ }
}
}
}
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
index 94752b740b..9f13c48a29 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
@@ -159,21 +159,27 @@ and [compilephase] is a valid Integer based org.codehaus.groovy.control.CompileP
def writer = new StringBuilderWriter()
def scriptName = 'script' + System.currentTimeMillis() + '.groovy'
GroovyCodeSource codeSource = new GroovyCodeSource(script, scriptName, '/groovy/script')
- CompilationUnit cu = new CompilationUnit((CompilerConfiguration) (config ?: CompilerConfiguration.DEFAULT), (CodeSource) codeSource.codeSource, (GroovyClassLoader) classLoader ?: new GroovyClassLoader(this.class.classLoader))
- cu.addPhaseOperation(new AstNodeToScriptVisitor(writer, showScriptFreeForm, showScriptClass), compilePhase)
- cu.addSource(codeSource.getName(), script)
+ boolean ownLoader = classLoader == null
+ GroovyClassLoader loader = (GroovyClassLoader) classLoader ?: new GroovyClassLoader(this.class.classLoader)
try {
- cu.compile(compilePhase)
- } catch (CompilationFailedException cfe) {
- writer.println 'Unable to produce AST for this phase due to earlier compilation error:'
- cfe.message.eachLine {
- writer.println it
+ CompilationUnit cu = new CompilationUnit((CompilerConfiguration) (config ?: CompilerConfiguration.DEFAULT), (CodeSource) codeSource.codeSource, loader)
+ cu.addPhaseOperation(new AstNodeToScriptVisitor(writer, showScriptFreeForm, showScriptClass), compilePhase)
+ cu.addSource(codeSource.getName(), script)
+ try {
+ cu.compile(compilePhase)
+ } catch (CompilationFailedException cfe) {
+ writer.println 'Unable to produce AST for this phase due to earlier compilation error:'
+ cfe.message.eachLine {
+ writer.println it
+ }
+ writer.println 'Fix the above error(s) and then press Refresh'
+ } catch (Throwable t) {
+ writer.println 'Unable to produce AST for this phase due to an error:'
+ writer.println t.getMessage()
+ writer.println 'Fix the above error(s) and then press Refresh'
}
- writer.println 'Fix the above error(s) and then press Refresh'
- } catch (Throwable t) {
- writer.println 'Unable to produce AST for this phase due to an error:'
- writer.println t.getMessage()
- writer.println 'Fix the above error(s) and then press Refresh'
+ } finally {
+ if (ownLoader) loader.close()
}
return writer.toString()
}
(groovy) 02/02: Close per-test GroovyClassLoader in contracts BaseTestClass
Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
paulk-asert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit aa30a6906577f66a707a6522ca67d7a233117b80
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu Jul 9 13:36:46 2026 +1000
Close per-test GroovyClassLoader in contracts BaseTestClass
BaseTestClass created a GroovyClassLoader in @BeforeEach but never closed it,
so every contracts test that extended it leaked a loader. Add an @AfterEach
that closes the loader, mirroring StubTestCase.
---
.../org/apache/groovy/contracts/tests/basic/BaseTestClass.groovy | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/subprojects/groovy-contracts/src/test/groovy/org/apache/groovy/contracts/tests/basic/BaseTestClass.groovy b/subprojects/groovy-contracts/src/test/groovy/org/apache/groovy/contracts/tests/basic/BaseTestClass.groovy
index 95a7c251b6..e1ceccafd6 100644
--- a/subprojects/groovy-contracts/src/test/groovy/org/apache/groovy/contracts/tests/basic/BaseTestClass.groovy
+++ b/subprojects/groovy-contracts/src/test/groovy/org/apache/groovy/contracts/tests/basic/BaseTestClass.groovy
@@ -21,6 +21,7 @@ package org.apache.groovy.contracts.tests.basic
import groovy.text.GStringTemplateEngine
import groovy.text.TemplateEngine
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter
+import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import static org.junit.jupiter.api.Assertions.assertTrue
@@ -39,6 +40,12 @@ class BaseTestClass {
loader = new GroovyClassLoader(getClass().getClassLoader())
}
+ @AfterEach
+ void tearDown() {
+ loader?.close()
+ loader = null
+ }
+
String createSourceCodeForTemplate(final String template, final Map binding) {
templateEngine.createTemplate(template).make(binding).toString()
}