update jdt.core to I20190301-0040 for 4.11RC1
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index ecc18d6..67ef467 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -1031,7 +1031,7 @@
 		String logContents = Util.fileContent(logFileName);
 		String expectedLogContents =
 			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
-			"<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.005 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_005.dtd\">\n" + 
+			"<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.006 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_006.dtd\">\n" + 
 			"<compiler copyright=\"{2}\" name=\"{1}\" version=\"{3}\">\n" + 
 			"	<command_line>\n" + 
 			"		<argument value=\"---OUTPUT_DIR_PLACEHOLDER---{0}X.java\"/>\n" + 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
index c57ea95..1504327 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java
@@ -9532,4 +9532,44 @@
 		};
 		runner.runConformTest();
 	}
+	public void testBug536860() {
+		runConformTest(
+			new String[] {
+				"Snippet.java",
+				"import java.io.IOException;\n" + 
+				"import java.io.InputStream;\n" + 
+				"import java.nio.file.Path;\n" + 
+				"import java.util.Map;\n" + 
+				"import java.util.concurrent.Callable;\n" + 
+				"import java.util.function.Function;\n" + 
+				"\n" + 
+				"interface EntityReader<T, S> { }\n" + 
+				"class ExtraIOUtils {\n" + 
+				"	public static Callable<InputStream> getInputStreamProvider() {\n" + 
+				"		return null;\n" + 
+				"	}\n" + 
+				"}\n" + 
+				"\n" + 
+				"public class Snippet {\n" + 
+				"	public <T> EntityReader<T, Path> createEntityReader(\n" + 
+				"	    Function<? super String, ? extends String> colNameMapper,\n" + 
+				"	    Function<? super String[], ? extends T> instantiator,\n" + 
+				"	    Map<String, ?> runtimeValues)\n" + 
+				"	         throws IOException {\n" + 
+				"	        EntityReader<T, ?> streamReader =\n" + 
+				"	            createEntityStreamReader(\n" + 
+				"	            		ExtraIOUtils.getInputStreamProvider(),\n" + 
+				"	                colNameMapper, instantiator, runtimeValues);\n" +
+				"			return null;\n" + 
+				"	}\n" + 
+				"	public <T> EntityReader<T, Callable<InputStream>> createEntityStreamReader(\n" + 
+				"	        Callable<InputStream> streamProvider,\n" + 
+				"	        Function<? super String, ? extends String> colNameMapper, Function<? super String[], ? extends T> instantiator,\n" + 
+				"	        Map<String, ?> runtimeValues)\n" + 
+				"	            throws IOException {\n" + 
+				"		return null;\n" + 
+				"	}\n" + 
+				"}\n"
+			});
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
index 703c756..a6e2ba3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -40,7 +40,7 @@
 public class ModuleCompilationTests extends AbstractBatchCompilerTest {
 
 	static {
-//		 TESTS_NAMES = new String[] { "testBug540067e" };
+//		 TESTS_NAMES = new String[] { "test001" };
 		// TESTS_NUMBERS = new int[] { 1 };
 		// TESTS_RANGE = new int[] { 298, -1 };
 	}
@@ -3977,11 +3977,11 @@
 					"}",
 				},
 		     "\"" + OUTPUT_DIR +  File.separator + "X.java\""
-		     + " --release 6 -d \"" + OUTPUT_DIR + "\"",
+		     + " --release 7 -d \"" + OUTPUT_DIR + "\"",
 		     "",
 		     "",
 		     true);
-		String expectedOutput = "// Compiled from X.java (version 1.6 : 50.0, super bit)";
+		String expectedOutput = "// Compiled from X.java (version 1.7 : 51.0, super bit)";
 			checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput);
 	}
 	public void testReleaseOption4() throws Exception {
@@ -4096,6 +4096,7 @@
 		     true);
 	}
 	public void testReleaseOption10() throws Exception {
+		if (isJRE12Plus) return;
 		this.runNegativeTest(
 				new String[] {
 					"X.java",
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
index 33aa81c..fee9aac 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
@@ -53,6 +53,7 @@
 	protected boolean enableAPT = false;
 	protected static boolean isJRE9Plus = false; // Stop gap, so tests need not be run at 9, but some tests can be adjusted for JRE 9
 	protected static boolean isJRE11Plus = false;
+	protected static boolean isJRE12Plus = false;
 	protected static boolean reflectNestedClassUseDollar;
 
 	/**
@@ -147,6 +148,7 @@
          int lessthan9 = F_1_3 | F_1_4 | F_1_5 | F_1_6 | F_1_7 | F_1_8;
          isJRE9Plus = !isJRELevel(lessthan9);
          isJRE11Plus = isJRELevel(F_11);
+         isJRE12Plus = "12".equals(System.getProperty("java.specification.version"));
 	 }
 
 	/**
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
index df6e565..7260030 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
@@ -74,6 +74,9 @@
 	protected String endChar = ",";
 
 	protected static boolean isJRE9 = false;
+	protected static boolean isJRE10 = false;
+	protected static boolean isJRE11 = false;
+	protected static boolean isJRE12 = false;
 	protected static String DEFAULT_MODULES = null;
 	static {
 		String javaVersion = System.getProperty("java.version");
@@ -87,6 +90,16 @@
 			}
 		}
 		long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion.length() > 3 ? javaVersion.substring(0, 3) : javaVersion);
+		if (jdkLevel >= ClassFileConstants.JDK11) {
+			if (CompilerOptions.versionToJdkLevel(javaVersion.length() > 3 ? javaVersion.substring(0, 3) : javaVersion, false) == 0) {
+				// version was capped to 11 during versionToJdkLevel(version, true)
+				isJRE12 = true;
+			}
+			isJRE11 = true;
+		}
+		if (jdkLevel >= ClassFileConstants.JDK10) {
+			isJRE10 = true;
+		}
 		if (jdkLevel >= ClassFileConstants.JDK9) {
 			isJRE9 = true;
 			if (vmName.contains("HotSpot")) {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index b80de70..ddc65ad 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -696,8 +696,14 @@
 	public void testConvertToModule() throws CoreException, IOException {
 		Hashtable<String, String> javaCoreOptions = JavaCore.getOptions();
 		try {
-			IJavaProject project = setUpJavaProject("ConvertToModule", "9");
-			assertEquals(project.getOption("org.eclipse.jdt.core.compiler.compliance", true), "9");
+			IJavaProject project = setUpJavaProject("ConvertToModule");
+			Map<String, String> options = new HashMap<>();
+			// Make sure the new options map doesn't reset.
+			options.put(CompilerOptions.OPTION_Compliance, "9");
+			options.put(CompilerOptions.OPTION_Source, "9");
+			options.put(CompilerOptions.OPTION_TargetPlatform, "9");
+			options.put(CompilerOptions.OPTION_Release, "enabled");
+			project.setOptions(options);
 			project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
 			IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
 			IPackageFragmentRoot theRoot = null;
@@ -709,7 +715,14 @@
 			}
 			assertNotNull("should not be null", theRoot);
 			String[] modules = JavaCore.getReferencedModules(project);
-			assertStringsEqual("incorrect result", new String[]{"java.desktop", "java.rmi", "java.sql"}, modules);
+			if (isJRE12)
+				assertStringsEqual("incorrect result", new String[]{"java.desktop", "java.rmi", "java.sql"}, modules);
+			else if (isJRE11)
+				assertStringsEqual("incorrect result", new String[]{"java.datatransfer", "java.desktop", "java.net.http", "java.rmi", "java.sql"}, modules);
+			else if (isJRE10)
+				assertStringsEqual("incorrect result", new String[]{"java.datatransfer", "java.desktop", "java.rmi", "java.sql"}, modules);
+			else // 9
+				assertStringsEqual("incorrect result", new String[]{"java.desktop", "java.rmi", "java.sql"}, modules);
 		} finally {
 			this.deleteProject("ConvertToModule");
 			 JavaCore.setOptions(javaCoreOptions);
@@ -8040,6 +8053,440 @@
 		}
 	}
 
+	public void testReleaseOption1() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "public class X {\n" +
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption2() throws Exception {
+		if (!isJRE12)
+			return;
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_6);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_6);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "public class X {\n" +
+								"	public java.util.stream.Stream<String> emptyStream() {\n" +
+								"		return null;\n" +
+								"	}\n" +
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"The project was not built due to \"release 6 is not found in the system\". "
+					+ "Fix the problem, then try refreshing this project and building it since it may be inconsistent",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption3() throws Exception {
+		if (isJRE12)
+			return;
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "public class X {\n" +
+								"	public java.util.stream.Stream<String> emptyStream() {\n" +
+								"		return null;\n" +
+								"	}\n" +
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"java.util.stream.Stream cannot be resolved to a type",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption4() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "public class X {\n" +
+								"	public java.util.stream.Stream<String> emptyStream() {\n" +
+								"		return null;\n" +
+								"	}\n" +
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption5() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "public class X {\n" +
+								"	public java.util.stream.Stream<String> emptyStream() {\n" +
+								"		return null;\n" +
+								"	}\n" +
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"java.util.stream.Stream cannot be resolved to a type",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption6() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "interface I {\n" +
+								"  int add(int x, int y);\n" +
+								"}\n" +
+								"public class X {\n" +
+								"  public static void main(String[] args) {\n" +
+								"    I i = (x, y) -> {\n" +
+								"      return x + y;\n" +
+								"    };\n" +
+								"  }\n" +
+								"}\n";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"Lambda expressions are allowed only at source level 1.8 or above",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption7() throws Exception {
+		if (isJRE12)
+			return;
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_6);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_6);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "import java.io.*;\n" +
+								"public class X {\n" + 
+								"	public static void main(String[] args) {\n" + 
+								"		try {\n" + 
+								"			System.out.println();\n" + 
+								"			Reader r = new FileReader(args[0]);\n" + 
+								"			r.read();\n" + 
+								"		} catch(IOException | FileNotFoundException e) {\n" +
+								"			e.printStackTrace();\n" + 
+								"		}\n" + 
+								"	}\n" + 
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",
+							"Multi-catch parameters are not allowed for source level below 1.7\n" + 
+							"The exception FileNotFoundException is already caught by the alternative IOException",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption8() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_9);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_9);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_9);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "module mod.one { \n" +
+								"	requires java.base;\n" +
+								"}";
+			String mPath = "p/src/module-info.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption9() throws Exception {
+		if (!isJRE10) return;
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_10);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_10);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_10);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "module mod.one { \n" +
+								"	requires java.base;\n" +
+								"}";
+			String mPath = "p/src/module-info.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption10() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "module mod.one { \n" +
+					"	requires java.base;\n" +
+					"}";
+			String mPath = "p/src/module-info.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			String expected =
+					"Syntax error on token \"module\", package expected\n" + 
+					"Syntax error on token(s), misplaced construct(s)\n" + 
+					"Syntax error on token \".\", , expected\n" + 
+					"Syntax error on token \"}\", delete this token";
+			assertMarkers("Unexpected markers",
+							expected,  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption11() throws Exception {
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			createFolder("p/src/foo");
+			createFile(
+					"p/src/foo/Module.java",
+					"package foo;\n" +
+					"public class Module {}\n");
+			createFile(
+					"p/src/foo/X.java",
+					"package foo;\n" +
+					"public class X { \n" +
+					"	public Module getModule(String name) {\n" + 
+					"		return null;\n" +
+					"	}\n" + 
+					"}");
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption12() throws Exception {
+		if (!isJRE12)
+			return;
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "import java.io.*;\n" + 
+								"\n" + 
+								"public class X {\n" + 
+								"	public static void main(String[] args) {\n" + 
+								"		String str = Integer.toUnsignedString(1, 1);\n" + 
+								"	}\n" + 
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"The method toUnsignedString(int, int) is undefined for the type Integer",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
+	public void testReleaseOption13() throws Exception {
+		if (!isJRE12)
+			return;
+		Hashtable<String, String> options = JavaCore.getOptions();
+		IJavaProject p = createJava9Project("p");
+		p.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
+		p.setOption(JavaCore.COMPILER_RELEASE, JavaCore.ENABLED);
+		String outputDirectory = Util.getOutputDirectory();
+		try {
+			String testSource = "\n" + 
+								"public class X {\n" + 
+								"	public static void main(String[] args) {\n" + 
+								"		Integer.toUnsignedString(1, 1);\n" + 
+								"	}\n" + 
+								"}";
+			String mPath = "p/src/X.java";
+			createFile(mPath,
+					testSource);
+			p.getProject().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
+			waitForAutoBuild();
+			IMarker[] markers = p.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",
+					"",  markers);
+
+		} finally {
+			JavaCore.setOptions(options);
+			deleteProject(p);
+			File outputDir = new File(outputDirectory);
+			if (outputDir.exists())
+				Util.flushDirectoryContent(outputDir);
+		}
+	}
 	protected void assertNoErrors() throws CoreException {
 		for (IProject p : getWorkspace().getRoot().getProjects()) {
 			int maxSeverity = p.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java
index 1057346..5879186 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingModuleDeclarationTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017 IBM Corporation and others.
+ * Copyright (c) 2017, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -364,4 +364,37 @@
 		}
 	}
 
+	public void testBug542106_since_9() throws Exception {
+		IJavaProject javaProject = null;
+		try {
+			javaProject = createProject("P_9", JavaCore.VERSION_9);
+			IPackageFragmentRoot currentSourceFolder = getPackageFragmentRoot("P_9", "src");
+			IPackageFragment pack1= currentSourceFolder.getPackageFragment(Util.EMPTY_STRING);
+			String content =
+					"import java.util.*;\n" +
+					"import java.util.function.Consumer;\n" +
+					"module first {\n" +
+					"}";
+			ICompilationUnit cu= pack1.createCompilationUnit("module-info.java", content, false, null);
+			CompilationUnit astRoot= createAST(cu);
+			ASTRewrite rewrite= ASTRewrite.create(astRoot.getAST());
+			AST ast= astRoot.getAST();
+			ListRewrite listRewrite = rewrite.getListRewrite(astRoot, CompilationUnit.IMPORTS_PROPERTY);
+			{
+				listRewrite.remove((ImportDeclaration) astRoot.imports().get(0), null);
+				ImportDeclaration newImport = ast.newImportDeclaration();
+				newImport.setName(ast.newName("java.io.Serializable"));
+				listRewrite.insertFirst(newImport, null);
+			}
+			String preview= evaluateRewrite(cu, rewrite);
+			content =
+					"import java.io.Serializable;\n" +
+					"import java.util.function.Consumer;\n" +
+					"module first {\n" +
+					"}";
+			assertEqualString(preview, content);
+		} finally {
+			if (javaProject != null) deleteProject(javaProject);
+		}
+	}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
index 7a39271..8aad546 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2018 IBM Corporation.
+ * Copyright (c) 2018, 2019 IBM Corporation.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v2.0
  * which accompanies this distribution, and is available at
@@ -42,15 +42,15 @@
 
 public class ClasspathJep247 extends ClasspathJrt {
 
-	private java.nio.file.FileSystem fs = null;
-	private String compliance = null;
-	private long jdklevel;
-	private String releaseInHex = null;
-	private String[] subReleases = null;
-	private Path releasePath = null;
-	private Set<String> packageCache;
-	File jdkHome;
-	String modulePath = null;
+	protected java.nio.file.FileSystem fs = null;
+	protected String compliance = null;
+	protected long jdklevel;
+	protected String releaseInHex = null;
+	protected String[] subReleases = null;
+	protected Path releasePath = null;
+	protected Set<String> packageCache;
+	protected File jdkHome;
+	protected String modulePath = null;
 
 	public ClasspathJep247(File jdkHome, String release, AccessRuleSet accessRuleSet) {
 		super(jdkHome, false, accessRuleSet, null);
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java
new file mode 100644
index 0000000..52a8398
--- /dev/null
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247Jdk12.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2019 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+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.function.Function;
+
+import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.JRTUtil;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ClasspathJep247Jdk12 extends ClasspathJep247 {
+
+	Map<String, IModule> modules;
+
+	public ClasspathJep247Jdk12(File jdkHome, String release, AccessRuleSet accessRuleSet) {
+		super(jdkHome, release, accessRuleSet);
+	}
+	@Override
+	public List<Classpath> fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
+		 return null;
+	}
+	@Override
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) {
+		return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false);
+	}
+	@Override
+	public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+		if (!isPackage(qualifiedPackageName, moduleName))
+			return null; // most common case
+
+		try {
+			ClassFileReader reader = null;
+			byte[] content = null;
+			qualifiedBinaryFileName = qualifiedBinaryFileName.replace(".class", ".sig"); //$NON-NLS-1$ //$NON-NLS-2$
+			if (this.subReleases != null && this.subReleases.length > 0) {
+				done: for (String rel : this.subReleases) {
+					if (moduleName == null) {
+						Path p = this.fs.getPath(rel);
+						try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(p)) {
+							for (final java.nio.file.Path subdir: stream) {
+								Path f = this.fs.getPath(rel, subdir.getFileName().toString(), qualifiedBinaryFileName);
+								if (Files.exists(f)) {
+									content = JRTUtil.safeReadBytes(f);
+									if (content != null)
+										break done;
+								}
+							}
+						}
+					} else {
+						Path p = this.fs.getPath(rel, moduleName, qualifiedBinaryFileName);
+						if (Files.exists(p)) {
+							content = JRTUtil.safeReadBytes(p);
+							if (content != null)
+								break;
+						}
+					}
+				}
+			} else {
+				content = JRTUtil.safeReadBytes(this.fs.getPath(this.releaseInHex, qualifiedBinaryFileName));
+			}
+			if (content != null) {
+				reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
+				return new NameEnvironmentAnswer(reader, fetchAccessRestriction(qualifiedBinaryFileName), null);
+			}
+		} catch(ClassFormatException e) {
+			// Continue
+		} catch (IOException e) {
+			// continue
+		}
+		return null;
+	}
+
+	@Override
+	public void initialize() throws IOException {
+		if (this.compliance == null) {
+			return;
+		}
+		if (this.fs != null) {
+			super.initialize();
+			return;
+		}
+		this.releaseInHex = Integer.toHexString(Integer.parseInt(this.compliance)).toUpperCase();
+		Path filePath = this.jdkHome.toPath().resolve("lib").resolve("ct.sym"); //$NON-NLS-1$ //$NON-NLS-2$
+		URI t = filePath.toUri();
+		if (!Files.exists(filePath)) {
+			return;
+		}
+		URI uri = URI.create("jar:file:" + t.getRawPath()); //$NON-NLS-1$
+		try {
+			this.fs = FileSystems.getFileSystem(uri);
+		} catch(FileSystemNotFoundException fne) {
+			// Ignore and move on
+		}
+		if (this.fs == null) {
+			HashMap<String, ?> env = new HashMap<>();
+			this.fs = FileSystems.newFileSystem(uri, env);
+		}
+		this.releasePath = this.fs.getPath("/"); //$NON-NLS-1$
+		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$
+		}
+		List<String> sub = new ArrayList<>();
+		try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
+			for (final java.nio.file.Path subdir: stream) {
+				String rel = subdir.getFileName().toString();
+				if (rel.contains(this.releaseInHex))
+					sub.add(rel);
+			}
+			this.subReleases = sub.toArray(new String[sub.size()]);
+		} catch (IOException e) {
+			//e.printStackTrace();
+		}
+		super.initialize();
+	}
+	@Override
+	public void loadModules() {
+		// Modules below level 8 are not dealt with here. Leave it to ClasspathJrt
+		if (this.jdklevel <= ClassFileConstants.JDK1_8) {
+			super.loadModules();
+			return;
+		}
+		final Path modPath = this.fs.getPath(this.releaseInHex);
+		this.modulePath = this.file.getPath() + "|" + modPath.toString(); //$NON-NLS-1$
+		this.modules = ModulesCache.get(this.modulePath);
+		if (this.modules == null) {
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
+				for (final java.nio.file.Path subdir: stream) {
+					String rel = subdir.getFileName().toString();
+					if (!rel.contains(this.releaseInHex)) {
+						continue;
+					}
+					Files.walkFileTree(subdir, Collections.EMPTY_SET, 2, new FileVisitor<java.nio.file.Path>() {
+
+						@Override
+						public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+								throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult visitFile(java.nio.file.Path f, BasicFileAttributes attrs) throws IOException {
+							if (attrs.isDirectory() || f.getNameCount() < 3) 
+								return FileVisitResult.CONTINUE;
+							byte[] content = null;
+							if (Files.exists(f)) {
+								content = JRTUtil.safeReadBytes(f);
+								if (content == null)
+									return FileVisitResult.CONTINUE;
+								Path m = f.subpath(1, f.getNameCount() - 1);
+								ClasspathJep247Jdk12.this.acceptModule(m.getFileName().toString(), content);
+								ClasspathJep247Jdk12.this.moduleNamesCache.add(m.getFileName().toString());
+							}
+							return FileVisitResult.SKIP_SIBLINGS;
+						}
+
+						@Override
+						public FileVisitResult visitFileFailed(java.nio.file.Path f, IOException exc) throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc) throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+					});
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		} else {
+			this.moduleNamesCache.addAll(this.modules.keySet());
+		}
+	}
+	@Override
+	public Collection<String> getModuleNames(Collection<String> limitModule, Function<String, IModule> getModule) {
+		return selectModules(this.moduleNamesCache, limitModule, getModule);
+	}
+	@Override
+	public IModule getModule(char[] moduleName) {
+		if (this.modules != null) {
+			return this.modules.get(String.valueOf(moduleName));
+		}
+		return null;
+	}
+	void acceptModule(String name, byte[] content) {
+		if (content == null) 
+			return;
+
+		if (this.modules != null) {
+			if (this.modules.containsKey(name))
+				return;
+		}
+
+		ClassFileReader reader = null;
+		try {
+			reader = new ClassFileReader(content, IModule.MODULE_INFO_CLASS.toCharArray());
+		} catch (ClassFormatException e) {
+			e.printStackTrace();
+		}
+		if (reader != null) {
+			acceptModule(reader);
+		}
+	}
+	@Override
+	void acceptModule(ClassFileReader reader) {
+		// Modules below level 8 are not dealt with here. Leave it to ClasspathJrt
+		if (this.jdklevel <= ClassFileConstants.JDK1_8) {
+			super.acceptModule(reader);
+			return;
+		}
+		if (reader != null) {
+			IModule moduleDecl = reader.getModuleDeclaration();
+			if (moduleDecl != null) {
+				if (this.modules == null) {
+					ModulesCache.put(this.modulePath, this.modules = new HashMap<String,IModule>());
+				}
+				this.modules.put(String.valueOf(moduleDecl.name()), moduleDecl);
+			}
+		}
+	}
+	@Override
+	public synchronized char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
+		// Ignore moduleName as this has nothing to do with modules (as of now)
+		if (this.packageCache != null)
+			return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName));
+
+		this.packageCache = new HashSet<>(41);
+		this.packageCache.add(Util.EMPTY_STRING);
+		try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
+			for (final java.nio.file.Path subdir: stream) {
+				String rel = subdir.getFileName().toString();
+				if (!rel.contains(this.releaseInHex)) {
+					continue;
+				}
+				try (DirectoryStream<java.nio.file.Path> stream2 = Files.newDirectoryStream(subdir)) {
+					for (final java.nio.file.Path subdir2: stream2) {
+						Files.walkFileTree(subdir2, new FileVisitor<java.nio.file.Path>() {
+							@Override
+							public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) throws IOException {
+								if (dir.getNameCount() <= 2)
+									return FileVisitResult.CONTINUE;
+								Path relative = dir.subpath(2, dir.getNameCount());
+								addToPackageCache(relative.toString(), false);
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult visitFile(java.nio.file.Path f, BasicFileAttributes attrs) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult visitFileFailed(java.nio.file.Path f, IOException exc) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+
+							@Override
+							public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc) throws IOException {
+								return FileVisitResult.CONTINUE;
+							}
+						});
+					}
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			// Rethrow
+		}
+		return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName));
+	}
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index 1753562..4b6788d 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -164,11 +164,14 @@
 	Set<String> knownFileNames;
 	protected boolean annotationsFromClasspath; // should annotation files be read from the classpath (vs. explicit separate path)?
 	private static HashMap<File, Classpath> JRT_CLASSPATH_CACHE = null;
-	
 	protected Map<String,Classpath> moduleLocations = new HashMap<>();
 
 	/** Tasks resulting from --add-reads or --add-exports command line options. */
 	Map<String,UpdatesByKind> moduleUpdates = new HashMap<>();
+	static final boolean isJRE12Plus;
+	static {
+		isJRE12Plus = "12".equals(System.getProperty("java.specification.version")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
 
 /*
 	classPathNames is a collection is Strings representing the full path of each class path
@@ -205,6 +208,8 @@
 		final Classpath classpath = paths[i];
 		try {
 			classpath.initialize();
+			for (String moduleName : classpath.getModuleNames(limitedModules))
+				this.moduleLocations.put(moduleName, classpath);
 			this.classpaths[counter++] = classpath;
 		} catch(IOException | InvalidPathException exception) {
 			// JRE 9 could throw an IAE if the linked JAR paths have invalid chars, such as ":"
@@ -256,7 +261,9 @@
 	return new ClasspathJrt(new File(convertPathSeparators(jdkHome)), true, accessRuleSet, null);
 }
 public static Classpath getOlderSystemRelease(String jdkHome, String release, AccessRuleSet accessRuleSet) {
-	return new ClasspathJep247(new File(convertPathSeparators(jdkHome)), release, accessRuleSet);
+	return isJRE12Plus ? 
+			new ClasspathJep247Jdk12(new File(convertPathSeparators(jdkHome)), release, accessRuleSet) :
+			new ClasspathJep247(new File(convertPathSeparators(jdkHome)), release, accessRuleSet);
 }
 public static Classpath getClasspath(String classpathName, String encoding,
 		boolean isSourceOnly, AccessRuleSet accessRuleSet,
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 4993c0b..d575841 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -212,7 +212,7 @@
 		private static final String INFO = "INFO"; //$NON-NLS-1$
 
 		public static final int XML = 1;
-		private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.005 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_005.dtd\">"; //$NON-NLS-1$
+		private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.006 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_006.dtd\">"; //$NON-NLS-1$
 		static {
 			try {
 				Class<?> c = IProblem.class;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index bb3bfb7..b11078d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -32,9 +32,7 @@
 	String externalAnnotationPath; // should be an absolute file system path
 
 	public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
-		this.binaryType = binaryType;
-		this.accessRestriction = accessRestriction;
-		this.moduleName = binaryType.getModule();
+		this(binaryType, accessRestriction, binaryType.getModule());
 	}
 
 	public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction, char[] module) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
index c5fcb08..1005de5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -355,6 +355,16 @@
 					return false;
 			}
 			return true;
+		case Binding.TYPE_PARAMETER:
+			// check compatibility with capture of ? super X
+			if (otherType.isCapture()) {
+				CaptureBinding otherCapture = (CaptureBinding) otherType;
+				TypeBinding otherLowerBound;
+				if ((otherLowerBound = otherCapture.lowerBound) != null) {
+					if (!otherLowerBound.isArrayType()) return false;
+					return isSubtypeOf(otherLowerBound, simulatingBugJDK8026527);
+				}
+			}
 	}
 	switch (otherType.leafComponentType().id) {
 	    case TypeIds.T_JavaLangObject :
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
index 481bbef..f6903f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/JRTUtil.java
@@ -22,6 +22,7 @@
 import java.nio.channels.ClosedByInterruptException;
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.FileSystems;
 import java.nio.file.FileVisitResult;
 import java.nio.file.FileVisitor;
@@ -59,7 +60,7 @@
 	public static int NOTIFY_ALL = NOTIFY_FILES | NOTIFY_PACKAGES | NOTIFY_MODULES;
 
 	// TODO: Java 9 Think about clearing the cache too.
-	private static Map<File, JrtFileSystem> images = null;
+	private static Map<String, JrtFileSystem> images = null;
 
 	private static final Object lock = new Object();
 
@@ -100,7 +101,11 @@
 	}
 
 	public static JrtFileSystem getJrtSystem(File image) {
-		Map<File, JrtFileSystem> i = images;
+		return getJrtSystem(image, null);
+	}
+
+	public static JrtFileSystem getJrtSystem(File image, String release) {
+		Map<String, JrtFileSystem> i = images;
 		if (images == null) {
 			synchronized (lock) {
 	            i = images;
@@ -110,10 +115,12 @@
 	        }
 		}
 		JrtFileSystem system = null;
+		String key = image.toString();
+		if (release != null) key = key + "|" + release; //$NON-NLS-1$
 		synchronized(i) {
-			if ((system = images.get(image)) == null) {
+			if ((system = images.get(key)) == null) {
 				try {
-					images.put(image, system = new JrtFileSystem(image));
+					images.put(key, system = JrtFileSystem.getNewJrtFileSystem(image, release));
 				} catch (IOException e) {
 					e.printStackTrace();
 					// Needs better error handling downstream? But for now, make sure 
@@ -138,8 +145,8 @@
 	 *  /modules/$MODULE/$PATH
 	 *  /packages/$PACKAGE/$MODULE 
 	 *  The latter provides quick look up of the module that contains a particular package. However,
-	 *  this method only notifies its clients of the entries within the modules sub-directory. The
-	 *  clients can decide which notifications they want to receive. See {@link JRTUtil#NOTIFY_ALL},
+	 *  this method only notifies its clients of the entries within the modules (latter) sub-directory. 
+	 *  Clients can decide which notifications they want to receive. See {@link JRTUtil#NOTIFY_ALL},
 	 *  {@link JRTUtil#NOTIFY_FILES}, {@link JRTUtil#NOTIFY_PACKAGES} and {@link JRTUtil#NOTIFY_MODULES}.
 	 *
 	 * @param image a java.io.File handle to the JRT image.
@@ -148,7 +155,10 @@
 	 * @throws IOException
 	 */
 	public static void walkModuleImage(File image, final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, int notify) throws IOException {
-		getJrtSystem(image).walkModuleImage(visitor, false, notify);
+		getJrtSystem(image, null).walkModuleImage(visitor, notify);
+	}
+	public static void walkModuleImage(File image, String release, final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, int notify) throws IOException {
+		getJrtSystem(image, release).walkModuleImage(visitor, notify);
 	}
 
 	public static InputStream getContentFromJrt(File jrt, String fileName, String module) throws IOException {
@@ -187,13 +197,138 @@
 		}
 	}
 }
+class JrtFileSystemWithOlderRelease extends JrtFileSystem {
+	final String release;
+	String releaseInHex = null;
+	//private Path releasePath = null;
+	private String[] subReleases = null;
+	protected Path modulePath = null;
+
+	/**
+	 * The jrt file system is based on the location of the JRE home whose libraries
+	 * need to be loaded.
+	 *
+	 * @param jrt the path to the root of the JRE whose libraries we are interested in.
+	 * @param release the older release where classes and modules should be searched for.
+	 * @throws IOException 
+	 */
+	JrtFileSystemWithOlderRelease(File jrt, String release) throws IOException {
+		super(jrt);
+		this.release = release;
+		initialize(jrt, release);
+	}
+	@Override
+	void initialize(File jdk) throws IOException {
+		// Just to make sure we don't do anything in super.initialize() 
+		// before setting this.release
+	}
+	void initialize(File jdk, String rel) throws IOException {
+		super.initialize(jdk);
+		this.fs = null;// reset and proceed, TODO: this is crude and need to be removed.
+		this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
+		Path ct = Paths.get(this.jdkHome, "lib", "ct.sym"); //$NON-NLS-1$ //$NON-NLS-2$
+		if (!Files.exists(ct)) {
+			return;
+		}
+		URI uri = URI.create("jar:file:" + ct.toUri().getRawPath()); //$NON-NLS-1$
+		try {
+			this.fs = FileSystems.getFileSystem(uri);
+		} catch(FileSystemNotFoundException fne) {
+			// Ignore and move on
+		}
+		if (this.fs == null) {
+			HashMap<String, ?> env = new HashMap<>();
+			try {
+				this.fs = FileSystems.newFileSystem(uri, env);
+			} catch (IOException e) {
+				return;
+			}
+		}
+		Path releasePath = this.fs.getPath("/"); //$NON-NLS-1$
+		if (!Files.exists(this.fs.getPath(this.releaseInHex))
+				|| Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
+			this.fs = null;
+		}
+		if (this.release != null) {
+			List<String> sub = new ArrayList<>();
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(releasePath)) {
+				for (final java.nio.file.Path subdir: stream) {
+					String r = subdir.getFileName().toString();
+					if (r.contains(this.releaseInHex)) {
+						sub.add(r);
+					} else {
+						continue;
+					}
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+				// Rethrow?
+			}
+			this.subReleases = sub.toArray(new String[sub.size()]);
+		}
+		// Ensure walkJrtForModules() is not called
+	}
+	@Override
+	void walkModuleImage(final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, final int notify) throws IOException {
+		if (this.subReleases != null && this.subReleases.length > 0) {
+			for (String rel : this.subReleases) {
+				Path p = this.fs.getPath(rel);
+				Files.walkFileTree(p, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
+					@Override
+					public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+							throws IOException {
+						int count = dir.getNameCount();
+						if (count == 1) {
+							return FileVisitResult.CONTINUE;
+						}
+						if (count == 2) {
+							// e.g. /9A/java.base
+							java.nio.file.Path mod = dir.getName(1);
+							if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0
+									&& JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) {
+								return FileVisitResult.SKIP_SUBTREE;
+							}
+							return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? FileVisitResult.CONTINUE
+									: visitor.visitModule(dir);
+						}
+						if ((notify & JRTUtil.NOTIFY_PACKAGES) == 0) {
+							// client is not interested in packages
+							return FileVisitResult.CONTINUE;
+						}
+						return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs);
+					}
+
+					@Override
+					public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs)
+							throws IOException {
+						if ((notify & JRTUtil.NOTIFY_FILES) == 0) {
+							return FileVisitResult.CONTINUE;
+						}
+						// This happens when a file in a default package is present. E.g. /modules/some.module/file.name
+						if (file.getNameCount() == 3) {
+							cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString());
+						}
+						return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs);
+					}
+				});
+			}
+		}
+	}
+	
+}
 class JrtFileSystem {
 	private final Map<String, String> packageToModule = new HashMap<String, String>();
 
 	private final Map<String, List<String>> packageToModules = new HashMap<String, List<String>>();
 
-	FileSystem jrtSystem = null;
-	
+	FileSystem fs = null;
+	Path modRoot = null;
+	String jdkHome = null;
+	public static JrtFileSystem getNewJrtFileSystem(File jrt, String release) throws IOException {
+		return (release == null) ? new JrtFileSystem(jrt) : 
+				new JrtFileSystemWithOlderRelease(jrt, release);
+				
+	}
 	/**
 	 * The jrt file system is based on the location of the JRE home whose libraries
 	 * need to be loaded.
@@ -201,18 +336,18 @@
 	 * @param jrt the path to the root of the JRE whose libraries we are interested in.
 	 * @throws IOException 
 	 */
-	public JrtFileSystem(File jrt) throws IOException {
+	JrtFileSystem(File jrt) throws IOException {
 		initialize(jrt);
 	}
 	void initialize(File jrt) throws IOException {
 		URL jrtPath = null;
-		String jdkHome = null;
+		this.jdkHome = null;
 		if (jrt.toString().endsWith(JRTUtil.JRT_FS_JAR)) {
 			jrtPath = jrt.toPath().toUri().toURL();
-			jdkHome = jrt.getParentFile().getParent();
+			this.jdkHome = jrt.getParentFile().getParent();
 		} else {
-			jdkHome = jrt.toPath().toString();
-			jrtPath = Paths.get(jdkHome, "lib", JRTUtil.JRT_FS_JAR).toUri().toURL(); //$NON-NLS-1$
+			this.jdkHome = jrt.toPath().toString();
+			jrtPath = Paths.get(this.jdkHome, "lib", JRTUtil.JRT_FS_JAR).toUri().toURL(); //$NON-NLS-1$
 
 		}
 		JRTUtil.MODULE_TO_LOAD = System.getProperty("modules.to.load"); //$NON-NLS-1$
@@ -220,13 +355,15 @@
 		if (javaVersion != null && javaVersion.startsWith("1.8")) { //$NON-NLS-1$
 			URLClassLoader loader = new URLClassLoader(new URL[] { jrtPath });
 			HashMap<String, ?> env = new HashMap<>();
-			this.jrtSystem = FileSystems.newFileSystem(JRTUtil.JRT_URI, env, loader);
+			this.fs = FileSystems.newFileSystem(JRTUtil.JRT_URI, env, loader);
 		} else {
 			HashMap<String, String> env = new HashMap<>();
-			env.put("java.home", jdkHome); //$NON-NLS-1$
-			this.jrtSystem = FileSystems.newFileSystem(JRTUtil.JRT_URI, env);
+			env.put("java.home", this.jdkHome); //$NON-NLS-1$
+			this.fs = FileSystems.newFileSystem(JRTUtil.JRT_URI, env);
 		}
-		walkModuleImage(null, true, 0 /* doesn't matter */);
+		this.modRoot = this.fs.getPath(JRTUtil.MODULES_SUBDIR);
+		// Set up the root directory wherere modules are located
+		walkJrtForModules();
 	}
 
 	public List<String> getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
@@ -279,7 +416,7 @@
 		String knownModule = this.packageToModule.get(qualifiedPackageName);
 		if (knownModule == null || (knownModule != JRTUtil.MULTIPLE && !knownModule.equals(module)))
 			return false;
-		Path packagePath = this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, qualifiedPackageName);
+		Path packagePath = this.fs.getPath(JRTUtil.MODULES_SUBDIR, module, qualifiedPackageName);
 		if (!Files.exists(packagePath))
 			return false;
 		// iterate files:
@@ -294,11 +431,11 @@
 
 	public InputStream getContentFromJrt(String fileName, String module) throws IOException {
 		if (module != null) {
-			return Files.newInputStream(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, fileName));
+			return Files.newInputStream(this.fs.getPath(JRTUtil.MODULES_SUBDIR, module, fileName));
 		}
 		String[] modules = getModules(fileName);
 		for (String mod : modules) {
-			return Files.newInputStream(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
+			return Files.newInputStream(this.fs.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
 		}
 		return null;
 	}
@@ -309,7 +446,7 @@
 		for (String mod : modules) {
 			if (moduleNameFilter != null && !moduleNameFilter.test(mod))
 				continue;
-			content = JRTUtil.safeReadBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
+			content = JRTUtil.safeReadBytes(this.fs.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
 			if (content != null) {
 				module = mod;
 				break;
@@ -330,7 +467,7 @@
 		} else {
 			String[] modules = getModules(fileName);
 			for (String mod : modules) {
-				content = JRTUtil.safeReadBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
+				content = JRTUtil.safeReadBytes(this.fs.getPath(JRTUtil.MODULES_SUBDIR, mod, fileName));
 				if (content != null) {
 					break;
 				}
@@ -339,7 +476,7 @@
 		return content;
 	}
 	private byte[] getClassfileBytes(String fileName, String module) throws IOException, ClassFormatException {
-		return JRTUtil.safeReadBytes(this.jrtSystem.getPath(JRTUtil.MODULES_SUBDIR, module, fileName));
+		return JRTUtil.safeReadBytes(this.fs.getPath(JRTUtil.MODULES_SUBDIR, module, fileName));
 	}
 	public ClassFileReader getClassfile(String fileName, String module, Predicate<String> moduleNameFilter) throws IOException, ClassFormatException {
 		ClassFileReader reader = null;
@@ -367,47 +504,12 @@
 		return reader;
 	}
 
-	void walkModuleImage(final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, boolean visitPackageMapping, final int notify) throws IOException {
-		Iterable<java.nio.file.Path> roots = this.jrtSystem.getRootDirectories();
+	void walkJrtForModules() throws IOException {
+		Iterable<java.nio.file.Path> roots = this.fs.getRootDirectories();
 		for (java.nio.file.Path path : roots) {
 			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
 				for (final java.nio.file.Path subdir: stream) {
-					if (subdir.toString().equals(JRTUtil.MODULES_SUBDIR)) {
-						if (visitPackageMapping) continue;
-						Files.walkFileTree(subdir, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
-							@Override
-							public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) throws IOException {
-								int count = dir.getNameCount();
-								if (count == 2) {
-									// e.g. /modules/java.base
-									java.nio.file.Path mod = dir.getName(1);
-									if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0 &&
-											JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) {
-										return FileVisitResult.SKIP_SUBTREE;
-									}
-									return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? 
-											FileVisitResult.CONTINUE : visitor.visitModule(mod);
-								}
-								if (dir == subdir || count < 3 || (notify & JRTUtil.NOTIFY_PACKAGES) == 0) {
-									// We are dealing with a module or not client is not interested in packages
-									return FileVisitResult.CONTINUE;
-								}
-								return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs);
-							}
-
-							@Override
-							public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException {
-								if ((notify & JRTUtil.NOTIFY_FILES) == 0)
-									return FileVisitResult.CONTINUE;
-								int count = file.getNameCount();
-								// This happens when a file in a default package is present. E.g. /modules/some.module/file.name
-								if (count == 3) {
-									cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString());
-								}
-								return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs);
-							}
-						});
-					} else if (visitPackageMapping) {
+					if (!subdir.toString().equals(JRTUtil.MODULES_SUBDIR)) {
 						Files.walkFileTree(subdir, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
 							@Override
 							public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException {
@@ -424,6 +526,42 @@
 			}
 		}
 	}
+	void walkModuleImage(final JRTUtil.JrtFileVisitor<java.nio.file.Path> visitor, final int notify) throws IOException {
+		Files.walkFileTree(this.modRoot, new JRTUtil.AbstractFileVisitor<java.nio.file.Path>() {
+			@Override
+			public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) throws IOException {
+				int count = dir.getNameCount();
+				if (count == 1) return FileVisitResult.CONTINUE;
+				if (count == 2) {
+					// e.g. /modules/java.base
+					java.nio.file.Path mod = dir.getName(1);
+					if ((JRTUtil.MODULE_TO_LOAD != null && JRTUtil.MODULE_TO_LOAD.length() > 0 &&
+							JRTUtil.MODULE_TO_LOAD.indexOf(mod.toString()) == -1)) {
+						return FileVisitResult.SKIP_SUBTREE;
+					}
+					return ((notify & JRTUtil.NOTIFY_MODULES) == 0) ? 
+							FileVisitResult.CONTINUE : visitor.visitModule(mod);
+				}
+				if ((notify & JRTUtil.NOTIFY_PACKAGES) == 0) {
+					// We are dealing with a module or not client is not interested in packages
+					return FileVisitResult.CONTINUE;
+				}
+				return visitor.visitPackage(dir.subpath(2, count), dir.getName(1), attrs);
+			}
+
+			@Override
+			public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException {
+				if ((notify & JRTUtil.NOTIFY_FILES) == 0)
+					return FileVisitResult.CONTINUE;
+				int count = file.getNameCount();
+				// This happens when a file in a default package is present. E.g. /modules/some.module/file.name
+				if (count == 3) {
+					cachePackage(JRTUtil.DEFAULT_PACKAGE, file.getName(1).toString());
+				}
+				return visitor.visitFile(file.subpath(2, file.getNameCount()), file.getName(1), attrs);
+			}
+		});
+	}
 
 	void cachePackage(String packageName, String module) {
 		packageName = packageName.intern();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index 0007007..750e067 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -1704,19 +1704,23 @@
 		if (!hasChildrenChanges(node)) {
 			return doVisitUnchangedChildren(node);
 		}
-
-		if (node.getAST().apiLevel() >= JLS9_INTERNAL && node.getModule() != null) {
-			rewriteNode(node, CompilationUnit.MODULE_PROPERTY, 0, ASTRewriteFormatter.NONE);
-			return false;
-		}
-		int startPos= rewriteNode(node, CompilationUnit.PACKAGE_PROPERTY, 0, ASTRewriteFormatter.NONE);
-
-		if (getChangeKind(node, CompilationUnit.PACKAGE_PROPERTY) == RewriteEvent.INSERTED) {
-			doTextInsert(0, getLineDelimiter(), getEditGroup(node, CompilationUnit.PACKAGE_PROPERTY));
+		int startPos = 0;
+		boolean isModuleInfo = node.getAST().apiLevel() >= JLS9_INTERNAL && node.getModule() != null;
+		
+		if (!isModuleInfo) {
+			startPos = rewriteNode(node, CompilationUnit.PACKAGE_PROPERTY, 0, ASTRewriteFormatter.NONE);
+	
+			if (getChangeKind(node, CompilationUnit.PACKAGE_PROPERTY) == RewriteEvent.INSERTED) {
+				doTextInsert(0, getLineDelimiter(), getEditGroup(node, CompilationUnit.PACKAGE_PROPERTY));
+			}
 		}
 
-		startPos= rewriteParagraphList(node, CompilationUnit.IMPORTS_PROPERTY, startPos, 0, 0, 2);
-		rewriteParagraphList(node, CompilationUnit.TYPES_PROPERTY, startPos, 0, -1, 2);
+		startPos = rewriteParagraphList(node, CompilationUnit.IMPORTS_PROPERTY, startPos, 0, 0, 2);
+		if (isModuleInfo) {
+			rewriteNode(node, CompilationUnit.MODULE_PROPERTY, startPos, ASTRewriteFormatter.NONE);
+		} else {
+			rewriteParagraphList(node, CompilationUnit.TYPES_PROPERTY, startPos, 0, -1, 2);
+		}
 		return false;
 	}
 
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index ab55daf..5201ed6 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -2542,6 +2542,12 @@
 	 * This method is used to handle deprecated preferences which might be replaced by
 	 * one or more preferences.
 	 * Depending on deprecated option handling policy, set the new formatting option(s).
+	 * <p>
+	 * Note: Also add deprecated preference keys in {@link org.eclipse.jdt.internal.core.JavaCorePreferenceInitializer#initializeDeprecatedOptions}
+	 * so that the formatter recognizes those deprecated options when used with project specific formatter profiles.
+	 * (see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=544776">Bug 544776</a>)
+	 * </p>
+	 * 
 	 * @param settings the given map
 	 * @deprecated
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 4ab376b..97be67e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -160,7 +160,6 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.SubMonitor;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.MultiRule;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.search.IJavaSearchConstants;
@@ -4615,11 +4614,7 @@
 			};
 			mainMonitor.subTask(Messages.javamodel_building_after_upgrade);
 			try {
-				ResourcesPlugin.getWorkspace().run(
-					runnable,
-					new MultiRule(Arrays.stream(projects).map(IJavaProject::getResource).toArray(ISchedulingRule[]::new)),
-					IWorkspace.AVOID_UPDATE,
-					mainMonitor.split(1));
+				ResourcesPlugin.getWorkspace().run(runnable, mainMonitor.split(1));
 			} catch (CoreException e) {
 				// could not touch all projects
 			}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 29f746a..0aa71be 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -34,7 +34,6 @@
 import org.eclipse.core.resources.IWorkspaceRunnable;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.jobs.MultiRule;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
@@ -902,7 +901,7 @@
 							}
 						};
 						try {
-							ResourcesPlugin.getWorkspace().run(runnable, new MultiRule(projectsToTouch), IWorkspace.AVOID_UPDATE, monitor);
+							ResourcesPlugin.getWorkspace().run(runnable, monitor);
 						} catch (CoreException e) {
 							throw new JavaModelException(e);
 						}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
index ed85f3b..cef00e7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -136,6 +136,9 @@
 	}
 
 	/**
+	 * Note: For deprecated formatter options, you may also add migration to their replacement options in 
+	 * {@link org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions#setDeprecatedOptions}.
+	 * 
 	 * @deprecated As using deprecated options
 	 */
 	private void initializeDeprecatedOptions() {
@@ -156,5 +159,42 @@
 				DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_LOCAL_VARIABLE,
 				DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_PARAMETER
 			});
+
+		deprecatedOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_BINARY_EXPRESSION,
+			new String[] {
+				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_MULTIPLICATIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ADDITIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_STRING_CONCATENATION,
+				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_BITWISE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_LOGICAL_OPERATOR,
+			});
+		deprecatedOptions.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_BINARY_OPERATOR,
+			new String[] {
+				DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_MULTIPLICATIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_ADDITIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_STRING_CONCATENATION,
+				DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_BITWISE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_LOGICAL_OPERATOR,
+			});
+		deprecatedOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR,
+			new String[] {
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MULTIPLICATIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ADDITIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_STRING_CONCATENATION,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SHIFT_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_RELATIONAL_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BITWISE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LOGICAL_OPERATOR,
+			});
+		deprecatedOptions.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR,
+			new String[] {
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_MULTIPLICATIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ADDITIVE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_STRING_CONCATENATION,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SHIFT_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_RELATIONAL_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BITWISE_OPERATOR,
+				DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_LOGICAL_OPERATOR,
+			});
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 09250fc..1c9dde2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -2985,9 +2985,9 @@
 		ArchiveValidity validity = getArchiveValidity(path);
 		IOException reason;
 		switch (validity) {
-			case BAD_FORMAT: reason = new ZipException(); break;
-			case FILE_NOT_FOUND: reason = new FileNotFoundException(); break;
-			case UNABLE_TO_READ: reason = new IOException(); break;
+			case BAD_FORMAT: reason = new ZipException("Bad format in archive: " + path); break; //$NON-NLS-1$
+			case FILE_NOT_FOUND: reason = new FileNotFoundException("Archive not found for path: " + path); break; //$NON-NLS-1$
+			case UNABLE_TO_READ: reason = new IOException("Unable to read archive: " + path); break; //$NON-NLS-1$
 			default: reason = null;
 		}
 		if (reason != 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 34ab941..50cfd27 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2018 IBM Corporation and others.
+ * Copyright (c) 2016, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -15,16 +15,9 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URI;
-import java.nio.file.DirectoryStream;
-import java.nio.file.FileSystemNotFoundException;
-import java.nio.file.FileSystems;
 import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -35,7 +28,6 @@
 import java.util.zip.ZipFile;
 
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
@@ -50,36 +42,29 @@
 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 {
 
 //private HashMap<String, SimpleSet> packagesInModule = null;
-private static HashMap<String, HashMap<String, SimpleSet>> PackageCache = new HashMap<>();
-private static HashMap<String, Set<IModule>> ModulesCache = new HashMap<>();
+protected static HashMap<String, HashMap<String, SimpleSet>> PackageCache = new HashMap<>();
+protected static HashMap<String, Set<IModule>> ModulesCache = new HashMap<>();
 String externalAnnotationPath;
-private ZipFile annotationZipFile;
+protected ZipFile annotationZipFile;
 String zipFilename; // keep for equals
 AccessRuleSet accessRuleSet;
-String release = null;
-String releaseInHex = null;
-private Path releasePath = null;
-private String[] subReleases = null;
-private java.nio.file.FileSystem fs = null;
 
 static final Set<String> NO_LIMIT_MODULES = new HashSet<>();
 
-public ClasspathJrt(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, String release) {
+/*
+ * Only for use from ClasspathJrtWithOlderRelease
+ */
+protected ClasspathJrt() {
+}
+public ClasspathJrt(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
 	this.zipFilename = zipFilename;
 	this.accessRuleSet = accessRuleSet;
 	if (externalAnnotationPath != null)
 		this.externalAnnotationPath = externalAnnotationPath.toString();
-	if (release != null && release.length() == 0) {
-		this.release = null;
-	} else {
-		this.release = release;
-	}
-	initialize();
 	loadModules(this);
 }
 /**
@@ -89,7 +74,7 @@
  */
 static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrt jrt) {
 	String zipFileName = jrt.zipFilename;
-	HashMap<String, SimpleSet> cache = PackageCache.get(zipFileName);
+	HashMap<String, SimpleSet> cache = PackageCache.get(jrt.getKey());
 	if (cache != null) {
 		return cache;
 	}
@@ -97,7 +82,7 @@
 	PackageCache.put(zipFileName, packagesInModule);
 	try {
 		final File imageFile = new File(zipFileName);
-		org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile,
+		org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile, 
 				new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
 			SimpleSet packageSet = null;
 			@Override
@@ -132,12 +117,11 @@
 }
 
 public static void loadModules(final ClasspathJrt jrt) {
-	String zipFileName = jrt.zipFilename;
-	Set<IModule> cache = ModulesCache.get(zipFileName);
+	Set<IModule> cache = ModulesCache.get(jrt.getKey());
 
 	if (cache == null) {
 		try {
-			final File imageFile = new File(zipFileName);
+			final File imageFile = new File(jrt.zipFilename);
 			org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile,
 					new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
 				SimpleSet packageSet = null;
@@ -174,70 +158,11 @@
 //		}
 	}
 }
-public void initialize() {
-	if (this.release == null) {
-		return;
-	}
-	this.release = getReleaseOptionFromCompliance(this.release);
-	this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
-	Path lib = Paths.get(this.zipFilename).getParent();
-	Path filePath = Paths.get(lib.toString(),  "ct.sym"); //$NON-NLS-1$
-	URI t = filePath.toUri();
-	if (!Files.exists(filePath)) {
-		return;
-	}
-	URI uri = URI.create("jar:file:" + t.getRawPath()); //$NON-NLS-1$
-	try {
-		this.fs = FileSystems.getFileSystem(uri);
-	} catch(FileSystemNotFoundException fne) {
-		// Ignore and move on
-	}
-	if (this.fs == null) {
-		HashMap<String, ?> env = new HashMap<>();
-		try {
-			this.fs = FileSystems.newFileSystem(uri, env);
-		} catch (IOException e) {
-			this.release = null;
-			return;
-		}
-	}
-	this.releasePath = this.fs.getPath("/"); //$NON-NLS-1$
-	if (!Files.exists(this.fs.getPath(this.releaseInHex))
-			|| Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
-		this.release = null;
-	}
-	if (this.release != null) {
-		List<String> sub = new ArrayList<>();
-		try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
-			for (final java.nio.file.Path subdir: stream) {
-				String rel = subdir.getFileName().toString();
-				if (rel.contains(this.releaseInHex)) {
-					sub.add(rel);
-				} else {
-					continue;
-				}
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-			// Rethrow
-		}
-		this.subReleases = sub.toArray(new String[sub.size()]);
-	}
-}
-private String getReleaseOptionFromCompliance(String comp) {
-	if (JavaCore.compareJavaVersions(comp, JavaCore.VERSION_1_5) <= 0) {
-		// For a JDK 9 and above, the minimum release we support is "6"
-		return "6"; //$NON-NLS-1$
-	}
-	int index = comp.indexOf("1."); //$NON-NLS-1$
-	if (index != -1) {
-		return comp.substring(index + 2, comp.length());
-	} else {
-		return comp;
-	}
+protected String getKey() {
+	return this.zipFilename;
 }
 void acceptModule(byte[] content) {
-	if (content == null)
+	if (content == null) 
 		return;
 	ClassFileReader reader = null;
 	try {
@@ -246,11 +171,12 @@
 		e.printStackTrace();
 	}
 	if (reader != null) {
+		String key = getKey();
 		IModule moduleDecl = reader.getModuleDeclaration();
 		if (moduleDecl != null) {
-			Set<IModule> cache = ModulesCache.get(this.zipFilename);
+			Set<IModule> cache = ModulesCache.get(key);
 			if (cache == null) {
-				ModulesCache.put(this.zipFilename, cache = new HashSet<IModule>());
+				ModulesCache.put(key, cache = new HashSet<IModule>());
 			}
 			cache.add(moduleDecl);
 		}
@@ -265,7 +191,6 @@
 		}
 		this.annotationZipFile = null;
 	}
-	this.fs = null;
 }
 
 @Override
@@ -273,9 +198,6 @@
 	if (this == o) return true;
 	if (!(o instanceof ClasspathJrt)) return false;
 	ClasspathJrt jar = (ClasspathJrt) o;
-	if (!Util.equalOrNull(this.release, jar.release)) {
-		return false;
-	}
 	if (this.accessRuleSet != jar.accessRuleSet)
 		if (this.accessRuleSet == null || !this.accessRuleSet.equals(jar.accessRuleSet))
 			return false;
@@ -288,46 +210,34 @@
 	if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case
 
 	try {
-		IBinaryType reader = null;
-		byte[] content = null;
 		String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
-		if (this.subReleases != null && this.subReleases.length > 0) {
-			qualifiedBinaryFileName = qualifiedBinaryFileName.replace(".class", ".sig"); //$NON-NLS-1$ //$NON-NLS-2$
-			for (String rel : this.subReleases) {
-				Path p = this.fs.getPath(rel, qualifiedBinaryFileName);
-				if (Files.exists(p)) {
-					content = JRTUtil.safeReadBytes(p);
-					if (content != null) {
-						reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
-						break;
-					}
-				}
-			}
-		} else {
-			reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName, moduleNameFilter);
-		}
-		if (reader != null) {
-			if (this.externalAnnotationPath != null) {
-				try {
-					if (this.annotationZipFile == null) {
-						this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(this.externalAnnotationPath, null);
-					}
-					reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath, fileNameWithoutExtension, this.annotationZipFile);
-				} catch (IOException e) {
-					// don't let error on annotations fail class reading
-				}
-			}
-			if (this.accessRuleSet == null)
-				return new NameEnvironmentAnswer(reader, null, reader.getModule());
-			return new NameEnvironmentAnswer(reader,
-					this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()),
-					reader.getModule());
-		}
+		IBinaryType reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName, moduleNameFilter);
+		return createAnswer(fileNameWithoutExtension, reader);
 	} catch (ClassFormatException e) { // treat as if class file is missing
 	} catch (IOException e) { // treat as if class file is missing
 	}
 	return null;
 }
+protected NameEnvironmentAnswer createAnswer(String fileNameWithoutExtension, IBinaryType reader) {
+	if (reader != null) {
+		if (this.externalAnnotationPath != null) {
+			try {
+				if (this.annotationZipFile == null) {
+					this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(this.externalAnnotationPath, null);
+				}
+				reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath, fileNameWithoutExtension, this.annotationZipFile);
+			} catch (IOException e) {
+				// don't let error on annotations fail class reading
+			}
+		}
+		if (this.accessRuleSet == null)
+			return new NameEnvironmentAnswer(reader, null, reader.getModule());
+		return new NameEnvironmentAnswer(reader,
+				this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()),
+				reader.getModule());
+	}
+	return null;
+}
 
 @Override
 public IPath getProjectRelativePath() {
@@ -341,7 +251,7 @@
 @Override
 public char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
 	List<String> moduleNames = JRTUtil.getModulesDeclaringPackage(new File(this.zipFilename), qualifiedPackageName, moduleName);
-	return CharOperation.toCharArrays(moduleNames);
+	return CharOperation.toCharArrays(moduleNames); 
 }
 @Override
 public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) {
@@ -374,7 +284,7 @@
 }
 @Override
 public IModule getModule(char[] moduleName) {
-	Set<IModule> modules = ModulesCache.get(this.zipFilename);
+	Set<IModule> modules = ModulesCache.get(getKey());
 	if (modules != null) {
 		for (IModule mod : modules) {
 			if (CharOperation.equals(mod.name(), moduleName))
@@ -391,7 +301,7 @@
 	return Collections.emptyList();
 }
 
-private Collection<String> selectModules(Set<String> keySet, Collection<String> limitModules) {
+protected Collection<String> selectModules(Set<String> keySet, Collection<String> limitModules) {
 	Collection<String> rootModules;
 	if (limitModules == NO_LIMIT_MODULES) {
 		rootModules = new HashSet<>(keySet);
@@ -408,7 +318,7 @@
 	return allModules;
 }
 
-private void addRequired(String mod, Set<String> allModules) {
+protected void addRequired(String mod, Set<String> allModules) {
 	IModule iMod = getModule(mod.toCharArray());
 	for (IModuleReference requiredRef : iMod.requires()) {
 		IModule reqMod = getModule(requiredRef.name());
@@ -421,7 +331,7 @@
 }
 @Override
 public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName) {
-	//
+	// 
 	return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false, null);
 }
 /** TEST ONLY */
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
new file mode 100644
index 0000000..a5d8446
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrtWithReleaseOption.java
@@ -0,0 +1,387 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.builder;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+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.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+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.JRTUtil;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public class ClasspathJrtWithReleaseOption extends ClasspathJrt {
+
+	final String release;
+	String releaseInHex;
+	private String[] subReleases;
+	private java.nio.file.FileSystem fs;
+	protected Path modulePath;
+	private String modPathString;
+	private boolean isJRE12Plus;
+
+	public ClasspathJrtWithReleaseOption(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath,
+			String release) throws CoreException {
+		super();
+		if (release == null || release.equals("")) { //$NON-NLS-1$
+			throw new IllegalArgumentException("--release argument can not be null"); //$NON-NLS-1$
+		}
+		this.zipFilename = zipFilename;
+		this.accessRuleSet = accessRuleSet;
+		if (externalAnnotationPath != null)
+			this.externalAnnotationPath = externalAnnotationPath.toString();
+		this.release = getReleaseOptionFromCompliance(release);
+		initialize();
+		loadModules(this);
+	}
+	/*
+	 * JDK 11 doesn't contain release 5. Hence
+	 * if the compliance is below 6, we simply return the lowest supported
+	 * release, which is 6.
+	 */
+	private String getReleaseOptionFromCompliance(String comp) {
+		if (JavaCore.compareJavaVersions(comp, JavaCore.VERSION_1_5) <= 0) {
+			return "6"; //$NON-NLS-1$
+		}
+		int index = comp.indexOf("1."); //$NON-NLS-1$
+		if (index != -1) {
+			return comp.substring(index + 2, comp.length());
+		} else {
+			return comp;
+		}
+	}
+	private boolean isJRE12Plus(Path path) {
+		try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path)) {
+			for (final java.nio.file.Path subdir : stream) {
+				String rel = subdir.getFileName().toString();
+				if (Files.exists(this.fs.getPath(rel, "system-modules"))) { //$NON-NLS-1$
+					int parseInt = Integer.parseInt(rel, 16);
+					return (parseInt > 11);
+				}
+			}
+		} catch (IOException e) {
+			this.fs = null;
+		}
+		return false; 
+	}
+	/*
+	 * Set up the paths where modules and regular classes need to be read. We need to deal with two different kind of
+	 * formats of cy.sym: Post JDK 12: ct.sym -> 9 -> java/ -> lang/* 9-modules -> java.base -> module-info.sig
+	 * 
+	 * From JDK 12 onward: ct.sym -> 9 -> java.base -> module-info.sig java/ -> lang/* Notably, 1) in JDK 12 modules
+	 * classes and ordinary classes are located in the same location 2) in JDK 12, ordinary classes are found inside
+	 * their respective modules
+	 * 
+	 */
+	protected void initialize() throws CoreException {
+		this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release)).toUpperCase();
+		Path lib = Paths.get(this.zipFilename).getParent();
+		Path filePath = Paths.get(lib.toString(), "ct.sym"); //$NON-NLS-1$
+		URI t = filePath.toUri();
+		if (!Files.exists(filePath)) {
+			return;
+		}
+		URI uri = URI.create("jar:file:" + t.getRawPath()); //$NON-NLS-1$
+		try {
+			this.fs = FileSystems.getFileSystem(uri);
+		} catch (FileSystemNotFoundException fne) {
+			// Ignore and move on
+		}
+		if (this.fs == null) {
+			HashMap<String, ?> env = new HashMap<>();
+			try {
+				this.fs = FileSystems.newFileSystem(uri, env);
+			} catch (IOException e) {
+				return;
+			}
+		}
+		Path releasePath = this.fs.getPath("/"); //$NON-NLS-1$
+		this.isJRE12Plus = isJRE12Plus(releasePath);
+		Path modPath = this.fs.getPath(this.releaseInHex + (this.isJRE12Plus ? "" : "-modules")); //$NON-NLS-1$ //$NON-NLS-2$
+		if (Files.exists(modPath)) {
+			this.modulePath = modPath;
+			this.modPathString = this.zipFilename + "|"+ modPath.toString(); //$NON-NLS-1$
+		}
+		
+		if (!Files.exists(releasePath.resolve(this.releaseInHex))) {
+			Exception e = new IllegalArgumentException("release " + this.release + " is not found in the system"); //$NON-NLS-1$//$NON-NLS-2$
+			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, e.getMessage(), e));
+		}
+		if (Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
+			this.fs = null;  // Fallback to default version
+			return;
+		}
+		if (this.release != null) {
+			List<String> sub = new ArrayList<>();
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(releasePath)) {
+				for (final java.nio.file.Path subdir : stream) {
+					String rel = subdir.getFileName().toString();
+					if (rel.contains(this.releaseInHex)) {
+						sub.add(rel);
+					} else {
+						continue;
+					}
+				}
+			} catch (IOException e) {
+				this.fs = null; // Fallback to default version
+			}
+			this.subReleases = sub.toArray(new String[sub.size()]);
+		}
+	}
+
+	static HashMap<String, SimpleSet> findPackagesInModules(final ClasspathJrtWithReleaseOption jrt) {
+		// 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 (jrt.fs == null || !jrt.isJRE12Plus) {
+			return ClasspathJrt.findPackagesInModules(jrt);
+		}
+		String zipFileName = jrt.zipFilename;
+		HashMap<String, SimpleSet> cache = PackageCache.get(jrt.modPathString);
+		if (cache != null) {
+			return cache;
+		}
+		final HashMap<String, SimpleSet> packagesInModule = new HashMap<>();
+		PackageCache.put(jrt.modPathString, packagesInModule);
+		try {
+			final File imageFile = new File(zipFileName);
+			org.eclipse.jdt.internal.compiler.util.JRTUtil.walkModuleImage(imageFile, jrt.release,
+					new org.eclipse.jdt.internal.compiler.util.JRTUtil.JrtFileVisitor<Path>() {
+						SimpleSet packageSet = null;
+
+						@Override
+						public FileVisitResult visitPackage(Path dir, Path mod, BasicFileAttributes attrs)
+								throws IOException {
+							ClasspathJar.addToPackageSet(this.packageSet, dir.toString(), true);
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult visitFile(Path file, Path mod, BasicFileAttributes attrs)
+								throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult visitModule(Path mod) throws IOException {
+							String name = mod.getName(1).toString();
+							this.packageSet = new SimpleSet(41);
+							this.packageSet.add(""); //$NON-NLS-1$
+							packagesInModule.put(name, this.packageSet);
+							return FileVisitResult.CONTINUE;
+						}
+					}, JRTUtil.NOTIFY_PACKAGES | JRTUtil.NOTIFY_MODULES);
+		} catch (IOException e) {
+			// return empty handed
+		}
+		return packagesInModule;
+	}
+
+	public static void loadModules(final ClasspathJrtWithReleaseOption jrt) {
+		if (jrt.fs == null || !jrt.isJRE12Plus) {
+			ClasspathJrt.loadModules(jrt);
+			return;
+		}
+		if (jrt.modPathString == null)
+			return;
+		Set<IModule> cache = ModulesCache.get(jrt.modPathString);
+		if (cache == null) {
+			try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(jrt.modulePath)) {
+				for (final java.nio.file.Path subdir : stream) {
+
+					Files.walkFileTree(subdir, Collections.EMPTY_SET, 1, new FileVisitor<java.nio.file.Path>() {
+						@Override
+						public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+								throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult visitFile(java.nio.file.Path f, BasicFileAttributes attrs)
+								throws IOException {
+							byte[] content = null;
+							if (Files.exists(f)) {
+								content = JRTUtil.safeReadBytes(f);
+								if (content == null)
+									return FileVisitResult.CONTINUE;
+								jrt.acceptModule(content);
+							}
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult visitFileFailed(java.nio.file.Path f, IOException exc)
+								throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+
+						@Override
+						public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc)
+								throws IOException {
+							return FileVisitResult.CONTINUE;
+						}
+					});
+				}
+			} catch (IOException e) {
+				// Nothing much to do
+			}
+		}
+	}
+
+
+	@Override
+	public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName,
+			String qualifiedBinaryFileName, boolean asBinaryOnly, Predicate<String> moduleNameFilter) {
+
+		if (this.fs == null) {
+			return super.findClass(binaryFileName, qualifiedPackageName, moduleName, qualifiedBinaryFileName,
+					asBinaryOnly, moduleNameFilter);
+		}
+		if (!isPackage(qualifiedPackageName, moduleName))
+			return null; // most common case
+
+		try {
+			IBinaryType reader = null;
+			byte[] content = null;
+			String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0,
+												qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+			if (this.subReleases != null && this.subReleases.length > 0) {
+				qualifiedBinaryFileName = qualifiedBinaryFileName.replace(".class", ".sig"); //$NON-NLS-1$ //$NON-NLS-2$
+				outer: for (String rel : this.subReleases) {
+					Path p = null;
+					inner: if (this.isJRE12Plus) {
+						if (moduleName != null) {
+							p = this.fs.getPath(rel, moduleName, qualifiedBinaryFileName);
+						} 
+						else {
+							try (DirectoryStream<java.nio.file.Path> stream = Files
+									.newDirectoryStream(this.fs.getPath(rel))) {
+								for (final java.nio.file.Path subdir : stream) {
+									p = subdir.resolve(qualifiedBinaryFileName);
+									if (Files.exists(p)) {
+										if (subdir.getNameCount() == 2 ) {
+											moduleName = subdir.getName(1).toString();
+										}
+										break inner;
+									}
+								}
+							}
+						}
+					} else {
+						p = this.fs.getPath(rel, qualifiedBinaryFileName);
+					}
+					if (Files.exists(p)) {
+						content = JRTUtil.safeReadBytes(p);
+						if (content != null) {
+							reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
+							if (moduleName != null)
+								((ClassFileReader) reader).moduleName = moduleName.toCharArray();
+							break outer;
+						}
+					}
+				}
+			} else {
+				reader = ClassFileReader.readFromModule(new File(this.zipFilename), moduleName, qualifiedBinaryFileName,
+						moduleNameFilter);
+			}
+			return createAnswer(fileNameWithoutExtension, reader);
+		} catch (ClassFormatException e) { 
+			// treat as if class file is missing
+		} catch (IOException e) { 
+			// treat as if class file is missing
+		}
+		return null;
+	}
+
+	@Override
+	public Collection<String> getModuleNames(Collection<String> limitModules) {
+		HashMap<String, SimpleSet> cache = findPackagesInModules(this);
+		if (cache != null)
+			return selectModules(cache.keySet(), limitModules);
+		return Collections.emptyList();
+	}
+
+	@Override
+	public void cleanup() {
+		try {
+			super.reset();
+		} finally {
+			// The same file system is also used in JRTUtil, so don't close it here.
+			this.fs = null;
+		}
+	}
+
+	@Override
+	public boolean hasModule() {
+		return this.modPathString != null;
+	}
+
+	@Override
+	protected String getKey() {
+		return this.modPathString;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o)
+			return true;
+		if (!(o instanceof ClasspathJrtWithReleaseOption))
+			return false;
+		ClasspathJrtWithReleaseOption jar = (ClasspathJrtWithReleaseOption) o;
+		if (!Util.equalOrNull(this.release, jar.release)) {
+			return false;
+		}
+		return super.equals(o);
+	}
+
+	@Override
+	public int hashCode() {
+		int hash = this.zipFilename == null ? super.hashCode() : this.zipFilename.hashCode();
+		return Util.combineHashCodes(hash, this.release.hashCode());
+	}
+
+	@Override
+	public String toString() {
+		String start = "Classpath jrt file " + this.zipFilename + " with --release option " + this.release; //$NON-NLS-1$ //$NON-NLS-2$
+		return start;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index d501e43..52cd7e0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -23,6 +23,7 @@
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
@@ -141,8 +142,9 @@
 				new ClasspathMultiReleaseJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule, compliance));
 
 }
-static ClasspathJrt forJrtSystem(String jrtPath, AccessRuleSet accessRuleSet, IPath annotationsPath, String release) {
-	return new ClasspathJrt(jrtPath, accessRuleSet, annotationsPath, release);
+public static ClasspathJrt forJrtSystem(String jrtPath, AccessRuleSet accessRuleSet, IPath annotationsPath, String release) throws CoreException {
+	return (release == null || release.equals("")) ? new ClasspathJrt(jrtPath, accessRuleSet, annotationsPath) : //$NON-NLS-1$
+						new ClasspathJrtWithReleaseOption(jrtPath, accessRuleSet, annotationsPath, release);
 }
 
 public static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index e1ec43d..a760438 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -18,8 +18,7 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.preferences.InstanceScope;
+
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
@@ -34,7 +33,6 @@
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class JavaBuilder extends IncrementalProjectBuilder {
 
-public static final String PREF_NULL_SCHEDULING_RULE = "useNullSchedulingRule"; //$NON-NLS-1$
 IProject currentProject;
 JavaProject javaProject;
 IWorkspaceRoot workspaceRoot;
@@ -155,7 +153,7 @@
 	}
 }
 
-public static State readState(IProject project, DataInputStream in) throws IOException {
+public static State readState(IProject project, DataInputStream in) throws IOException, CoreException {
 	return State.read(project, in);
 }
 
@@ -828,14 +826,6 @@
 		: "JavaBuilder for " + this.currentProject.getName(); //$NON-NLS-1$
 }
 
-	@Override
-	public ISchedulingRule getRule(int kind, Map<String, String> args) {
-		if (InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID).getBoolean(PREF_NULL_SCHEDULING_RULE, false)) {
-			return null;
-		}
-		return super.getRule(kind, args);
-	}
-
 //{ObjectTeams:
 /**
  * @param path
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index 0b6535c..d6e6b4f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -58,7 +58,7 @@
 private StringSet structurallyChangedTypes;
 public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
 
-public static final byte VERSION = 0x0021;
+public static final byte VERSION = 0x0022;
 
 static final byte SOURCE_FOLDER = 1;
 static final byte BINARY_FOLDER = 2;
@@ -235,7 +235,7 @@
 	this.typeLocators.removeKey(qualifiedTypeNameToRemove);
 }
 
-static State read(IProject project, DataInputStream in) throws IOException {
+static State read(IProject project, DataInputStream in) throws IOException, CoreException {
 	if (JavaBuilder.DEBUG)
 		System.out.println("About to read state " + project.getName()); //$NON-NLS-1$
 	if (VERSION != in.readByte()) {
@@ -570,13 +570,20 @@
 			out.writeBoolean(jar.isOnModulePath);
 			out.writeUTF(jar.compliance == null ? "" : jar.compliance); //$NON-NLS-1$
 			
-		} else {
+		} else if (c instanceof ClasspathJrt) {
 			ClasspathJrt jrt = (ClasspathJrt) c;
 			out.writeByte(EXTERNAL_JAR);
 			out.writeUTF(jrt.zipFilename);
 			writeRestriction(jrt.accessRuleSet, out);
 			out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
-			out.writeUTF(jrt.release != null ? jrt.release : ""); //$NON-NLS-1$
+			out.writeUTF(""); //$NON-NLS-1$
+		} else {
+			ClasspathJrtWithReleaseOption jrt = (ClasspathJrtWithReleaseOption) c;
+			out.writeByte(EXTERNAL_JAR);
+			out.writeUTF(jrt.zipFilename);
+			writeRestriction(jrt.accessRuleSet, out);
+			out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
+			out.writeUTF(jrt.release);
 		}
 		char[] patchName = c.patchModuleName == null ? CharOperation.NO_CHAR : c.patchModuleName.toCharArray();
 		writeName(patchName, out);
@@ -682,13 +689,20 @@
 				out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$
 				out.writeBoolean(jar.isOnModulePath);
 				out.writeUTF(jar.compliance != null ? jar.compliance : ""); //$NON-NLS-1$
-			} else {
+			} else if (c instanceof ClasspathJrt) {
 				ClasspathJrt jrt = (ClasspathJrt) c;
 				out.writeByte(EXTERNAL_JAR);
 				out.writeUTF(jrt.zipFilename);
 				writeRestriction(jrt.accessRuleSet, out);
 				out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
-				out.writeUTF(jrt.release != null ? jrt.release : ""); //$NON-NLS-1$
+				out.writeUTF(""); //$NON-NLS-1$
+			} else {
+				ClasspathJrtWithReleaseOption jrt = (ClasspathJrtWithReleaseOption) c;
+				out.writeByte(EXTERNAL_JAR);
+				out.writeUTF(jrt.zipFilename);
+				writeRestriction(jrt.accessRuleSet, out);
+				out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
+				out.writeUTF(jrt.release);
 			}
 		}
 
diff --git a/org.eclipse.jdt.core/schema/compiler.dtd b/org.eclipse.jdt.core/schema/compiler.dtd
index a82ade0..4cc5e13 100644
--- a/org.eclipse.jdt.core/schema/compiler.dtd
+++ b/org.eclipse.jdt.core/schema/compiler.dtd
@@ -69,7 +69,8 @@
 			   optionKey  CDATA #IMPLIED
 >
 <!ATTLIST classfile path CDATA #REQUIRED>
-<!ATTLIST error message CDATA #REQUIRED>
+<!ATTLIST error message CDATA #REQUIRED
+				path    CDATA #IMPLIED>
 <!ATTLIST warning message CDATA #REQUIRED>
 <!ATTLIST problem_summary problems CDATA #REQUIRED
                           errors   CDATA #REQUIRED
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index a61e40a..db613ca 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -49,7 +49,6 @@
 import org.eclipse.jdt.internal.core.JrtPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.NameLookup;
 import org.eclipse.jdt.internal.core.PackageFragmentRoot;
-import org.eclipse.jdt.internal.core.builder.ClasspathJrt;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -162,7 +161,7 @@
 			IJavaProject project = (IJavaProject) root.getParent();
 			String compliance = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
 			cp = (root instanceof JrtPackageFragmentRoot) ? 
-					new ClasspathJrt(path.toOSString(), rawClasspathEntry.getAccessRuleSet(), 
+					ClasspathLocation.forJrtSystem(path.toOSString(), rawClasspathEntry.getAccessRuleSet(), 
 							ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, project.getProject(), true), compliance) :
 									ClasspathLocation.forLibrary(manager.getZipFile(path), rawClasspathEntry.getAccessRuleSet(),
 												ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry,