Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
Expand All @@ -51,6 +54,7 @@ public class ClasspathJep247 extends ClasspathJrt {
protected Set<String> packageCache;
protected final File jdkHome;
protected String modulePath;
protected Set<String> currentReleaseModules;

public ClasspathJep247(File jdkHome, String release, AccessRuleSet accessRuleSet) {
super(new File(new File(jdkHome, "lib"), JRTUtil.JRT_FS_JAR), false, accessRuleSet, null); //$NON-NLS-1$
Expand All @@ -68,6 +72,10 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN
}
@Override
public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
return super.findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, asBinaryOnly);
}
if (!isPackage(qualifiedPackageName, moduleName))
return null; // most common case

Expand Down Expand Up @@ -117,10 +125,22 @@ public void initialize() throws IOException {
if (!Files.exists(this.fs.getPath(this.releaseInHex))) {
throw new IllegalArgumentException("release " + this.compliance + " is not found in the system"); //$NON-NLS-1$//$NON-NLS-2$
}
Path systemModules = this.fs.getPath(this.releaseInHex, "system-modules"); //$NON-NLS-1$
if (Files.isRegularFile(systemModules)) {
// Per JEP 247, ct.sym uses this file for the current release instead of storing duplicate signatures.
// Read classes from the live JRT image, but expose only the standard modules listed by ct.sym.
this.currentReleaseModules = Set.copyOf(Files.readAllLines(systemModules, StandardCharsets.UTF_8));
}
super.initialize();
}
@Override
public void loadModules() {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
super.loadModules();
this.moduleNamesCache.retainAll(this.currentReleaseModules);
return;
}
// Modules below level 9 are not dealt with here. Leave it to ClasspathJrt
if (this.jdklevel <= ClassFileConstants.JDK1_8) {
super.loadModules();
Expand Down Expand Up @@ -187,6 +207,24 @@ public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException ex
this.moduleNamesCache.addAll(cache.keySet());
}

@Override
public Collection<String> getModuleNames(Collection<String> limitModules, Function<String, IModule> getModule) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
return selectModules(this.moduleNamesCache, limitModules, getModule);
}
return super.getModuleNames(limitModules, getModule);
}

@Override
public IModule getModule(char[] moduleName) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null && !this.currentReleaseModules.contains(String.valueOf(moduleName))) {
return null;
}
return super.getModule(moduleName);
}

@Override
void acceptModule(ClassFileReader reader, Map<String, IModule> cache) {
// Modules below level 9 are not dealt with here. Leave it to ClasspathJrt
Expand All @@ -208,6 +246,23 @@ protected void addToPackageCache(String packageName, boolean endsWithSep) {
}
@Override
public synchronized char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
if (moduleName != null && !this.currentReleaseModules.contains(moduleName)) {
return null;
}
char[][] declaringModules = super.getModulesDeclaringPackage(qualifiedPackageName, moduleName);
if (moduleName != null || declaringModules == null) {
return declaringModules;
}
List<char[]> filteredModules = new ArrayList<>(declaringModules.length);
for (char[] declaringModule : declaringModules) {
if (this.currentReleaseModules.contains(String.valueOf(declaringModule))) {
filteredModules.add(declaringModule);
}
}
return filteredModules.isEmpty() ? null : filteredModules.toArray(char[][]::new);
}
if (this.packageCache == null) {
this.packageCache = new HashSet<>(41);
this.packageCache.add(Util.EMPTY_STRING);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN
}
@Override
public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
return super.findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, asBinaryOnly);
}
if (!isPackage(qualifiedPackageName, moduleName))
return null; // most common case

Expand Down Expand Up @@ -147,6 +151,11 @@ public void initialize() throws IOException {
}
@Override
public void loadModules() {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
super.loadModules();
return;
}
// Modules below level 9 are not dealt with here. Leave it to ClasspathJrt
if (this.jdklevel <= ClassFileConstants.JDK1_8) {
super.loadModules();
Expand Down Expand Up @@ -219,6 +228,10 @@ public Collection<String> getModuleNames(Collection<String> limitModule, Functio
}
@Override
public IModule getModule(char[] moduleName) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
return super.getModule(moduleName);
}
// Modules below level 9 are not dealt with here. Leave it to ClasspathJrt
if (this.jdklevel <= ClassFileConstants.JDK1_8) {
return super.getModule(moduleName);
Expand Down Expand Up @@ -261,6 +274,10 @@ void acceptModule(ClassFileReader reader, Map<String, IModule> cache) {
}
@Override
public synchronized char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
// The current release uses the JRT filtered by ct.sym's system-modules.
if (this.currentReleaseModules != null) {
return super.getModulesDeclaringPackage(qualifiedPackageName, moduleName);
}
if (this.jdklevel >= ClassFileConstants.JDK9) {
// Delegate to the boss, even if it means inaccurate error reporting at times
List<String> mods = JRTUtil.getModulesDeclaringPackage(this.jrtFileSystem, qualifiedPackageName, moduleName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5201,7 +5201,7 @@ protected void setPaths(ArrayList<String> bootclasspaths,
ArrayList<Classpath> allPaths = null;
long jdkLevel = validateClasspathOptions(bootclasspaths, endorsedDirClasspaths, extdirsClasspaths);

if (this.releaseVersion != null && this.complianceLevel < jdkLevel) {
if (this.releaseVersion != null && this.complianceLevel <= jdkLevel) {
// TODO: Revisit for access rules
allPaths = new ArrayList<>();
Classpath olderSystemRelease = FileSystem.getOlderSystemRelease(this.javaHomeCache.getAbsolutePath(), this.releaseVersion, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,9 @@ protected void handleLocations() {
}
}
}
fileSystemClasspaths.addAll(platformLocations);
if (this.releaseVersion == null) {
fileSystemClasspaths.addAll(platformLocations);
}
break; // Only possible scenario is, we have one and only entry representing the Java home.
} else {
Classpath classpath = FileSystem.getClasspath(
Expand Down Expand Up @@ -791,7 +793,7 @@ private String getJavaVersion(File javaHome) {
}
private Classpath getSystemClasspath(File jdkHome, long jdkLevel) {
Classpath system;
if (this.releaseVersion != null && this.complianceLevel < jdkLevel) {
if (this.releaseVersion != null && this.complianceLevel <= jdkLevel) {
String versionFromJdkLevel = CompilerOptions.versionFromJdkLevel(this.complianceLevel);
if (versionFromJdkLevel.length() >= 3) {
versionFromJdkLevel = versionFromJdkLevel.substring(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.module.ModuleFinder;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
Expand All @@ -55,6 +57,7 @@
import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.batch.ClasspathDirectory;
import org.eclipse.jdt.internal.compiler.batch.ClasspathJep247;
import org.eclipse.jdt.internal.compiler.batch.ClasspathJar;
import org.eclipse.jdt.internal.compiler.batch.FileSystem;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
Expand Down Expand Up @@ -87,6 +90,20 @@ public static Test suite() {
public static Class<? extends TestCase> testClass() {
return BatchCompilerTest.class;
}
private static class InspectableMain extends Main {
InspectableMain() {
super(new PrintWriter(new StringWriter()), new PrintWriter(new StringWriter()), false, null, null);
}

boolean usesCtSymReleaseClasspath() {
for (Classpath classpath : this.checkedClasspaths) {
if (classpath instanceof ClasspathJep247) {
return true;
}
}
return false;
}
}
static class StringMatcher extends Matcher {
private final String expected;
private final Normalizer normalizer;
Expand Down Expand Up @@ -13528,4 +13545,43 @@ public static void main(String[] args) {

true);
}
}
public void testReleaseCurrentJdkUsesCtSym() {
File outputDirectory = new File(OUTPUT_DIR);
Util.flushDirectoryContent(outputDirectory);
outputDirectory.mkdirs();
String sourceFile = OUTPUT_DIR + File.separator + "X.java";
Util.writeToFile("public class X {}", sourceFile);

InspectableMain compiler = new InspectableMain();
String release = System.getProperty("java.specification.version");
assertTrue(compiler.compile(new String[] { "--release", release, "-d", OUTPUT_DIR, sourceFile }));
assertTrue("--release must use ct.sym metadata for the current JDK", compiler.usesCtSymReleaseClasspath());
}
public void testReleaseCurrentJdkFiltersImplementationSpecificModules() {
String implementationSpecificModule = "jdk.internal.vm.ci";
if (ModuleFinder.ofSystem().find(implementationSpecificModule).isEmpty()) {
return;
}

String[] testFiles = {
"X.java",
"public class X {}"
};
String release = System.getProperty("java.specification.version");
String sourceFile = "\"" + OUTPUT_DIR + File.separator + "X.java\"";
String outputDirectory = "-d \"" + OUTPUT_DIR + "\"";

runConformTest(
testFiles,
outputDirectory + " --add-modules " + implementationSpecificModule + " " + sourceFile,
"",
"",
true);
runNegativeTest(
testFiles,
outputDirectory + " --release " + release + " --add-modules " + implementationSpecificModule + " " + sourceFile,
"",
"invalid module name: " + implementationSpecificModule + "\n",
true);
}
}
Loading