From b51be097958e11aeb21914331b7f0f7c69788169 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 13 Aug 2024 11:43:17 +0100 Subject: [PATCH] [core] Cache moduleName to URLs in ClasspathClassLoader --- .../internal/util/ClasspathClassLoader.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java index 009249fc61..6f23edb3eb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/ClasspathClassLoader.java @@ -20,6 +20,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; @@ -206,6 +207,8 @@ public class ClasspathClassLoader extends URLClassLoader { private static final String MODULE_INFO_SUFFIX = "module-info.class"; private static final String MODULE_INFO_SUFFIX_SLASH = "/" + MODULE_INFO_SUFFIX; + // this is lazily initialized on first query of a module-info.class + private Map moduleNameToModuleInfoUrls; @Nullable private static String extractModuleName(String name) { @@ -263,10 +266,10 @@ public class ClasspathClassLoader extends URLClassLoader { } } - private static class ModuleFinder extends ClassVisitor { + private static class ModuleNameExtractor extends ClassVisitor { private String moduleName; - protected ModuleFinder() { + protected ModuleNameExtractor() { super(Opcodes.ASM9); } @@ -281,21 +284,39 @@ public class ClasspathClassLoader extends URLClassLoader { } } - private URL findModule(Enumeration moduleInfoUrls, String moduleName) throws IOException { + private void collectAllModules() { + if (moduleNameToModuleInfoUrls != null) { + return; + } + + Map allModules = new HashMap<>(); + try { + Enumeration moduleInfoUrls = findResources(MODULE_INFO_SUFFIX); + collectModules(allModules, moduleInfoUrls); + + // also search in parents + moduleInfoUrls = getParent().getResources(MODULE_INFO_SUFFIX); + collectModules(allModules, moduleInfoUrls); + + LOG.debug("Found {} modules on auxclasspath", allModules.size()); + + moduleNameToModuleInfoUrls = Collections.unmodifiableMap(allModules); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void collectModules(Map allModules, Enumeration moduleInfoUrls) throws IOException { while (moduleInfoUrls.hasMoreElements()) { URL url = moduleInfoUrls.nextElement(); - ModuleFinder finder = new ModuleFinder(); + ModuleNameExtractor finder = new ModuleNameExtractor(); try (InputStream inputStream = url.openStream()) { ClassReader classReader = new ClassReader(inputStream); classReader.accept(finder, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); } - if (moduleName.equals(finder.getModuleName())) { - return url; - } + allModules.putIfAbsent(finder.getModuleName(), url); } - - return null; } @Override @@ -306,20 +327,9 @@ public class ClasspathClassLoader extends URLClassLoader { String moduleName = extractModuleName(name); if (moduleName != null) { - try { - Enumeration moduleInfoUrls = findResources(MODULE_INFO_SUFFIX); - URL moduleUrl = findModule(moduleInfoUrls, moduleName); - - // no match in this classloader, search in parents - if (moduleUrl == null) { - moduleInfoUrls = getParent().getResources(MODULE_INFO_SUFFIX); - moduleUrl = findModule(moduleInfoUrls, moduleName); - } - - return moduleUrl; - } catch (IOException e) { - throw new RuntimeException(e); - } + collectAllModules(); + assert moduleNameToModuleInfoUrls != null : "Modules should have been detected by collectAllModules()"; + return moduleNameToModuleInfoUrls.get(moduleName); } URL url = findResource(name);