Summary
initalizeClassloader() constructs a fresh RemoteResourcesClassLoader (a URLClassLoader) for every mojo execution and never closes it.
src/main/java/org/apache/maven/plugin/resources/remote/AbstractProcessRemoteResourcesMojo.java:865-875
private ClassLoader initalizeClassloader(List<File> artifacts) throws MojoExecutionException {
RemoteResourcesClassLoader cl = new RemoteResourcesClassLoader(null);
try {
for (File artifact : artifacts) {
cl.addURL(artifact.toURI().toURL());
}
return cl;
} catch (MalformedURLException e) {
throw new MojoExecutionException("Unable to configure resources classloader: " + e.getMessage(), e);
}
}
Impact
URLClassLoader holds open file handles (jar URL connections, caches). In long-running builds that execute this mojo many times (e.g. aggregator + forked lifecycles, or the documented double-execute pattern), the unclosed classloaders retain jar file descriptors until GC — the references are dropped after execute(), but not closed deterministically. Minor resource leak / handle retention.
Suggested fix
Call cl.close() when the classloader is no longer needed (after processResourceBundles, before restoring the original context classloader in execute()), or use try-with-resources around its lifetime. Note RemoteResourcesClassLoader.getResource intentionally delegates after findResource, so closing it is safe once processing completes.
Summary
initalizeClassloader()constructs a freshRemoteResourcesClassLoader(aURLClassLoader) for every mojo execution and never closes it.src/main/java/org/apache/maven/plugin/resources/remote/AbstractProcessRemoteResourcesMojo.java:865-875Impact
URLClassLoaderholds open file handles (jar URL connections, caches). In long-running builds that execute this mojo many times (e.g. aggregator + forked lifecycles, or the documented double-execute pattern), the unclosed classloaders retain jar file descriptors until GC — the references are dropped afterexecute(), but not closed deterministically. Minor resource leak / handle retention.Suggested fix
Call
cl.close()when the classloader is no longer needed (afterprocessResourceBundles, before restoring the original context classloader inexecute()), or use try-with-resources around its lifetime. NoteRemoteResourcesClassLoader.getResourceintentionally delegates afterfindResource, so closing it is safe once processing completes.