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 <[email protected]>
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()
     }

Reply via email to