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() }
