diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java index 6b52a0a83c4..3ce3f79aa4b 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJMod.java @@ -15,6 +15,8 @@ import java.io.IOException; import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; import java.util.function.Predicate; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -26,14 +28,12 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; -import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; public class ClasspathJMod extends ClasspathJar { public static char[] CLASSES = "classes".toCharArray(); //$NON-NLS-1$ public static final String CLASSES_FOLDER = "classes/"; //$NON-NLS-1$ - private static int MODULE_DESCRIPTOR_NAME_LENGTH = IModule.MODULE_INFO_CLASS.length(); ClasspathJMod(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) { super(zipFilename, lastModified, accessRuleSet, externalAnnotationPath, true); @@ -80,8 +80,9 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa return null; } @Override - protected String readJarContent(final SimpleSet packageSet) { - String modInfo = null; + protected Set readPackageNames() { + final Set packageSet = new HashSet<>(); + packageSet.add(""); //$NON-NLS-1$ for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { ZipEntry entry = e.nextElement(); char[] entryName = entry.getName().toCharArray(); @@ -90,15 +91,10 @@ protected String readJarContent(final SimpleSet packageSet) { char[] folder = CharOperation.subarray(entryName, 0, index); if (CharOperation.equals(CLASSES, folder)) { char[] fileName = CharOperation.subarray(entryName, index + 1, entryName.length); - if (modInfo == null && fileName.length == MODULE_DESCRIPTOR_NAME_LENGTH) { - if (CharOperation.equals(fileName, IModule.MODULE_INFO_CLASS.toCharArray())) { - modInfo = new String(entryName); - } - } addToPackageSet(packageSet, new String(fileName), false); } } } - return modInfo; + return packageSet; } } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java index c2dce184cca..391895167eb 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java @@ -28,7 +28,9 @@ import java.util.Arrays; import java.util.Date; import java.util.Enumeration; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.jar.Manifest; @@ -49,7 +51,6 @@ import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; -import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.util.Util; @@ -57,72 +58,53 @@ public class ClasspathJar extends ClasspathLocation { final boolean isOnModulePath; -static class PackageCacheEntry { - WeakReference zipFile; - long lastModified; - long fileSize; - SimpleSet packageSet; - - PackageCacheEntry(ZipFile zipFile, long lastModified, long fileSize, SimpleSet packageSet) { - this.zipFile = new WeakReference<>(zipFile); - this.lastModified = lastModified; - this.fileSize = fileSize; - this.packageSet = packageSet; - } +private static record PackageCacheEntry( + WeakReference zipFile, + long lastModified, + long fileSize, + Set packageSet) { } -protected static Map PackageCache = new ConcurrentHashMap<>(); +protected static final Map packageCache = new ConcurrentHashMap<>(); -protected static void addToPackageSet(SimpleSet packageSet, String fileName, boolean endsWithSep) { +protected static void addToPackageSet(Set packageSet, String fileName, boolean endsWithSep) { int last = endsWithSep ? fileName.length() : fileName.lastIndexOf('/'); while (last > 0) { // extract the package name String packageName = fileName.substring(0, last); - if (packageSet.addIfNotIncluded(packageName) == null) + if (!packageSet.add(packageName)) { return; // already existed + } last = packageName.lastIndexOf('/'); } } -/** - * Calculate and cache the package list available in the zipFile. - * @return A SimpleSet with the all the package names in the zipFile. - */ -protected SimpleSet findPackageSet() { - PackageCacheEntry entry = PackageCache.compute(this.zipFilename, (zipFileName, cacheEntry) -> { +private Set getCachedPackageNames() { + PackageCacheEntry entry = packageCache.compute(this.zipFilename, (zipFileName, cacheEntry) -> { if(cacheEntry != null && cacheEntry.zipFile.get() == this.zipFile) { return cacheEntry; } long timestamp = this.lastModified(); if (cacheEntry != null && cacheEntry.lastModified == timestamp && cacheEntry.fileSize == this.fileSize) { - cacheEntry.zipFile = new WeakReference<>(this.zipFile); - return cacheEntry; + // cacheEntry.zipFile.get() != this.zipFile => update zipFile + return new PackageCacheEntry(new WeakReference<>(this.zipFile), cacheEntry.lastModified , cacheEntry.fileSize, cacheEntry.packageSet); } - final SimpleSet packageSet = new SimpleSet(41); - packageSet.add(""); //$NON-NLS-1$ - readJarContent(packageSet); - return new PackageCacheEntry(this.zipFile, timestamp, this.fileSize, packageSet); + return new PackageCacheEntry(new WeakReference<>(this.zipFile), timestamp, this.fileSize, Set.copyOf(readPackageNames())); }); return entry.packageSet; } -protected String readJarContent(final SimpleSet packageSet) { - String modInfo = null; +/** overloaded */ +protected Set readPackageNames() { + final Set packageSet = new HashSet<>(); + packageSet.add(""); //$NON-NLS-1$ for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { String fileName = e.nextElement().getName(); if (fileName.startsWith("META-INF/")) //$NON-NLS-1$ continue; - if (modInfo == null) { - int folderEnd = fileName.lastIndexOf('/'); - folderEnd += 1; - String className = fileName.substring(folderEnd, fileName.length()); - if (className.equalsIgnoreCase(IModule.MODULE_INFO_CLASS)) { - modInfo = fileName; - } - } addToPackageSet(packageSet, fileName, false); } - return modInfo; + return packageSet; } IModule initializeModule() { IModule mod = null; @@ -149,30 +131,33 @@ IModule initializeModule() { return mod; } -String zipFilename; // keep for equals -IFile resource; -ZipFile zipFile; -long lastModified; -long fileSize; -boolean closeZipFileAtEnd; -private SimpleSet knownPackageNames; +final String zipFilename; // keep for equals +final IFile resource; +/** lazy initialized, closed and reset to null in {@link #cleanup()} **/ +volatile protected ZipFile zipFile; +volatile long lastModified; +volatile long fileSize; +/** lazy initialized **/ +private volatile Set knownPackageNames; // Meant for ClasspathMultiReleaseJar, not used in here String compliance; ClasspathJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { this.resource = resource; + String filename; try { java.net.URI location = resource.getLocationURI(); if (location == null) { - this.zipFilename = ""; //$NON-NLS-1$ + filename = ""; //$NON-NLS-1$ } else { File localFile = Util.toLocalFile(location, null); - this.zipFilename = localFile.getPath(); + filename = localFile.getPath(); } } catch (CoreException e) { // ignore - this.zipFilename = ""; //$NON-NLS-1$ + filename = ""; //$NON-NLS-1$ } + this.zipFilename = filename; this.zipFile = null; this.knownPackageNames = null; this.accessRuleSet = accessRuleSet; @@ -182,6 +167,7 @@ IModule initializeModule() { } ClasspathJar(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) { + this.resource = null; this.zipFilename = zipFilename; this.lastModified = lastModified; this.zipFile = null; @@ -195,43 +181,31 @@ IModule initializeModule() { public ClasspathJar(ZipFile zipFile, AccessRuleSet accessRuleSet, boolean isOnModulePath) { this(zipFile.getName(), 0, accessRuleSet, null, isOnModulePath); this.zipFile = zipFile; - this.closeZipFileAtEnd = true; } @Override public void cleanup() { - if (this.closeZipFileAtEnd) { - if (this.zipFile != null) { - try { - this.zipFile.close(); - if (JavaModelManager.ZIP_ACCESS_VERBOSE) { - trace("(" + Thread.currentThread() + ") [ClasspathJar.cleanup()] Closed ZipFile on " + this.zipFilename); //$NON-NLS-1$ //$NON-NLS-2$ - } - } catch(IOException e) { // ignore it - JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Error closing " + this.zipFile.getName(), e)); //$NON-NLS-1$ - } - this.zipFile = null; - } - if (this.annotationZipFile != null) { - try { - this.annotationZipFile.close(); - if (JavaModelManager.ZIP_ACCESS_VERBOSE) { - trace("(" + Thread.currentThread() + ") [ClasspathJar.cleanup()] Closed Annotation ZipFile on " + this.zipFilename); //$NON-NLS-1$ //$NON-NLS-2$ - } - } catch(IOException e) { // ignore it - JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Error closing " + this.annotationZipFile.getName(), e)); //$NON-NLS-1$ + if (this.zipFile != null) { + try { + this.zipFile.close(); + if (JavaModelManager.ZIP_ACCESS_VERBOSE) { + trace("(" + Thread.currentThread() + ") [ClasspathJar.cleanup()] Closed ZipFile on " + this.zipFilename); //$NON-NLS-1$ //$NON-NLS-2$ } - this.annotationZipFile = null; + } catch(IOException e) { // ignore it + JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Error closing " + this.zipFile.getName(), e)); //$NON-NLS-1$ } - } else { - if (this.zipFile != null && JavaModelManager.ZIP_ACCESS_VERBOSE) { - try { - this.zipFile.size(); - trace("(" + Thread.currentThread() + ") [ClasspathJar.cleanup()] ZipFile NOT closed on " + this.zipFilename); //$NON-NLS-1$ //$NON-NLS-2$ - } catch (IllegalStateException e) { - // OK: the file was already closed + this.zipFile = null; + } + if (this.annotationZipFile != null) { + try { + this.annotationZipFile.close(); + if (JavaModelManager.ZIP_ACCESS_VERBOSE) { + trace("(" + Thread.currentThread() + ") [ClasspathJar.cleanup()] Closed Annotation ZipFile on " + this.zipFilename); //$NON-NLS-1$ //$NON-NLS-2$ } + } catch(IOException e) { // ignore it + JavaCore.getPlugin().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "Error closing " + this.annotationZipFile.getName(), e)); //$NON-NLS-1$ } + this.annotationZipFile = null; } this.module = null; // TODO(SHMOD): is this safe? this.knownPackageNames = null; @@ -295,13 +269,13 @@ public boolean isPackage(String qualifiedPackageName, String moduleName) { return false; } if (this.knownPackageNames == null) - scanContent(); - return this.knownPackageNames.includes(qualifiedPackageName); + readKnownPackageNames(); + return this.knownPackageNames.contains(qualifiedPackageName); } @Override public boolean hasCompilationUnit(String pkgName, String moduleName) { - if (scanContent()) { - if (!this.knownPackageNames.includes(pkgName)) { + if (readKnownPackageNames()) { + if (!this.knownPackageNames.contains(pkgName)) { // Don't waste time walking through the zip if we know that it doesn't // contain a directory that matches pkgName return false; @@ -322,22 +296,19 @@ public boolean hasCompilationUnit(String pkgName, String moduleName) { return false; } -/** Scan the contained packages and try to locate the module descriptor. */ -private boolean scanContent() { +/** Scan the contained packages. */ +private boolean readKnownPackageNames() { try { if (this.zipFile == null) { if (JavaModelManager.ZIP_ACCESS_VERBOSE) { trace("(" + Thread.currentThread() + ") [ClasspathJar.isPackage(String)] Creating ZipFile on " + this.zipFilename); //$NON-NLS-1$ //$NON-NLS-2$ } this.zipFile = new ZipFile(this.zipFilename); - this.closeZipFileAtEnd = true; - this.knownPackageNames = findPackageSet(); - } else { - this.knownPackageNames = findPackageSet(); } + this.knownPackageNames = getCachedPackageNames(); return true; } catch(Exception e) { - this.knownPackageNames = new SimpleSet(); // assume for this build the zipFile is empty + this.knownPackageNames = Set.of(); // assume for this build the zipFile is empty return false; } } @@ -378,7 +349,7 @@ public String debugPathString() { @Override public IModule getModule() { if (this.knownPackageNames == null) - scanContent(); + readKnownPackageNames(); return this.module; } @@ -388,7 +359,7 @@ public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageN return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false, null); } public Manifest getManifest() { - if (!scanContent()) // ensure zipFile is initialized + if (!readKnownPackageNames()) // ensure zipFile is initialized return null; ZipEntry entry = this.zipFile.getEntry(TypeConstants.META_INF_MANIFEST_MF); if (entry == null) { @@ -403,12 +374,12 @@ public Manifest getManifest() { } @Override public char[][] listPackages() { - if (!scanContent()) // ensure zipFile is initialized + if (!readKnownPackageNames()) // ensure zipFile is initialized return null; - char[][] result = new char[this.knownPackageNames.elementSize][]; + // -1 because it always contains empty string: + char[][] result = new char[this.knownPackageNames.size() - 1][]; int count = 0; - for (Object value : this.knownPackageNames.values) { - String string = (String) value; + for (String string : this.knownPackageNames) { if (string != null &&!string.isEmpty()) { result[count++] = string.replace('/', '.').toCharArray(); } @@ -420,7 +391,7 @@ public char[][] listPackages() { @Override protected IBinaryType decorateWithExternalAnnotations(IBinaryType reader, String fileNameWithoutExtension) { - if (scanContent()) { // ensure zipFile is initialized + if (readKnownPackageNames()) { // ensure zipFile is initialized String qualifiedBinaryFileName = fileNameWithoutExtension + ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX; ZipEntry entry = this.zipFile.getEntry(qualifiedBinaryFileName); if (entry != null) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java index 400b8bb294d..be0c4ca0a33 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java @@ -17,7 +17,6 @@ import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -41,15 +40,13 @@ import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor; import org.eclipse.jdt.internal.compiler.util.JrtFileSystem; -import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.util.Util; public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry { -protected final static Map> PackageCache = new ConcurrentHashMap<>(); -protected final static Map> ModulesCache = new ConcurrentHashMap<>(); +protected final static Map> modulesCache = new ConcurrentHashMap<>(); protected final String zipFilename; // keep for equals protected final JrtFileSystem jrtFileSystem; static final Set NO_LIMIT_MODULES = Collections.emptySet(); @@ -73,51 +70,18 @@ public ClasspathJrt(String zipFilename, AccessRuleSet accessRuleSet, IPath exter loadModules(this); } -/** - * Calculate and cache the package list available in the zipFile. - * @param jrt The ClasspathJar to use - * @return A SimpleSet with the all the package names in the zipFile. - */ -static Map findPackagesInModules(final ClasspathJrt jrt) { +static Set getModuleNames(final ClasspathJrt jrt) { if (jrt.zipFilename == null) { - return Map.of(); + return Set.of(); } - Map cache = PackageCache.computeIfAbsent(jrt.zipFilename, zipFileName -> { - final Map packagesInModule = new HashMap<>(); - try { - JRTUtil.walkModuleImage(jrt.jrtFileSystem, new JrtPackageVisitor(packagesInModule), JRTUtil.NOTIFY_PACKAGES | JRTUtil.NOTIFY_MODULES); - } catch (IOException e) { - Util.log(e, "Failed to init packages for " + zipFileName); //$NON-NLS-1$ - } - return packagesInModule.isEmpty() ? null : Collections.unmodifiableMap(packagesInModule); - }); - return cache; -} - -static final class JrtPackageVisitor implements JRTUtil.JrtFileVisitor { - private final Map packagesInModule; - SimpleSet packageSet; - - JrtPackageVisitor(Map packagesInModule) { - this.packagesInModule = packagesInModule; - } - - @Override - public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs) throws IOException { - ClasspathJar.addToPackageSet(this.packageSet, dir.toString(), true); - return FileVisitResult.CONTINUE; + if (modulesCache.isEmpty()) { + return null; } - - @Override - public FileVisitResult visitModule(Path path, String name) throws IOException { - this.packageSet = new SimpleSet(41); - this.packageSet.add(""); //$NON-NLS-1$ - if (name.endsWith("/")) { //$NON-NLS-1$ - name = name.substring(0, name.length() - 1); - } - this.packagesInModule.put(name, this.packageSet); - return FileVisitResult.CONTINUE; + Map modules = modulesCache.get(jrt.getKey()); + if (modules != null) { + return modules.keySet(); } + return null; } public static void loadModules(final ClasspathJrt jrt) { @@ -125,7 +89,7 @@ public static void loadModules(final ClasspathJrt jrt) { if (jrtKey == null) { return; } - ModulesCache.computeIfAbsent(jrtKey, key -> { + modulesCache.computeIfAbsent(jrtKey, key -> { Map newCache = new HashMap<>(); try { JRTUtil.walkModuleImage(jrt.jrtFileSystem, new JrtFileVisitor() { @@ -138,7 +102,7 @@ public FileVisitResult visitModule(Path path, String name) throws IOException { } catch (IOException e) { Util.log(e, "Failed to init packages for " + jrt); //$NON-NLS-1$ } - return newCache.isEmpty() ? null : Collections.unmodifiableMap(newCache); + return newCache.isEmpty() ? null : Map.copyOf(newCache); }); } @@ -255,7 +219,7 @@ public IModule getModule(String moduleName) { if (!hasModule()) { return null; } - Map modules = ModulesCache.get(getKey()); + Map modules = modulesCache.get(getKey()); if (modules != null) { return modules.get(moduleName); } @@ -263,9 +227,9 @@ public IModule getModule(String moduleName) { } @Override public Collection getModuleNames(Collection limitModules) { - Map cache = findPackagesInModules(this); + Set cache = getModuleNames(this); if (cache != null) - return selectModules(cache.keySet(), limitModules); + return selectModules(cache, limitModules); return Collections.emptyList(); } @@ -307,7 +271,6 @@ public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageN } /** TEST ONLY */ public static void resetCaches() { - PackageCache.clear(); - ModulesCache.clear(); + modulesCache.clear(); } } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java index 6cf45b68099..51e55ef92aa 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java @@ -12,8 +12,6 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.core.builder; - -import java.io.File; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.FileVisitResult; @@ -26,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Predicate; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -39,8 +38,6 @@ import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.util.CtSym; import org.eclipse.jdt.internal.compiler.util.JRTUtil; -import org.eclipse.jdt.internal.compiler.util.JrtFileSystem; -import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.util.Util; @@ -57,7 +54,6 @@ public class ClasspathJrtWithReleaseOption extends ClasspathJrt { private final Path releasePath; private final String modPathString; private CtSym ctSym; - private final JrtFileSystem jrtFileSystemForRelease; public ClasspathJrtWithReleaseOption(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, @@ -71,13 +67,6 @@ public ClasspathJrtWithReleaseOption(String zipFilename, AccessRuleSet accessRul this.externalAnnotationPath = externalAnnotationPath.toString(); } this.release = getReleaseOptionFromCompliance(release); - JrtFileSystem systemForRelease = null; - try { - systemForRelease = JRTUtil.getJrtSystem(new File(zipFilename), this.release); - } catch (IOException e) { - Util.log(e, "Failed to init packages for " + zipFilename); //$NON-NLS-1$ - } - this.jrtFileSystemForRelease = systemForRelease; try { this.ctSym = JRTUtil.getCtSym(Path.of(this.zipFilename).getParent().getParent()); } catch (IOException e) { @@ -126,27 +115,6 @@ private String getReleaseOptionFromCompliance(String comp) throws CoreException } } - Map findPackagesInModules() { - // In JDK 11 and before, classes are not listed under their respective modules - // Hence, we simply go to the default module system for package-module mapping - if (this.fs == null || !this.ctSym.isJRE12Plus()) { - return ClasspathJrt.findPackagesInModules(this); - } - if (this.modPathString == null) { - return Map.of(); - } - Map cache = PackageCache.computeIfAbsent(this.modPathString, key -> { - final Map packagesInModule = new HashMap<>(); - try { - JRTUtil.walkModuleImage(this.jrtFileSystemForRelease, new JrtPackageVisitor(packagesInModule), JRTUtil.NOTIFY_PACKAGES | JRTUtil.NOTIFY_MODULES); - } catch (IOException e) { - Util.log(e, "Failed to init packages for " + this.modPathString); //$NON-NLS-1$ - } - return packagesInModule.isEmpty() ? null : Collections.unmodifiableMap(packagesInModule); - }); - return cache; - } - public void loadModules() { if (this.fs == null || !this.ctSym.isJRE12Plus()) { ClasspathJrt.loadModules(this); @@ -155,7 +123,7 @@ public void loadModules() { if (this.modPathString == null) { return; } - ModulesCache.computeIfAbsent(this.modPathString, key -> { + modulesCache.computeIfAbsent(this.modPathString, key -> { List releaseRoots = this.ctSym.releaseRoots(this.releaseCode); Map newCache = new HashMap<>(); for (Path root : releaseRoots) { @@ -180,7 +148,7 @@ public FileVisitResult visitFile(Path f, BasicFileAttributes attrs) throws IOExc Util.log(e, "Failed to init modules cache for " + key); //$NON-NLS-1$ } } - return newCache.isEmpty() ? null : Collections.unmodifiableMap(newCache); + return newCache.isEmpty() ? null : Map.copyOf(newCache); }); } @@ -241,9 +209,9 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa @Override public Collection getModuleNames(Collection limitModules) { - Map cache = findPackagesInModules(); + Set cache = ClasspathJrt.getModuleNames(this); if (cache != null) - return selectModules(cache.keySet(), limitModules); + return selectModules(cache, limitModules); return Collections.emptyList(); } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java index acb99d78741..94ecf3ad346 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java @@ -3,7 +3,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -17,7 +19,6 @@ import org.eclipse.jdt.internal.compiler.env.IModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.util.Util; @@ -41,7 +42,6 @@ public class ClasspathMultiReleaseJar extends ClasspathJar { public ClasspathMultiReleaseJar(ZipFile zipFile, AccessRuleSet accessRuleSet, boolean isOnModulePath, String compliance) { this(zipFile.getName(), 0, accessRuleSet, null, isOnModulePath, compliance); this.zipFile = zipFile; - this.closeZipFileAtEnd = true; } @Override @@ -98,8 +98,9 @@ private String[] supportedVersions(ZipFile file) { } @Override - protected String readJarContent(final SimpleSet packageSet) { - String modInfo = null; + protected Set readPackageNames() { + final Set packageSet = new HashSet<>(); + packageSet.add(""); //$NON-NLS-1$ for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) { String fileName = e.nextElement().getName(); if (fileName.startsWith(META_INF_VERSIONS) && fileName.length() > META_INF_LENGTH) { @@ -107,17 +108,9 @@ protected String readJarContent(final SimpleSet packageSet) { fileName = fileName.substring(i + 1); } else if (fileName.startsWith("META-INF/")) //$NON-NLS-1$ continue; - if (modInfo == null) { - int folderEnd = fileName.lastIndexOf('/'); - folderEnd += 1; - String className = fileName.substring(folderEnd, fileName.length()); - if (className.equalsIgnoreCase(IModule.MODULE_INFO_CLASS)) { - modInfo = fileName; - } - } addToPackageSet(packageSet, fileName, false); } - return modInfo; + return packageSet; } @Override