changeset 14459:b2d898bbd0c4

Merge
author amurillo
date Fri, 22 Apr 2016 01:04:01 -0700
parents 35ce2ada6b0a 6c107c537b84
children ce87b09f35dd 8bc8f99ed902
files src/java.base/share/classes/java/lang/Thread.java src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileAttributes.java src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileAttributes.java src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedPath.java src/java.base/share/classes/jdk/internal/jrtfs/SystemImages.java src/java.base/share/classes/sun/reflect/AccessorGenerator.java src/java.base/share/classes/sun/reflect/BootstrapConstructorAccessorImpl.java src/java.base/share/classes/sun/reflect/ByteVector.java src/java.base/share/classes/sun/reflect/ByteVectorFactory.java src/java.base/share/classes/sun/reflect/ByteVectorImpl.java src/java.base/share/classes/sun/reflect/CallerSensitive.java src/java.base/share/classes/sun/reflect/ClassDefiner.java src/java.base/share/classes/sun/reflect/ClassFileAssembler.java src/java.base/share/classes/sun/reflect/ClassFileConstants.java src/java.base/share/classes/sun/reflect/ConstantPool.java src/java.base/share/classes/sun/reflect/ConstructorAccessor.java src/java.base/share/classes/sun/reflect/ConstructorAccessorImpl.java src/java.base/share/classes/sun/reflect/DelegatingConstructorAccessorImpl.java src/java.base/share/classes/sun/reflect/DelegatingMethodAccessorImpl.java src/java.base/share/classes/sun/reflect/FieldAccessor.java src/java.base/share/classes/sun/reflect/FieldAccessorImpl.java src/java.base/share/classes/sun/reflect/FieldInfo.java src/java.base/share/classes/sun/reflect/InstantiationExceptionConstructorAccessorImpl.java src/java.base/share/classes/sun/reflect/Label.java src/java.base/share/classes/sun/reflect/LangReflectAccess.java src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java src/java.base/share/classes/sun/reflect/MethodAccessor.java src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java src/java.base/share/classes/sun/reflect/MethodAccessorImpl.java src/java.base/share/classes/sun/reflect/NativeConstructorAccessorImpl.java src/java.base/share/classes/sun/reflect/NativeMethodAccessorImpl.java src/java.base/share/classes/sun/reflect/Reflection.java src/java.base/share/classes/sun/reflect/ReflectionFactory.java src/java.base/share/classes/sun/reflect/SerializationConstructorAccessorImpl.java src/java.base/share/classes/sun/reflect/SignatureIterator.java src/java.base/share/classes/sun/reflect/UTF8.java src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorFactory.java src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeObjectFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedObjectFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticObjectFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticObjectFieldAccessorImpl.java src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java src/jdk.rmic/share/classes/jdk/rmi/rmic/Main.java test/java/util/ServiceLoader/modules/BasicTest.java test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java test/sun/reflect/CallerSensitive/CallerSensitiveFinder.java test/sun/reflect/CallerSensitive/MissingCallerSensitive.java test/sun/reflect/Reflection/GetCallerClass.java test/sun/reflect/Reflection/GetCallerClassTest.java test/sun/reflect/Reflection/GetCallerClassTest.sh test/sun/reflect/constantPool/ConstantPoolTest.java test/sun/reflect/constantPool/ConstantPoolTestDummy.jasm
diffstat 602 files changed, 29820 insertions(+), 16689 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Apr 21 15:04:00 2016 -0400
+++ b/.hgtags	Fri Apr 22 01:04:01 2016 -0700
@@ -357,3 +357,4 @@
 1565a0efe6f0ca411a6df277df1e069431c60988 jdk-9+112
 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113
 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114
+35225b837d66582037eeadeb471c13235dfd793d jdk-9+115
--- a/make/data/fontconfig/windows.fontconfig.properties	Thu Apr 21 15:04:00 2016 -0400
+++ b/make/data/fontconfig/windows.fontconfig.properties	Fri Apr 22 01:04:01 2016 -0700
@@ -37,6 +37,7 @@
 allfonts.chinese-hkscs=MingLiU_HKSCS
 allfonts.chinese-ms950-extb=MingLiU-ExtB
 allfonts.devanagari=Mangal
+allfonts.kannada=Tunga
 allfonts.dingbats=Wingdings
 allfonts.lucida=Lucida Sans Regular
 allfonts.symbol=Symbol
@@ -239,11 +240,11 @@
 
 sequence.fallback=lucida,symbols,\
                   chinese-ms950,chinese-hkscs,chinese-ms936,chinese-gb18030,\
-                  japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian
+                  japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian,kannada
 
 # Exclusion Ranges
 
-exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff
+exclusion.alphabetic=0700-1e9f,1f00-2017,2020-20ab,20ad-20b8,20bb-20bc,20be-f8ff
 exclusion.chinese-gb18030=0390-03d6,2200-22ef,2701-27be
 exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
 
@@ -295,6 +296,7 @@
 
 filename.Lucida_Sans_Regular=LucidaSansRegular.ttf
 filename.Mangal=MANGAL.TTF
+filename.Tunga=TUNGA.TTF
 filename.Symbol=SYMBOL.TTF
 filename.Wingdings=WINGDING.TTF
 
--- a/make/launcher/Launcher-jdk.rmic.gmk	Thu Apr 21 15:04:00 2016 -0400
+++ b/make/launcher/Launcher-jdk.rmic.gmk	Fri Apr 22 01:04:01 2016 -0700
@@ -26,6 +26,6 @@
 include LauncherCommon.gmk
 
 $(eval $(call SetupBuildLauncher, rmic, \
-    MAIN_CLASS := jdk.rmi.rmic.Main, \
+    MAIN_CLASS := sun.rmi.rmic.Main, \
     CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
 ))
--- a/make/mapfiles/libjava/mapfile-vers	Thu Apr 21 15:04:00 2016 -0400
+++ b/make/mapfiles/libjava/mapfile-vers	Fri Apr 22 01:04:01 2016 -0700
@@ -236,32 +236,32 @@
 		Java_jdk_internal_misc_Signal_findSignal0;
 		Java_jdk_internal_misc_Signal_handle0;
 		Java_jdk_internal_misc_Signal_raise0;
-              Java_sun_reflect_ConstantPool_getClassAt0;
-              Java_sun_reflect_ConstantPool_getClassAtIfLoaded0;
-              Java_sun_reflect_ConstantPool_getClassRefIndexAt0;
-              Java_sun_reflect_ConstantPool_getDoubleAt0;
-              Java_sun_reflect_ConstantPool_getFieldAt0;
-              Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0;
-              Java_sun_reflect_ConstantPool_getFloatAt0;
-              Java_sun_reflect_ConstantPool_getIntAt0;
-              Java_sun_reflect_ConstantPool_getLongAt0;
-              Java_sun_reflect_ConstantPool_getMemberRefInfoAt0;
-              Java_sun_reflect_ConstantPool_getMethodAt0;
-              Java_sun_reflect_ConstantPool_getMethodAtIfLoaded0;
-              Java_sun_reflect_ConstantPool_getNameAndTypeRefIndexAt0;
-              Java_sun_reflect_ConstantPool_getNameAndTypeRefInfoAt0;
-              Java_sun_reflect_ConstantPool_getSize0;
-              Java_sun_reflect_ConstantPool_getStringAt0;
-              Java_sun_reflect_ConstantPool_getTagAt0;
-              Java_sun_reflect_ConstantPool_getUTF8At0;
+              Java_jdk_internal_reflect_ConstantPool_getClassAt0;
+              Java_jdk_internal_reflect_ConstantPool_getClassAtIfLoaded0;
+              Java_jdk_internal_reflect_ConstantPool_getClassRefIndexAt0;
+              Java_jdk_internal_reflect_ConstantPool_getDoubleAt0;
+              Java_jdk_internal_reflect_ConstantPool_getFieldAt0;
+              Java_jdk_internal_reflect_ConstantPool_getFieldAtIfLoaded0;
+              Java_jdk_internal_reflect_ConstantPool_getFloatAt0;
+              Java_jdk_internal_reflect_ConstantPool_getIntAt0;
+              Java_jdk_internal_reflect_ConstantPool_getLongAt0;
+              Java_jdk_internal_reflect_ConstantPool_getMemberRefInfoAt0;
+              Java_jdk_internal_reflect_ConstantPool_getMethodAt0;
+              Java_jdk_internal_reflect_ConstantPool_getMethodAtIfLoaded0;
+              Java_jdk_internal_reflect_ConstantPool_getNameAndTypeRefIndexAt0;
+              Java_jdk_internal_reflect_ConstantPool_getNameAndTypeRefInfoAt0;
+              Java_jdk_internal_reflect_ConstantPool_getSize0;
+              Java_jdk_internal_reflect_ConstantPool_getStringAt0;
+              Java_jdk_internal_reflect_ConstantPool_getTagAt0;
+              Java_jdk_internal_reflect_ConstantPool_getUTF8At0;
 		Java_java_io_Console_istty;
 		Java_java_io_Console_encoding;
                 Java_java_io_Console_echo;
-		Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
-		Java_sun_reflect_NativeMethodAccessorImpl_invoke0;
-		Java_sun_reflect_Reflection_getCallerClass__;
-		Java_sun_reflect_Reflection_getCallerClass__I;
-		Java_sun_reflect_Reflection_getClassAccessFlags;
+		Java_jdk_internal_reflect_NativeConstructorAccessorImpl_newInstance0;
+		Java_jdk_internal_reflect_NativeMethodAccessorImpl_invoke0;
+		Java_jdk_internal_reflect_Reflection_getCallerClass__;
+		Java_jdk_internal_reflect_Reflection_getCallerClass__I;
+		Java_jdk_internal_reflect_Reflection_getClassAccessFlags;
 		Java_jdk_internal_misc_VM_latestUserDefinedLoader;
                 Java_jdk_internal_misc_VM_getuid;
                 Java_jdk_internal_misc_VM_geteuid;
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java	Fri Apr 22 01:04:01 2016 -0700
@@ -102,8 +102,8 @@
 
     @Override
     FileTypeDetector getFileTypeDetector() {
-        Path userMimeTypes = Paths.get(AccessController.doPrivileged(
-            new GetPropertyAction("user.home")), ".mime.types");
+        String userHome = GetPropertyAction.getProperty("user.home");
+        Path userMimeTypes = Paths.get(userHome, ".mime.types");
         Path etcMimeTypes = Paths.get("/etc/mime.types");
 
         return chain(new GioFileTypeDetector(),
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Fri Apr 22 01:04:01 2016 -0700
@@ -32,9 +32,9 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import java.io.FileDescriptor;
 import java.util.Iterator;
 import java.util.LinkedList;
+import sun.security.action.GetPropertyAction;
 
 /*
  * struct kevent {           // 32-bit    64-bit
@@ -84,10 +84,8 @@
     static {
         IOUtil.load();
         initStructSizes();
-        String datamodel = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetPropertyAction("sun.arch.data.model")
-        );
-        is64bit = datamodel.equals("64");
+        String datamodel = GetPropertyAction.getProperty("sun.arch.data.model");
+        is64bit = "64".equals(datamodel);
     }
 
     KQueueArrayWrapper() {
--- a/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java	Fri Apr 22 01:04:01 2016 -0700
@@ -28,7 +28,6 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.spi.FileTypeDetector;
-import java.security.AccessController;
 import sun.security.action.GetPropertyAction;
 
 /**
@@ -47,8 +46,8 @@
 
     @Override
     FileTypeDetector getFileTypeDetector() {
-        Path userMimeTypes = Paths.get(AccessController.doPrivileged(
-            new GetPropertyAction("user.home")), ".mime.types");
+        Path userMimeTypes = Paths.get(
+            GetPropertyAction.getProperty("user.home"), ".mime.types");
 
         return chain(new MimeTypesFileTypeDetector(userMimeTypes),
                      new UTIFileTypeDetector());
--- a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Fri Apr 22 01:04:01 2016 -0700
@@ -71,6 +71,17 @@
         initialize(2048, null);
     }
 
+    private static void checkKeySize(int keysize)
+            throws InvalidParameterException {
+
+        if ((keysize < 512) || (keysize > 8192) || ((keysize & 0x3F) != 0)) {
+            throw new InvalidParameterException(
+                    "DH key size must be multiple of 64, and can only range " +
+                    "from 512 to 8192 (inclusive). " +
+                    "The specific key size " + keysize + " is not supported");
+        }
+    }
+
     /**
      * Initializes this key pair generator for a certain keysize and source of
      * randomness.
@@ -80,16 +91,22 @@
      * @param random the source of randomness
      */
     public void initialize(int keysize, SecureRandom random) {
-        if ((keysize < 512) || (keysize > 2048) || (keysize % 64 != 0)) {
-            throw new InvalidParameterException("Keysize must be multiple "
-                                                + "of 64, and can only range "
-                                                + "from 512 to 2048 "
-                                                + "(inclusive)");
+        checkKeySize(keysize);
+
+        // Use the built-in parameters (ranging from 512 to 8192)
+        // when available.
+        this.params = ParameterCache.getCachedDHParameterSpec(keysize);
+
+        // Due to performance issue, only support DH parameters generation
+        // up to 1024 bits.
+        if ((this.params == null) && (keysize > 1024)) {
+            throw new InvalidParameterException(
+                "Unsupported " + keysize + "-bit DH parameter generation");
         }
+
         this.pSize = keysize;
         this.lSize = 0;
         this.random = random;
-        this.params = null;
     }
 
     /**
@@ -115,11 +132,10 @@
 
         params = (DHParameterSpec)algParams;
         pSize = params.getP().bitLength();
-        if ((pSize < 512) || (pSize > 2048) ||
-            (pSize % 64 != 0)) {
-            throw new InvalidAlgorithmParameterException
-                ("Prime size must be multiple of 64, and can only range "
-                 + "from 512 to 2048 (inclusive)");
+        try {
+            checkKeySize(pSize);
+        } catch (InvalidParameterException ipe) {
+            throw new InvalidAlgorithmParameterException(ipe.getMessage());
         }
 
         // exponent size is optional, could be 0
@@ -164,7 +180,7 @@
         }
 
         BigInteger x;
-        BigInteger pMinus2 = p.subtract(BigInteger.valueOf(2));
+        BigInteger pMinus2 = p.subtract(BigInteger.TWO);
 
         //
         // PKCS#3 section 7.1 "Private-value generation"
--- a/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Fri Apr 22 01:04:01 2016 -0700
@@ -25,6 +25,7 @@
 
 package com.sun.crypto.provider;
 
+import java.math.BigInteger;
 import java.security.*;
 import java.security.spec.*;
 import javax.crypto.spec.DHParameterSpec;
@@ -46,8 +47,7 @@
  * @see java.security.spec.AlgorithmParameterSpec
  * @see DHParameters
  */
-public final class DHParameterGenerator
-extends AlgorithmParameterGeneratorSpi {
+public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi {
 
     // The size in bits of the prime modulus
     private int primeSize = 2048;
@@ -59,12 +59,16 @@
     private SecureRandom random = null;
 
     private static void checkKeySize(int keysize)
-        throws InvalidAlgorithmParameterException {
-        if ((keysize != 2048) &&
-            ((keysize < 512) || (keysize > 1024) || (keysize % 64 != 0))) {
-            throw new InvalidAlgorithmParameterException(
-                "Keysize must be multiple of 64 ranging from "
-                + "512 to 1024 (inclusive), or 2048");
+            throws InvalidParameterException {
+
+        boolean supported = ((keysize == 2048) || (keysize == 3072) ||
+            ((keysize >= 512) && (keysize <= 1024) && ((keysize & 0x3F) == 0)));
+
+        if (!supported) {
+            throw new InvalidParameterException(
+                    "DH key size must be multiple of 64 and range " +
+                    "from 512 to 1024 (inclusive), or 2048, 3072. " +
+                    "The specific key size " + keysize + " is not supported");
         }
     }
 
@@ -76,13 +80,9 @@
      * @param keysize the keysize (size of prime modulus) in bits
      * @param random the source of randomness
      */
+    @Override
     protected void engineInit(int keysize, SecureRandom random) {
-        // Re-uses DSA parameters and thus have the same range
-        try {
-            checkKeySize(keysize);
-        } catch (InvalidAlgorithmParameterException ex) {
-            throw new InvalidParameterException(ex.getMessage());
-        }
+        checkKeySize(keysize);
         this.primeSize = keysize;
         this.random = random;
     }
@@ -98,32 +98,31 @@
      * @exception InvalidAlgorithmParameterException if the given parameter
      * generation values are inappropriate for this parameter generator
      */
+    @Override
     protected void engineInit(AlgorithmParameterSpec genParamSpec,
-                              SecureRandom random)
-        throws InvalidAlgorithmParameterException {
+            SecureRandom random) throws InvalidAlgorithmParameterException {
+
         if (!(genParamSpec instanceof DHGenParameterSpec)) {
             throw new InvalidAlgorithmParameterException
                 ("Inappropriate parameter type");
         }
 
         DHGenParameterSpec dhParamSpec = (DHGenParameterSpec)genParamSpec;
-
         primeSize = dhParamSpec.getPrimeSize();
-
-        // Re-uses DSA parameters and thus have the same range
-        checkKeySize(primeSize);
-
         exponentSize = dhParamSpec.getExponentSize();
-        if (exponentSize <= 0) {
-            throw new InvalidAlgorithmParameterException
-                ("Exponent size must be greater than zero");
+        if ((exponentSize <= 0) || (exponentSize >= primeSize)) {
+            throw new InvalidAlgorithmParameterException(
+                    "Exponent size (" + exponentSize +
+                    ") must be positive and less than modulus size (" +
+                    primeSize + ")");
+        }
+        try {
+            checkKeySize(primeSize);
+        } catch (InvalidParameterException ipe) {
+            throw new InvalidAlgorithmParameterException(ipe.getMessage());
         }
 
-        // Require exponentSize < primeSize
-        if (exponentSize >= primeSize) {
-            throw new InvalidAlgorithmParameterException
-                ("Exponent size must be less than modulus size");
-        }
+        this.random = random;
     }
 
     /**
@@ -131,24 +130,22 @@
      *
      * @return the new AlgorithmParameters object
      */
+    @Override
     protected AlgorithmParameters engineGenerateParameters() {
-        AlgorithmParameters algParams = null;
 
-        if (this.exponentSize == 0) {
-            this.exponentSize = this.primeSize - 1;
+        if (random == null) {
+            random = SunJCE.getRandom();
         }
 
-        if (this.random == null)
-            this.random = SunJCE.getRandom();
-
+        BigInteger paramP = null;
+        BigInteger paramG = null;
         try {
-            AlgorithmParameterGenerator paramGen;
-            DSAParameterSpec dsaParamSpec;
-
-            paramGen = AlgorithmParameterGenerator.getInstance("DSA");
-            paramGen.init(this.primeSize, random);
-            algParams = paramGen.generateParameters();
-            dsaParamSpec = algParams.getParameterSpec(DSAParameterSpec.class);
+            AlgorithmParameterGenerator dsaParamGen =
+                    AlgorithmParameterGenerator.getInstance("DSA");
+            dsaParamGen.init(primeSize, random);
+            AlgorithmParameters dsaParams = dsaParamGen.generateParameters();
+            DSAParameterSpec dsaParamSpec =
+                    dsaParams.getParameterSpec(DSAParameterSpec.class);
 
             DHParameterSpec dhParamSpec;
             if (this.exponentSize > 0) {
@@ -159,16 +156,13 @@
                 dhParamSpec = new DHParameterSpec(dsaParamSpec.getP(),
                                                   dsaParamSpec.getG());
             }
-            algParams = AlgorithmParameters.getInstance("DH",
-                    SunJCE.getInstance());
+            AlgorithmParameters algParams =
+                    AlgorithmParameters.getInstance("DH", SunJCE.getInstance());
             algParams.init(dhParamSpec);
-        } catch (InvalidParameterSpecException e) {
-            // this should never happen
-            throw new RuntimeException(e.getMessage());
-        } catch (NoSuchAlgorithmException e) {
-            // this should never happen, because we provide it
-            throw new RuntimeException(e.getMessage());
+
+            return algParams;
+        } catch (Exception ex) {
+            throw new ProviderException("Unexpected exception", ex);
         }
-        return algParams;
     }
 }
--- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java	Fri Apr 22 01:04:01 2016 -0700
@@ -512,11 +512,17 @@
         byte[] sOut = new byte[s.length];
         GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
         gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
+
+        // check entire authentication tag for time-consistency
+        int mismatch = 0;
         for (int i = 0; i < tagLenBytes; i++) {
-            if (tag[i] != sOut[i]) {
-                throw new AEADBadTagException("Tag mismatch!");
-            }
+            mismatch |= tag[i] ^ sOut[i];
         }
+
+        if (mismatch != 0) {
+            throw new AEADBadTagException("Tag mismatch!");
+        }
+
         return len;
     }
 
--- a/src/java.base/share/classes/java/io/DataInput.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/DataInput.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -182,10 +182,11 @@
      * not all bytes of {@code b} have been
      * updated with data from the input stream.
      *
-     * @param     b   the buffer into which the data is read.
-     * @exception  EOFException  if this stream reaches the end before reading
-     *               all the bytes.
-     * @exception  IOException   if an I/O error occurs.
+     * @param   b   the buffer into which the data is read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  EOFException  if this stream reaches the end before reading
+     *          all the bytes.
+     * @throws  IOException   if an I/O error occurs.
      */
     void readFully(byte b[]) throws IOException;
 
@@ -226,12 +227,16 @@
      * and so on. The number of bytes read is,
      * at most, equal to {@code len}.
      *
-     * @param     b   the buffer into which the data is read.
-     * @param off  an int specifying the offset into the data.
-     * @param len  an int specifying the number of bytes to read.
-     * @exception  EOFException  if this stream reaches the end before reading
-     *               all the bytes.
-     * @exception  IOException   if an I/O error occurs.
+     * @param   b    the buffer into which the data is read.
+     * @param   off  an int specifying the offset in the data array {@code b}.
+     * @param   len  an int specifying the number of bytes to read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  IndexOutOfBoundsException if {@code off} is negative,
+     *          {@code len} is negative, or {@code len} is greater than
+     *          {@code b.length - off}.
+     * @throws  EOFException  if this stream reaches the end before reading
+     *          all the bytes.
+     * @throws  IOException   if an I/O error occurs.
      */
     void readFully(byte b[], int off, int len) throws IOException;
 
--- a/src/java.base/share/classes/java/io/DataInputStream.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/DataInputStream.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -150,38 +150,43 @@
     }
 
     /**
-     * See the general contract of the <code>readFully</code>
-     * method of <code>DataInput</code>.
+     * See the general contract of the {@code readFully}
+     * method of {@code DataInput}.
      * <p>
      * Bytes
      * for this operation are read from the contained
      * input stream.
      *
-     * @param      b   the buffer into which the data is read.
-     * @exception  EOFException  if this input stream reaches the end before
-     *             reading all the bytes.
-     * @exception  IOException   the stream has been closed and the contained
-     *             input stream does not support reading after close, or
-     *             another I/O error occurs.
-     * @see        java.io.FilterInputStream#in
+     * @param   b   the buffer into which the data is read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  EOFException  if this input stream reaches the end before
+     *          reading all the bytes.
+     * @throws  IOException   the stream has been closed and the contained
+     *          input stream does not support reading after close, or
+     *          another I/O error occurs.
+     * @see     java.io.FilterInputStream#in
      */
     public final void readFully(byte b[]) throws IOException {
         readFully(b, 0, b.length);
     }
 
     /**
-     * See the general contract of the <code>readFully</code>
-     * method of <code>DataInput</code>.
+     * See the general contract of the {@code readFully}
+     * method of {@code DataInput}.
      * <p>
      * Bytes
      * for this operation are read from the contained
      * input stream.
      *
      * @param      b     the buffer into which the data is read.
-     * @param      off   the start offset of the data.
+     * @param      off   the start offset in the data array {@code b}.
      * @param      len   the number of bytes to read.
+     * @exception  NullPointerException if {@code b} is {@code null}.
+     * @exception  IndexOutOfBoundsException if {@code off} is negative,
+     *             {@code len} is negative, or {@code len} is greater than
+     *             {@code b.length - off}.
      * @exception  EOFException  if this input stream reaches the end before
-     *               reading all the bytes.
+     *             reading all the bytes.
      * @exception  IOException   the stream has been closed and the contained
      *             input stream does not support reading after close, or
      *             another I/O error occurs.
--- a/src/java.base/share/classes/java/io/File.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/File.java	Fri Apr 22 01:04:01 2016 -0700
@@ -31,7 +31,6 @@
 import java.net.URISyntaxException;
 import java.util.List;
 import java.util.ArrayList;
-import java.security.AccessController;
 import java.security.SecureRandom;
 import java.nio.file.Path;
 import java.nio.file.FileSystems;
@@ -1896,8 +1895,8 @@
         private TempDirectory() { }
 
         // temporary directory location
-        private static final File tmpdir = new File(AccessController
-            .doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+        private static final File tmpdir = new File(
+                GetPropertyAction.getProperty("java.io.tmpdir"));
         static File location() {
             return tmpdir;
         }
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java	Fri Apr 22 01:04:01 2016 -0700
@@ -40,6 +40,9 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
+import jdk.internal.misc.JavaObjectInputStreamAccess;
+import jdk.internal.misc.ObjectStreamClassValidator;
+import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.Unsafe;
 import sun.reflect.misc.ReflectUtil;
 
@@ -853,10 +856,14 @@
      * exactly 'length' bytes.
      *
      * @param   buf the buffer into which the data is read
-     * @param   off the start offset of the data
+     * @param   off the start offset in the destination array {@code buf}
      * @param   len the maximum number of bytes read
      * @return  the actual number of bytes read, -1 is returned when the end of
      *          the stream is reached.
+     * @throws  NullPointerException if {@code buf} is {@code null}.
+     * @throws  IndexOutOfBoundsException if {@code off} is negative,
+     *          {@code len} is negative, or {@code len} is greater than
+     *          {@code buf.length - off}.
      * @throws  IOException If an I/O error has occurred.
      * @see java.io.DataInputStream#readFully(byte[],int,int)
      */
@@ -1014,6 +1021,7 @@
      * Reads bytes, blocking until all bytes are read.
      *
      * @param   buf the buffer into which the data is read
+     * @throws  NullPointerException If {@code buf} is {@code null}.
      * @throws  EOFException If end of file is reached.
      * @throws  IOException If other I/O error has occurred.
      */
@@ -1025,8 +1033,12 @@
      * Reads bytes, blocking until all bytes are read.
      *
      * @param   buf the buffer into which the data is read
-     * @param   off the start offset of the data
+     * @param   off the start offset into the data array {@code buf}
      * @param   len the maximum number of bytes to read
+     * @throws  NullPointerException If {@code buf} is {@code null}.
+     * @throws  IndexOutOfBoundsException If {@code off} is negative,
+     *          {@code len} is negative, or {@code len} is greater than
+     *          {@code buf.length - off}.
      * @throws  EOFException If end of file is reached.
      * @throws  IOException If other I/O error has occurred.
      */
@@ -1509,23 +1521,28 @@
         throws IOException
     {
         byte tc = bin.peekByte();
+        ObjectStreamClass descriptor;
         switch (tc) {
             case TC_NULL:
-                return (ObjectStreamClass) readNull();
-
+                descriptor = (ObjectStreamClass) readNull();
+                break;
             case TC_REFERENCE:
-                return (ObjectStreamClass) readHandle(unshared);
-
+                descriptor = (ObjectStreamClass) readHandle(unshared);
+                break;
             case TC_PROXYCLASSDESC:
-                return readProxyDesc(unshared);
-
+                descriptor = readProxyDesc(unshared);
+                break;
             case TC_CLASSDESC:
-                return readNonProxyDesc(unshared);
-
+                descriptor = readNonProxyDesc(unshared);
+                break;
             default:
                 throw new StreamCorruptedException(
                     String.format("invalid type code: %02X", tc));
         }
+        if (descriptor != null) {
+            validateDescriptor(descriptor);
+        }
+        return descriptor;
     }
 
     private boolean isCustomSubclass() {
@@ -1915,6 +1932,8 @@
                 if (obj == null || handles.lookupException(passHandle) != null) {
                     defaultReadFields(null, slotDesc); // skip field values
                 } else if (slotDesc.hasReadObjectMethod()) {
+                    ThreadDeath t = null;
+                    boolean reset = false;
                     SerialCallbackContext oldContext = curContext;
                     if (oldContext != null)
                         oldContext.check();
@@ -1933,10 +1952,19 @@
                          */
                         handles.markException(passHandle, ex);
                     } finally {
-                        curContext.setUsed();
-                        if (oldContext!= null)
-                            oldContext.check();
-                        curContext = oldContext;
+                        do {
+                            try {
+                                curContext.setUsed();
+                                if (oldContext!= null)
+                                    oldContext.check();
+                                curContext = oldContext;
+                                reset = true;
+                            } catch (ThreadDeath x) {
+                                t = x;  // defer until reset is true
+                            }
+                        } while (!reset);
+                        if (t != null)
+                            throw t;
                     }
 
                     /*
@@ -3647,4 +3675,20 @@
         }
     }
 
+    private void validateDescriptor(ObjectStreamClass descriptor) {
+        ObjectStreamClassValidator validating = validator;
+        if (validating != null) {
+            validating.validateDescriptor(descriptor);
+        }
+    }
+
+    // controlled access to ObjectStreamClassValidator
+    private volatile ObjectStreamClassValidator validator;
+
+    private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
+        ois.validator = validator;
+    }
+    static {
+        SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
+    }
 }
--- a/src/java.base/share/classes/java/io/ObjectStreamClass.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java	Fri Apr 22 01:04:01 2016 -0700
@@ -49,9 +49,9 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import jdk.internal.misc.Unsafe;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
-import sun.reflect.ReflectionFactory;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import jdk.internal.reflect.ReflectionFactory;
 import sun.reflect.misc.ReflectUtil;
 
 import static java.io.ObjectStreamField.*;
--- a/src/java.base/share/classes/java/io/ObjectStreamField.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/ObjectStreamField.java	Fri Apr 22 01:04:01 2016 -0700
@@ -26,8 +26,8 @@
 package java.io;
 
 import java.lang.reflect.Field;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
 
 /**
--- a/src/java.base/share/classes/java/io/RandomAccessFile.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/io/RandomAccessFile.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -418,10 +418,11 @@
      * read. This method blocks until the requested number of bytes are
      * read, the end of the stream is detected, or an exception is thrown.
      *
-     * @param      b   the buffer into which the data is read.
-     * @exception  EOFException  if this file reaches the end before reading
-     *               all the bytes.
-     * @exception  IOException   if an I/O error occurs.
+     * @param   b   the buffer into which the data is read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  EOFException  if this file reaches the end before reading
+     *              all the bytes.
+     * @throws  IOException   if an I/O error occurs.
      */
     public final void readFully(byte b[]) throws IOException {
         readFully(b, 0, b.length);
@@ -434,12 +435,16 @@
      * read. This method blocks until the requested number of bytes are
      * read, the end of the stream is detected, or an exception is thrown.
      *
-     * @param      b     the buffer into which the data is read.
-     * @param      off   the start offset of the data.
-     * @param      len   the number of bytes to read.
-     * @exception  EOFException  if this file reaches the end before reading
-     *               all the bytes.
-     * @exception  IOException   if an I/O error occurs.
+     * @param   b     the buffer into which the data is read.
+     * @param   off   the start offset into the data array {@code b}.
+     * @param   len   the number of bytes to read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  IndexOutOfBoundsException if {@code off} is negative,
+     *                {@code len} is negative, or {@code len} is greater than
+     *                {@code b.length - off}.
+     * @throws  EOFException  if this file reaches the end before reading
+     *                all the bytes.
+     * @throws  IOException   if an I/O error occurs.
      */
     public final void readFully(byte b[], int off, int len) throws IOException {
         int n = 0;
--- a/src/java.base/share/classes/java/lang/Boolean.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Boolean.java	Fri Apr 22 01:04:01 2016 -0700
@@ -79,13 +79,16 @@
      * Allocates a {@code Boolean} object representing the
      * {@code value} argument.
      *
-     * <p><b>Note: It is rarely appropriate to use this constructor.
-     * Unless a <i>new</i> instance is required, the static factory
-     * {@link #valueOf(boolean)} is generally a better choice. It is
-     * likely to yield significantly better space and time performance.</b>
+     * @param   value   the value of the {@code Boolean}.
      *
-     * @param   value   the value of the {@code Boolean}.
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(boolean)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
+     * Also consider using the final fields {@link #TRUE} and {@link #FALSE}
+     * if possible.
      */
+    @Deprecated(since="9")
     public Boolean(boolean value) {
         this.value = value;
     }
@@ -94,15 +97,18 @@
      * Allocates a {@code Boolean} object representing the value
      * {@code true} if the string argument is not {@code null}
      * and is equal, ignoring case, to the string {@code "true"}.
-     * Otherwise, allocate a {@code Boolean} object representing the
-     * value {@code false}. Examples:<p>
-     * {@code new Boolean("True")} produces a {@code Boolean} object
-     * that represents {@code true}.<br>
-     * {@code new Boolean("yes")} produces a {@code Boolean} object
-     * that represents {@code false}.
+     * Otherwise, allocates a {@code Boolean} object representing the
+     * value {@code false}.
      *
      * @param   s   the string to be converted to a {@code Boolean}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseBoolean(String)} to convert a string to a
+     * {@code boolean} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Boolean} object.
      */
+    @Deprecated(since="9")
     public Boolean(String s) {
         this(parseBoolean(s));
     }
--- a/src/java.base/share/classes/java/lang/Byte.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Byte.java	Fri Apr 22 01:04:01 2016 -0700
@@ -297,7 +297,13 @@
      *
      * @param value     the value to be represented by the
      *                  {@code Byte}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(byte)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Byte(byte value) {
         this.value = value;
     }
@@ -311,10 +317,16 @@
      *
      * @param s         the {@code String} to be converted to a
      *                  {@code Byte}
-     * @throws           NumberFormatException If the {@code String}
+     * @throws          NumberFormatException if the {@code String}
      *                  does not contain a parsable {@code byte}.
-     * @see        java.lang.Byte#parseByte(java.lang.String, int)
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseByte(String)} to convert a string to a
+     * {@code byte} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Byte} object.
      */
+    @Deprecated(since="9")
     public Byte(String s) throws NumberFormatException {
         this.value = parseByte(s, 10);
     }
--- a/src/java.base/share/classes/java/lang/Character.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Character.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1256,14 +1256,14 @@
             new UnicodeBlock("SPECIALS");
 
         /**
-         * @deprecated As of J2SE 5, use {@link #HIGH_SURROGATES},
-         *             {@link #HIGH_PRIVATE_USE_SURROGATES}, and
-         *             {@link #LOW_SURROGATES}. These new constants match
-         *             the block definitions of the Unicode Standard.
-         *             The {@link #of(char)} and {@link #of(int)} methods
-         *             return the new constants, not SURROGATES_AREA.
-         */
-        @Deprecated
+         * @deprecated
+         * Instead of {@code SURROGATES_AREA}, use {@link #HIGH_SURROGATES},
+         * {@link #HIGH_PRIVATE_USE_SURROGATES}, and {@link #LOW_SURROGATES}.
+         * These constants match the block definitions of the Unicode Standard.
+         * The {@link #of(char)} and {@link #of(int)} methods return the
+         * standard constants.
+         */
+        @Deprecated(since="1.5")
         public static final UnicodeBlock SURROGATES_AREA =
             new UnicodeBlock("SURROGATES_AREA");
 
@@ -7451,7 +7451,13 @@
      *
      * @param  value   the value to be represented by the
      *                  {@code Character} object.
-     */
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(char)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
+     */
+    @Deprecated(since="9")
     public Character(char value) {
         this.value = value;
     }
@@ -8799,7 +8805,7 @@
      * @since   1.0.2
      * @deprecated Replaced by isJavaIdentifierStart(char).
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public static boolean isJavaLetter(char ch) {
         return isJavaIdentifierStart(ch);
     }
@@ -8835,7 +8841,7 @@
      * @since   1.0.2
      * @deprecated Replaced by isJavaIdentifierPart(char).
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public static boolean isJavaLetterOrDigit(char ch) {
         return isJavaIdentifierPart(ch);
     }
@@ -9580,7 +9586,7 @@
      * @see        Character#isWhitespace(char)
      * @deprecated Replaced by isWhitespace(char).
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public static boolean isSpace(char ch) {
         return (ch <= 0x0020) &&
             (((((1L << 0x0009) |
--- a/src/java.base/share/classes/java/lang/Class.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Class.java	Fri Apr 22 01:04:01 2016 -0700
@@ -66,10 +66,10 @@
 import jdk.internal.loader.BuiltinClassLoader;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
-import sun.reflect.CallerSensitive;
-import sun.reflect.ConstantPool;
-import sun.reflect.Reflection;
-import sun.reflect.ReflectionFactory;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.ConstantPool;
+import jdk.internal.reflect.Reflection;
+import jdk.internal.reflect.ReflectionFactory;
 import sun.reflect.generics.factory.CoreReflectionFactory;
 import sun.reflect.generics.factory.GenericsFactory;
 import sun.reflect.generics.repository.ClassRepository;
@@ -3473,7 +3473,7 @@
         if (reflectionFactory == null) {
             reflectionFactory =
                 java.security.AccessController.doPrivileged
-                    (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());
+                    (new ReflectionFactory.GetReflectionFactoryAction());
         }
         return reflectionFactory;
     }
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Fri Apr 22 01:04:01 2016 -0700
@@ -60,8 +60,8 @@
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.util.SecurityConstants;
 
@@ -727,7 +727,7 @@
      * @deprecated  Replaced by {@link #defineClass(String, byte[], int, int)
      * defineClass(String, byte[], int, int)}
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     protected final Class<?> defineClass(byte[] b, int off, int len)
         throws ClassFormatError
     {
@@ -817,6 +817,9 @@
         if (!checkName(name))
             throw new NoClassDefFoundError("IllegalName: " + name);
 
+        // Note:  Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
+        // relies on the fact that spoofing is impossible if a class has a name
+        // of the form "java.*"
         if ((name != null) && name.startsWith("java.")
                 && this != getBuiltinPlatformClassLoader()) {
             throw new SecurityException
@@ -2012,7 +2015,7 @@
      *
      * @since  1.2
      */
-    @Deprecated
+    @Deprecated(since="9")
     protected Package getPackage(String name) {
         Package pkg = getDefinedPackage(name);
         if (pkg == null) {
--- a/src/java.base/share/classes/java/lang/Double.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Double.java	Fri Apr 22 01:04:01 2016 -0700
@@ -589,7 +589,13 @@
      * represents the primitive {@code double} argument.
      *
      * @param   value   the value to be represented by the {@code Double}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(double)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Double(double value) {
         this.value = value;
     }
@@ -601,10 +607,16 @@
      * {@code double} value as if by the {@code valueOf} method.
      *
      * @param  s  a string to be converted to a {@code Double}.
-     * @throws    NumberFormatException  if the string does not contain a
+     * @throws    NumberFormatException if the string does not contain a
      *            parsable number.
-     * @see       java.lang.Double#valueOf(java.lang.String)
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseDouble(String)} to convert a string to a
+     * {@code double} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Double} object.
      */
+    @Deprecated(since="9")
     public Double(String s) throws NumberFormatException {
         value = parseDouble(s);
     }
--- a/src/java.base/share/classes/java/lang/Float.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Float.java	Fri Apr 22 01:04:01 2016 -0700
@@ -502,7 +502,13 @@
      * represents the primitive {@code float} argument.
      *
      * @param   value   the value to be represented by the {@code Float}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(float)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Float(float value) {
         this.value = value;
     }
@@ -512,7 +518,13 @@
      * represents the argument converted to type {@code float}.
      *
      * @param   value   the value to be represented by the {@code Float}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. Instead, use the
+     * static factory method {@link #valueOf(float)} method as follows:
+     * {@code Float.valueOf((float)value)}.
      */
+    @Deprecated(since="9")
     public Float(double value) {
         this.value = (float)value;
     }
@@ -523,11 +535,17 @@
      * represented by the string. The string is converted to a
      * {@code float} value as if by the {@code valueOf} method.
      *
-     * @param      s   a string to be converted to a {@code Float}.
-     * @throws  NumberFormatException  if the string does not contain a
-     *               parsable number.
-     * @see        java.lang.Float#valueOf(java.lang.String)
+     * @param   s   a string to be converted to a {@code Float}.
+     * @throws      NumberFormatException if the string does not contain a
+     *              parsable number.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseFloat(String)} to convert a string to a
+     * {@code float} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Float} object.
      */
+    @Deprecated(since="9")
     public Float(String s) throws NumberFormatException {
         value = parseFloat(s);
     }
--- a/src/java.base/share/classes/java/lang/Integer.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Integer.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1106,7 +1106,13 @@
      *
      * @param   value   the value to be represented by the
      *                  {@code Integer} object.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(int)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Integer(int value) {
         this.value = value;
     }
@@ -1118,12 +1124,17 @@
      * {@code int} value in exactly the manner used by the
      * {@code parseInt} method for radix 10.
      *
-     * @param      s   the {@code String} to be converted to an
-     *                 {@code Integer}.
-     * @exception  NumberFormatException  if the {@code String} does not
-     *               contain a parsable integer.
-     * @see        java.lang.Integer#parseInt(java.lang.String, int)
+     * @param   s   the {@code String} to be converted to an {@code Integer}.
+     * @throws      NumberFormatException if the {@code String} does not
+     *              contain a parsable integer.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseInt(String)} to convert a string to a
+     * {@code int} primitive, or use {@link #valueOf(String)}
+     * to convert a string to an {@code Integer} object.
      */
+    @Deprecated(since="9")
     public Integer(String s) throws NumberFormatException {
         this.value = parseInt(s, 10);
     }
--- a/src/java.base/share/classes/java/lang/Long.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Long.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1340,7 +1340,13 @@
      *
      * @param   value   the value to be represented by the
      *          {@code Long} object.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(long)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Long(long value) {
         this.value = value;
     }
@@ -1356,8 +1362,14 @@
      *             {@code Long}.
      * @throws     NumberFormatException  if the {@code String} does not
      *             contain a parsable {@code long}.
-     * @see        java.lang.Long#parseLong(java.lang.String, int)
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseLong(String)} to convert a string to a
+     * {@code long} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Long} object.
      */
+    @Deprecated(since="9")
     public Long(String s) throws NumberFormatException {
         this.value = parseLong(s, 10);
     }
--- a/src/java.base/share/classes/java/lang/Math.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Math.java	Fri Apr 22 01:04:01 2016 -0700
@@ -25,6 +25,7 @@
 
 package java.lang;
 
+import java.math.BigDecimal;
 import java.util.Random;
 import jdk.internal.math.FloatConsts;
 import jdk.internal.math.DoubleConsts;
@@ -1450,6 +1451,199 @@
     }
 
     /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code double}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fma(a, 1.0, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fma(a, b, +0.0)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fma(-0.0, +0.0, +0.0)} is {@code +0.0} while
+     * ({@code -0.0 * +0.0}) is {@code -0.0}; {@code fma(a, b, -0.0)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code double} value
+     */
+    // @HotSpotIntrinsicCandidate
+    public static double fma(double a, double b, double c) {
+        /*
+         * Infinity and NaN arithmetic is not quite the same with two
+         * roundings as opposed to just one so the simple expression
+         * "a * b + c" cannot always be used to compute the correct
+         * result.  With two roundings, the product can overflow and
+         * if the addend is infinite, a spurious NaN can be produced
+         * if the infinity from the overflow and the infinite addend
+         * have opposite signs.
+         */
+
+        // First, screen for and handle non-finite input values whose
+        // arithmetic is not supported by BigDecimal.
+        if (Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(c)) {
+            return Double.NaN;
+        } else { // All inputs non-NaN
+            boolean infiniteA = Double.isInfinite(a);
+            boolean infiniteB = Double.isInfinite(b);
+            boolean infiniteC = Double.isInfinite(c);
+            double result;
+
+            if (infiniteA || infiniteB || infiniteC) {
+                if (infiniteA && b == 0.0 ||
+                    infiniteB && a == 0.0 ) {
+                    return Double.NaN;
+                }
+                // Store product in a double field to cause an
+                // overflow even if non-strictfp evaluation is being
+                // used.
+                double product = a * b;
+                if (Double.isInfinite(product) && !infiniteA && !infiniteB) {
+                    // Intermediate overflow; might cause a
+                    // spurious NaN if added to infinite c.
+                    assert Double.isInfinite(c);
+                    return c;
+                } else {
+                    result = product + c;
+                    assert !Double.isFinite(result);
+                    return result;
+                }
+            } else { // All inputs finite
+                BigDecimal product = (new BigDecimal(a)).multiply(new BigDecimal(b));
+                if (c == 0.0) { // Positive or negative zero
+                    // If the product is an exact zero, use a
+                    // floating-point expression to compute the sign
+                    // of the zero final result. The product is an
+                    // exact zero if and only if at least one of a and
+                    // b is zero.
+                    if (a == 0.0 || b == 0.0) {
+                        return a * b + c;
+                    } else {
+                        // The sign of a zero addend doesn't matter if
+                        // the product is nonzero. The sign of a zero
+                        // addend is not factored in the result if the
+                        // exact product is nonzero but underflows to
+                        // zero; see IEEE-754 2008 section 6.3 "The
+                        // sign bit".
+                        return product.doubleValue();
+                    }
+                } else {
+                    return product.add(new BigDecimal(c)).doubleValue();
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code float}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fma(a, 1.0f, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fma(a, b, +0.0f)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fma(-0.0f, +0.0f, +0.0f)} is {@code +0.0f} while
+     * ({@code -0.0f * +0.0f}) is {@code -0.0f}; {@code fma(a, b, -0.0f)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code float} value
+     */
+    // @HotSpotIntrinsicCandidate
+    public static float fma(float a, float b, float c) {
+        /*
+         *  Since the double format has more than twice the precision
+         *  of the float format, the multiply of a * b is exact in
+         *  double. The add of c to the product then incurs one
+         *  rounding error. Since the double format moreover has more
+         *  than (2p + 2) precision bits compared to the p bits of the
+         *  float format, the two roundings of (a * b + c), first to
+         *  the double format and then secondarily to the float format,
+         *  are equivalent to rounding the intermediate result directly
+         *  to the float format.
+         *
+         * In terms of strictfp vs default-fp concerns related to
+         * overflow and underflow, since
+         *
+         * (Float.MAX_VALUE * Float.MAX_VALUE) << Double.MAX_VALUE
+         * (Float.MIN_VALUE * Float.MIN_VALUE) >> Double.MIN_VALUE
+         *
+         * neither the multiply nor add will overflow or underflow in
+         * double. Therefore, it is not necessary for this method to
+         * be declared strictfp to have reproducible
+         * behavior. However, it is necessary to explicitly store down
+         * to a float variable to avoid returning a value in the float
+         * extended value set.
+         */
+        float result = (float)(((double) a * (double) b ) + (double) c);
+        return result;
+    }
+
+    /**
      * Returns the size of an ulp of the argument.  An ulp, unit in
      * the last place, of a {@code double} value is the positive
      * distance between this floating-point value and the {@code
--- a/src/java.base/share/classes/java/lang/Package.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Package.java	Fri Apr 22 01:04:01 2016 -0700
@@ -36,8 +36,8 @@
 import java.util.Objects;
 
 import jdk.internal.loader.BootLoader;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 
 /**
@@ -333,7 +333,7 @@
      * @see ClassLoader#getDefinedPackage
      */
     @CallerSensitive
-    @Deprecated
+    @Deprecated(since="9")
     @SuppressWarnings("deprecation")
     public static Package getPackage(String name) {
         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
--- a/src/java.base/share/classes/java/lang/ProcessBuilder.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/ProcessBuilder.java	Fri Apr 22 01:04:01 2016 -0700
@@ -30,13 +30,12 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.nio.channels.Pipe;
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+
 /**
  * This class is used to create operating system processes.
  *
@@ -468,11 +467,9 @@
      * @since 1.7
      */
     public abstract static class Redirect {
-        private static final File NULL_FILE = AccessController.doPrivileged(
-                (PrivilegedAction<File>) () -> {
-                    return new File((System.getProperty("os.name")
-                            .startsWith("Windows") ? "NUL" : "/dev/null"));
-                }
+        private static final File NULL_FILE = new File(
+                (GetPropertyAction.getProperty("os.name")
+                        .startsWith("Windows") ? "NUL" : "/dev/null")
         );
 
         /**
--- a/src/java.base/share/classes/java/lang/Runtime.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Runtime.java	Fri Apr 22 01:04:01 2016 -0700
@@ -27,8 +27,8 @@
 
 import java.io.*;
 import java.util.StringTokenizer;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 /**
  * Every Java application has a single instance of class
@@ -289,6 +289,7 @@
      *      finalizers being called on live objects while other threads are
      *      concurrently manipulating those objects, resulting in erratic
      *      behavior or deadlock.
+     *      This method is subject to removal in a future version of Java SE.
      *
      * @throws  SecurityException
      *        if a security manager exists and its {@code checkExit}
@@ -299,7 +300,7 @@
      * @see     java.lang.SecurityManager#checkExit(int)
      * @since   1.1
      */
-    @Deprecated
+    @Deprecated(since="1.2", forRemoval=true)
     public static void runFinalizersOnExit(boolean value) {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
@@ -894,8 +895,9 @@
      * stream in the local encoding into a character stream in Unicode is via
      * the {@code InputStreamReader} and {@code BufferedReader}
      * classes.
+     * This method is subject to removal in a future version of Java SE.
      */
-    @Deprecated
+    @Deprecated(since="1.1", forRemoval=true)
     public InputStream getLocalizedInputStream(InputStream in) {
         return in;
     }
@@ -915,6 +917,7 @@
      * Unicode character stream into a byte stream in the local encoding is via
      * the {@code OutputStreamWriter}, {@code BufferedWriter}, and
      * {@code PrintWriter} classes.
+     * This method is subject to removal in a future version of Java SE.
      *
      * @param      out OutputStream to localize
      * @return     a localized output stream
@@ -923,7 +926,7 @@
      * @see        java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
      * @see        java.io.PrintWriter#PrintWriter(java.io.OutputStream)
      */
-    @Deprecated
+    @Deprecated(since="1.1", forRemoval=true)
     public OutputStream getLocalizedOutputStream(OutputStream out) {
         return out;
     }
--- a/src/java.base/share/classes/java/lang/SecurityManager.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/SecurityManager.java	Fri Apr 22 01:04:01 2016 -0700
@@ -38,7 +38,7 @@
 import java.lang.reflect.*;
 import java.net.URL;
 
-import sun.reflect.CallerSensitive;
+import jdk.internal.reflect.CallerSensitive;
 import sun.security.util.SecurityConstants;
 
 /**
@@ -229,7 +229,7 @@
      *  It is recommended that the <code>checkPermission</code>
      *  call be used instead.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected boolean inCheck;
 
     /*
@@ -262,7 +262,7 @@
      *  It is recommended that the <code>checkPermission</code>
      *  call be used instead.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public boolean getInCheck() {
         return inCheck;
     }
@@ -345,7 +345,7 @@
      * @see  java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader
      * @see  #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected ClassLoader currentClassLoader() {
         ClassLoader cl = currentClassLoader0();
         if ((cl != null) && hasAllPermission())
@@ -391,7 +391,7 @@
      * @see  java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader
      * @see  #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected Class<?> currentLoadedClass() {
         Class<?> c = currentLoadedClass0();
         if ((c != null) && hasAllPermission())
@@ -411,7 +411,7 @@
      *  call be used instead.
      *
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected native int classDepth(String name);
 
     /**
@@ -449,7 +449,7 @@
      * @see   java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader
      * @see   #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected int classLoaderDepth() {
         int depth = classLoaderDepth0();
         if (depth != -1) {
@@ -474,7 +474,7 @@
      *  It is recommended that the <code>checkPermission</code>
      *  call be used instead.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected boolean inClass(String name) {
         return classDepth(name) >= 0;
     }
@@ -491,7 +491,7 @@
      *  call be used instead.
      * @see        #currentClassLoader() currentClassLoader
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     protected boolean inClassLoader() {
         return currentClassLoader() != null;
     }
@@ -1217,7 +1217,7 @@
      * @deprecated Use #checkPermission(java.security.Permission) instead
      * @see        #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.4")
     public void checkMulticast(InetAddress maddr, byte ttl) {
         String host = maddr.getHostAddress();
         if (!host.startsWith("[") && host.indexOf(':') != -1) {
@@ -1297,9 +1297,10 @@
      *             was trusted to bring up a top-level window. The method has been
      *             obsoleted and code should instead use {@link #checkPermission}
      *             to check {@code AWTPermission("showWindowWithoutWarningBanner")}.
+     *             This method is subject to removal in a future version of Java SE.
      * @see        #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.8", forRemoval=true)
     public boolean checkTopLevelWindow(Object window) {
         if (window == null) {
             throw new NullPointerException("window can't be null");
@@ -1340,9 +1341,10 @@
      *             thread could access the system clipboard. The method has been
      *             obsoleted and code should instead use {@link #checkPermission}
      *             to check {@code AWTPermission("accessClipboard")}.
+     *             This method is subject to removal in a future version of Java SE.
      * @see        #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.8", forRemoval=true)
     public void checkSystemClipboardAccess() {
         checkPermission(SecurityConstants.ALL_PERMISSION);
     }
@@ -1358,9 +1360,10 @@
      *             thread could access the AWT event queue. The method has been
      *             obsoleted and code should instead use {@link #checkPermission}
      *             to check {@code AWTPermission("accessEventQueue")}.
+     *             This method is subject to removal in a future version of Java SE.
      * @see        #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.8", forRemoval=true)
     public void checkAwtEventQueueAccess() {
         checkPermission(SecurityConstants.ALL_PERMISSION);
     }
@@ -1626,12 +1629,13 @@
      *             Users of this method should instead invoke {@link #checkPermission}
      *             directly.  This method will be changed in a future release
      *             to check the permission {@code java.security.AllPermission}.
+     *             This method is subject to removal in a future version of Java SE.
      *
      * @see java.lang.reflect.Member
      * @since 1.1
      * @see        #checkPermission(java.security.Permission) checkPermission
      */
-    @Deprecated
+    @Deprecated(since="1.8", forRemoval=true)
     @CallerSensitive
     public void checkMemberAccess(Class<?> clazz, int which) {
         if (clazz == null) {
--- a/src/java.base/share/classes/java/lang/Short.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Short.java	Fri Apr 22 01:04:01 2016 -0700
@@ -302,7 +302,13 @@
      *
      * @param value     the value to be represented by the
      *                  {@code Short}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(short)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Short(short value) {
         this.value = value;
     }
@@ -318,8 +324,14 @@
      *          {@code Short}
      * @throws  NumberFormatException If the {@code String}
      *          does not contain a parsable {@code short}.
-     * @see     java.lang.Short#parseShort(java.lang.String, int)
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseShort(String)} to convert a string to a
+     * {@code short} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Short} object.
      */
+    @Deprecated(since="9")
     public Short(String s) throws NumberFormatException {
         this.value = parseShort(s, 10);
     }
--- a/src/java.base/share/classes/java/lang/StackStreamFactory.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java	Fri Apr 22 01:04:01 2016 -0700
@@ -24,13 +24,12 @@
  */
 package java.lang;
 
+import jdk.internal.reflect.MethodAccessor;
 import java.lang.StackWalker.Option;
 import java.lang.StackWalker.StackFrame;
 
 import java.lang.annotation.Native;
 import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.Objects;
@@ -40,6 +39,7 @@
 import java.util.function.Function;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
+import sun.security.action.GetPropertyAction;
 
 import static java.lang.StackStreamFactory.WalkerState.*;
 
@@ -978,25 +978,20 @@
     }
 
     private static boolean isReflectionFrame(Class<?> c) {
-        if (c.getName().startsWith("sun.reflect") &&
-                !sun.reflect.MethodAccessor.class.isAssignableFrom(c)) {
-            throw new InternalError("Not sun.reflect.MethodAccessor: " + c.toString());
+        if (c.getName().startsWith("jdk.internal.reflect") &&
+                !MethodAccessor.class.isAssignableFrom(c)) {
+            throw new InternalError("Not jdk.internal.reflect.MethodAccessor: " + c.toString());
         }
         // ## should filter all @Hidden frames?
         return c == Method.class ||
-                sun.reflect.MethodAccessor.class.isAssignableFrom(c) ||
+                MethodAccessor.class.isAssignableFrom(c) ||
                 c.getName().startsWith("java.lang.invoke.LambdaForm");
     }
 
     private static boolean getProperty(String key, boolean value) {
-        String s = AccessController.doPrivileged(new PrivilegedAction<>() {
-            @Override
-            public String run() {
-                return System.getProperty(key);
-            }
-        });
+        String s = GetPropertyAction.getProperty(key);
         if (s != null) {
-            return Boolean.valueOf(s);
+            return Boolean.parseBoolean(s);
         }
         return value;
     }
--- a/src/java.base/share/classes/java/lang/StackWalker.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/StackWalker.java	Fri Apr 22 01:04:01 2016 -0700
@@ -24,7 +24,7 @@
  */
 package java.lang;
 
-import sun.reflect.CallerSensitive;
+import jdk.internal.reflect.CallerSensitive;
 
 import java.util.*;
 import java.util.function.Consumer;
--- a/src/java.base/share/classes/java/lang/StrictMath.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/StrictMath.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1135,6 +1135,110 @@
     }
 
     /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code double}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fusedMac(a, 1.0, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fusedMac(a, b, +0.0)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fusedMac(-0.0, +0.0, +0.0)} is {@code +0.0} while
+     * ({@code -0.0 * +0.0}) is {@code -0.0}; {@code fusedMac(a, b, -0.0)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code double} value
+     */
+    public static double fma(double a, double b, double c) {
+        return Math.fma(a, b, c);
+    }
+
+    /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code float}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fma(a, 1.0f, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fma(a, b, +0.0f)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fma(-0.0f, +0.0f, +0.0f)} is {@code +0.0f} while
+     * ({@code -0.0f * +0.0f}) is {@code -0.0f}; {@code fma(a, b, -0.0f)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code float} value
+     */
+    public static float fma(float a, float b, float c) {
+        return Math.fma(a, b, c);
+    }
+
+    /**
      * Returns the size of an ulp of the argument.  An ulp, unit in
      * the last place, of a {@code double} value is the positive
      * distance between this floating-point value and the {@code
--- a/src/java.base/share/classes/java/lang/String.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/String.java	Fri Apr 22 01:04:01 2016 -0700
@@ -363,7 +363,7 @@
      * @see  #String(byte[], java.nio.charset.Charset)
      * @see  #String(byte[])
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public String(byte ascii[], int hibyte, int offset, int count) {
         checkBoundsOffCount(offset, count, ascii.length);
         if (count == 0) {
@@ -415,7 +415,7 @@
      * @see  #String(byte[], java.nio.charset.Charset)
      * @see  #String(byte[])
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public String(byte ascii[], int hibyte) {
         this(ascii, hibyte, 0, ascii.length);
     }
@@ -911,7 +911,7 @@
      *                 dst.length}
      *          </ul>
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
         checkBoundsBeginEnd(srcBegin, srcEnd, length());
         Objects.requireNonNull(dst);
--- a/src/java.base/share/classes/java/lang/System.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/System.java	Fri Apr 22 01:04:01 2016 -0700
@@ -56,8 +56,8 @@
 import java.util.ResourceBundle;
 import java.util.function.Supplier;
 import sun.nio.ch.Interruptible;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.security.util.SecurityConstants;
 import sun.reflect.annotation.AnnotationType;
 import jdk.internal.HotSpotIntrinsicCandidate;
@@ -1715,6 +1715,7 @@
      *      finalizers being called on live objects while other threads are
      *      concurrently manipulating those objects, resulting in erratic
      *      behavior or deadlock.
+     *      This method is subject to removal in a future version of Java SE.
      * @param value indicating enabling or disabling of finalization
      * @throws  SecurityException
      *        if a security manager exists and its <code>checkExit</code>
@@ -1725,7 +1726,7 @@
      * @see     java.lang.SecurityManager#checkExit(int)
      * @since   1.1
      */
-    @Deprecated
+    @Deprecated(since="1.2", forRemoval=true)
     public static void runFinalizersOnExit(boolean value) {
         Runtime.runFinalizersOnExit(value);
     }
@@ -1978,7 +1979,7 @@
     private static void setJavaLangAccess() {
         // Allow privileged classes outside of java.lang
         SharedSecrets.setJavaLangAccess(new JavaLangAccess(){
-            public sun.reflect.ConstantPool getConstantPool(Class<?> klass) {
+            public jdk.internal.reflect.ConstantPool getConstantPool(Class<?> klass) {
                 return klass.getConstantPool();
             }
             public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
--- a/src/java.base/share/classes/java/lang/Thread.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/Thread.java	Fri Apr 22 01:04:01 2016 -0700
@@ -37,8 +37,8 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.locks.LockSupport;
 import sun.nio.ch.Interruptible;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.security.util.SecurityConstants;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
@@ -929,7 +929,7 @@
      *       <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void stop() {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
@@ -961,8 +961,9 @@
      *        For more information, see
      *        <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
+     *        This method is subject to removal in a future version of Java SE.
      */
-    @Deprecated
+    @Deprecated(since="1.2", forRemoval=true)
     public final synchronized void stop(Throwable obj) {
         throw new UnsupportedOperationException();
     }
@@ -1082,9 +1083,10 @@
      *     "frozen" processes. For more information, see
      *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
      *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
+     *     This method is subject to removal in a future version of Java SE.
      * @throws NoSuchMethodError always
      */
-    @Deprecated
+    @Deprecated(since="1.5", forRemoval=true)
     public void destroy() {
         throw new NoSuchMethodError();
     }
@@ -1122,7 +1124,7 @@
      *   <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void suspend() {
         checkAccess();
         suspend0();
@@ -1148,7 +1150,7 @@
      *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void resume() {
         checkAccess();
         resume0();
@@ -1309,8 +1311,10 @@
      * @deprecated The definition of this call depends on {@link #suspend},
      *             which is deprecated.  Further, the results of this call
      *             were never well-defined.
+     *             This method is subject to removal in a future version of Java SE.
+     * @see        StackWalker
      */
-    @Deprecated
+    @Deprecated(since="1.2", forRemoval=true)
     public native int countStackFrames();
 
     /**
--- a/src/java.base/share/classes/java/lang/ThreadGroup.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/ThreadGroup.java	Fri Apr 22 01:04:01 2016 -0700
@@ -607,7 +607,7 @@
      * @deprecated    This method is inherently unsafe.  See
      *     {@link Thread#stop} for details.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void stop() {
         if (stopOrSuspend(false))
             Thread.currentThread().stop();
@@ -669,7 +669,7 @@
      * @deprecated    This method is inherently deadlock-prone.  See
      *     {@link Thread#suspend} for details.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     @SuppressWarnings("deprecation")
     public final void suspend() {
         if (stopOrSuspend(true))
@@ -732,7 +732,7 @@
      *       both of which have been deprecated, as they are inherently
      *       deadlock-prone.  See {@link Thread#suspend} for details.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     @SuppressWarnings("deprecation")
     public final void resume() {
         int ngroupsSnapshot;
@@ -1073,7 +1073,7 @@
      *             which is deprecated.  Further, the behavior of this call
      *             was never specified.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public boolean allowThreadSuspension(boolean b) {
         this.vmAllowSuspension = b;
         if (!b) {
--- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Fri Apr 22 01:04:01 2016 -0700
@@ -88,8 +88,7 @@
 
     static {
         final String key = "jdk.internal.lambda.dumpProxyClasses";
-        String path = AccessController.doPrivileged(
-                new GetPropertyAction(key));
+        String path = GetPropertyAction.getProperty(key);
         dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
     }
 
--- a/src/java.base/share/classes/java/lang/invoke/MemberName.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java	Fri Apr 22 01:04:01 2016 -0700
@@ -733,6 +733,7 @@
     }
 
     @Override
+    @SuppressWarnings("deprecation")
     public int hashCode() {
         // Avoid autoboxing getReferenceKind(), since this is used early and will force
         // early initialization of Byte$ByteCache
@@ -826,7 +827,7 @@
         assert(isResolved() == isResolved);
     }
 
-    void checkForTypeAlias() {
+    void checkForTypeAlias(Class<?> refc) {
         if (isInvocable()) {
             MethodType type;
             if (this.type instanceof MethodType)
@@ -834,16 +835,16 @@
             else
                 this.type = type = getMethodType();
             if (type.erase() == type)  return;
-            if (VerifyAccess.isTypeVisible(type, clazz))  return;
-            throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
+            if (VerifyAccess.isTypeVisible(type, refc))  return;
+            throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
         } else {
             Class<?> type;
             if (this.type instanceof Class<?>)
                 type = (Class<?>) this.type;
             else
                 this.type = type = getFieldType();
-            if (VerifyAccess.isTypeVisible(type, clazz))  return;
-            throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
+            if (VerifyAccess.isTypeVisible(type, refc))  return;
+            throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
         }
     }
 
@@ -1015,10 +1016,25 @@
             MemberName m = ref.clone();  // JVM will side-effect the ref
             assert(refKind == m.getReferenceKind());
             try {
+                // There are 4 entities in play here:
+                //   * LC: lookupClass
+                //   * REFC: symbolic reference class (MN.clazz before resolution);
+                //   * DEFC: resolved method holder (MN.clazz after resolution);
+                //   * PTYPES: parameter types (MN.type)
+                //
+                // What we care about when resolving a MemberName is consistency between DEFC and PTYPES.
+                // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM
+                // finishes the resolution, so do TA checks right after MHN.resolve() is over.
+                //
+                // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation,
+                // so it is safe to call a MH from any context.
+                //
+                // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
+                // participate in method selection.
                 m = MethodHandleNatives.resolve(m, lookupClass);
-                m.checkForTypeAlias();
+                m.checkForTypeAlias(m.getDeclaringClass());
                 m.resolution = null;
-            } catch (LinkageError ex) {
+            } catch (ClassNotFoundException | LinkageError ex) {
                 // JVM reports that the "bytecode behavior" would get an error
                 assert(!m.isResolved());
                 m.resolution = ex;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Fri Apr 22 01:04:01 2016 -0700
@@ -33,13 +33,13 @@
 import java.util.List;
 import java.util.function.Function;
 
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import jdk.internal.vm.annotation.Stable;
 import sun.invoke.empty.Empty;
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.VerifyType;
 import sun.invoke.util.Wrapper;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
 import static java.lang.invoke.LambdaForm.*;
 import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Fri Apr 22 01:04:01 2016 -0700
@@ -49,7 +49,7 @@
 
     static native void init(MemberName self, Object ref);
     static native void expand(MemberName self);
-    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError;
+    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError, ClassNotFoundException;
     static native int getMembers(Class<?> defc, String matchName, String matchSig,
             int matchFlags, Class<?> caller, int skip, MemberName[] results);
 
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java	Fri Apr 22 01:04:01 2016 -0700
@@ -30,8 +30,8 @@
 import java.security.PrivilegedAction;
 import sun.invoke.WrapperInstance;
 import java.util.ArrayList;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
 import static java.lang.invoke.MethodHandleStatics.*;
 
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Fri Apr 22 01:04:01 2016 -0700
@@ -25,9 +25,9 @@
 
 package java.lang.invoke;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.util.Properties;
 import jdk.internal.misc.Unsafe;
+import sun.security.action.GetPropertyAction;
 
 /**
  * This class consists exclusively of static names internal to the
@@ -53,32 +53,27 @@
     static final boolean VAR_HANDLE_GUARDS;
 
     static {
-        final Object[] values = new Object[10];
-        AccessController.doPrivileged(new PrivilegedAction<>() {
-                public Void run() {
-                    values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
-                    values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
-                    values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
-                    values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
-                    values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 0);
-                    values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30);
-                    values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
-                    values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
-                    values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
-                    values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
-                    return null;
-                }
-            });
-        DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
-        DUMP_CLASS_FILES          = (Boolean) values[1];
-        TRACE_INTERPRETER         = (Boolean) values[2];
-        TRACE_METHOD_LINKAGE      = (Boolean) values[3];
-        COMPILE_THRESHOLD         = (Integer) values[4];
-        DONT_INLINE_THRESHOLD     = (Integer) values[5];
-        PROFILE_LEVEL             = (Integer) values[6];
-        PROFILE_GWT               = (Boolean) values[7];
-        CUSTOMIZE_THRESHOLD       = (Integer) values[8];
-        VAR_HANDLE_GUARDS         = (Boolean) values[9];
+        Properties props = GetPropertyAction.getProperties();
+        DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES"));
+        DUMP_CLASS_FILES = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"));
+        TRACE_INTERPRETER = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"));
+        TRACE_METHOD_LINKAGE = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"));
+        COMPILE_THRESHOLD = Integer.parseInt(
+                props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0"));
+        DONT_INLINE_THRESHOLD = Integer.parseInt(
+                props.getProperty("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", "30"));
+        PROFILE_LEVEL = Integer.parseInt(
+                props.getProperty("java.lang.invoke.MethodHandle.PROFILE_LEVEL", "0"));
+        PROFILE_GWT = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
+        CUSTOMIZE_THRESHOLD = Integer.parseInt(
+                props.getProperty("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", "127"));
+        VAR_HANDLE_GUARDS = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
 
         if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
             throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Fri Apr 22 01:04:01 2016 -0700
@@ -28,6 +28,7 @@
 import java.lang.reflect.*;
 import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Arrays;
 import java.util.Objects;
@@ -37,8 +38,8 @@
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.VerifyAccess;
 import sun.invoke.util.Wrapper;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.util.SecurityConstants;
 import java.lang.invoke.LambdaForm.BasicType;
@@ -53,6 +54,7 @@
 import jdk.internal.org.objectweb.asm.Opcodes;
 
 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
+import static java.lang.invoke.MethodType.methodType;
 
 /**
  * This class consists exclusively of static methods that operate on or return
@@ -3000,7 +3002,7 @@
 
     private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
     private static MethodHandle makeIdentity(Class<?> ptype) {
-        MethodType mtype = MethodType.methodType(ptype, ptype);
+        MethodType mtype = methodType(ptype, ptype);
         LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
     }
@@ -3018,7 +3020,7 @@
     }
     private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
     private static MethodHandle makeZero(Class<?> rtype) {
-        MethodType mtype = MethodType.methodType(rtype);
+        MethodType mtype = methodType(rtype);
         LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
         return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
     }
@@ -3929,7 +3931,7 @@
     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
         if (!Throwable.class.isAssignableFrom(exType))
             throw new ClassCastException(exType.getName());
-        return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
+        return MethodHandleImpl.throwException(methodType(returnType, exType));
     }
 
     /**
@@ -4166,7 +4168,7 @@
         for (int i = 0; i < nclauses; ++i) {
             Class<?> t = iterationVariableTypes.get(i);
             if (init.get(i) == null) {
-                init.set(i, empty(MethodType.methodType(t, commonSuffix)));
+                init.set(i, empty(methodType(t, commonSuffix)));
             }
             if (step.get(i) == null) {
                 step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i));
@@ -4175,7 +4177,7 @@
                 pred.set(i, dropArguments(constant(boolean.class, true), 0, commonParameterSequence));
             }
             if (fini.get(i) == null) {
-                fini.set(i, empty(MethodType.methodType(t, commonParameterSequence)));
+                fini.set(i, empty(methodType(t, commonParameterSequence)));
             }
         }
 
@@ -4269,7 +4271,8 @@
      * @since 9
      */
     public static MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) {
-        MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType());
+        MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) :
+                identity(init.type().returnType());
         MethodHandle[] checkExit = {null, null, pred, fin};
         MethodHandle[] varBody = {init, body};
         return loop(checkExit, varBody);
@@ -4335,7 +4338,8 @@
      * @since 9
      */
     public static MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) {
-        MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType());
+        MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) :
+                identity(init.type().returnType());
         MethodHandle[] clause = {init, body, pred, fin};
         return loop(clause);
     }
@@ -4472,8 +4476,8 @@
      * @since 9
      */
     public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
-        MethodHandle returnVar = dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()),
-                0, int.class, int.class);
+        MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ?
+                zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class);
         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
         MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
         MethodHandle[] bodyClause = {init,
@@ -4485,6 +4489,7 @@
     /**
      * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
      * The iterator will be produced by the evaluation of the {@code iterator} handle.
+     * This handle must have {@link java.util.Iterator} as its return type.
      * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
      * and will be applied to a leading argument of the loop handle.
      * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
@@ -4534,7 +4539,7 @@
      * assertEquals(reversedList, (List<String>) loop.invoke(list));
      * }</pre></blockquote>
      * <p>
-     * @implSpec The implementation of this method is equivalent to:
+     * @implSpec The implementation of this method is equivalent to (excluding error handling):
      * <blockquote><pre>{@code
      * MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
      *     // assume MH_next and MH_hasNext are handles to methods of Iterator
@@ -4550,6 +4555,7 @@
      * }</pre></blockquote>
      *
      * @param iterator a handle to return the iterator to start the loop.
+     *             The handle must have {@link java.util.Iterator} as its return type.
      *             Passing {@code null} will make the loop call {@link Iterable#iterator()} on the first
      *             incoming value.
      * @param init initializer for additional loop state. This determines the loop's result type.
@@ -4565,21 +4571,23 @@
      * @since 9
      */
     public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
-        checkIteratedLoop(body);
+        checkIteratedLoop(iterator, body);
+        final boolean voidInit = init == null || init.type().returnType() == void.class;
 
         MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
         MethodHandle initIterator = iterator == null ?
-                initit.asType(initit.type().changeParameterType(0, body.type().parameterType(init == null ? 1 : 2))) :
+                initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) :
                 iterator;
         Class<?> itype = initIterator.type().returnType();
         Class<?> ttype = body.type().parameterType(0);
 
         MethodHandle returnVar =
-                dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()), 0, itype);
+                dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype);
         MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
         MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype));
 
-        MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred), returnVar};
+        MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred),
+                returnVar};
         MethodHandle[] bodyClause = {init, filterArgument(body, 0, nextVal)};
 
         return loop(iterVar, bodyClause);
@@ -4833,7 +4841,10 @@
         }
     }
 
-    private static void checkIteratedLoop(MethodHandle body) {
+    private static void checkIteratedLoop(MethodHandle iterator, MethodHandle body) {
+        if (null != iterator && !Iterator.class.isAssignableFrom(iterator.type().returnType())) {
+            throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
+        }
         if (null == body) {
             throw newIllegalArgumentException("iterated loop body must not be null");
         }
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Fri Apr 22 01:04:01 2016 -0700
@@ -33,7 +33,6 @@
 import jdk.internal.misc.Unsafe;
 
 import java.lang.invoke.MethodHandles.Lookup;
-import java.security.AccessController;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -188,14 +187,15 @@
     private static final ProxyClassesDumper DUMPER;
 
     static {
-        final String strategy = AccessController.doPrivileged(
-                new GetPropertyAction("java.lang.invoke.stringConcat"));
-        CACHE_ENABLE = Boolean.parseBoolean(AccessController.doPrivileged(
-                new GetPropertyAction("java.lang.invoke.stringConcat.cache")));
-        DEBUG = Boolean.parseBoolean(AccessController.doPrivileged(
-                new GetPropertyAction("java.lang.invoke.stringConcat.debug")));
-        final String dumpPath = AccessController.doPrivileged(
-                new GetPropertyAction("java.lang.invoke.stringConcat.dumpClasses"));
+        Properties props = GetPropertyAction.getProperties();
+        final String strategy =
+                props.getProperty("java.lang.invoke.stringConcat");
+        CACHE_ENABLE = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.stringConcat.cache"));
+        DEBUG = Boolean.parseBoolean(
+                props.getProperty("java.lang.invoke.stringConcat.debug"));
+        final String dumpPath =
+                props.getProperty("java.lang.invoke.stringConcat.dumpClasses");
 
         STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
         CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
--- a/src/java.base/share/classes/java/lang/module/ModuleFinder.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/module/ModuleFinder.java	Fri Apr 22 01:04:01 2016 -0700
@@ -39,6 +39,7 @@
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import sun.security.action.GetPropertyAction;
 
 /**
  * A finder of modules. A {@code ModuleFinder} is used to find modules during
@@ -152,7 +153,7 @@
 
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            PrivilegedAction<String> pa = () -> System.getProperty("java.home");
+            PrivilegedAction<String> pa = new GetPropertyAction("java.home");
             home = AccessController.doPrivileged(pa);
             Permission p = new FilePermission(home + File.separator + "-", "read");
             sm.checkPermission(p);
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java	Fri Apr 22 01:04:01 2016 -0700
@@ -27,9 +27,9 @@
 
 import java.security.AccessController;
 
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
-import sun.reflect.ReflectionFactory;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import jdk.internal.reflect.ReflectionFactory;
 import java.lang.annotation.Annotation;
 
 /**
@@ -230,7 +230,7 @@
     // very early in the bootstrapping process.
     static final ReflectionFactory reflectionFactory =
         AccessController.doPrivileged(
-            new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());
+            new ReflectionFactory.GetReflectionFactoryAction());
 
     /**
      * @throws NullPointerException {@inheritDoc}
--- a/src/java.base/share/classes/java/lang/reflect/Constructor.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java	Fri Apr 22 01:04:01 2016 -0700
@@ -26,9 +26,9 @@
 package java.lang.reflect;
 
 import jdk.internal.misc.SharedSecrets;
-import sun.reflect.CallerSensitive;
-import sun.reflect.ConstructorAccessor;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.ConstructorAccessor;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.annotation.TypeAnnotation;
 import sun.reflect.annotation.TypeAnnotationParser;
 import sun.reflect.generics.repository.ConstructorRepository;
--- a/src/java.base/share/classes/java/lang/reflect/Field.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Field.java	Fri Apr 22 01:04:01 2016 -0700
@@ -26,9 +26,9 @@
 package java.lang.reflect;
 
 import jdk.internal.misc.SharedSecrets;
-import sun.reflect.CallerSensitive;
-import sun.reflect.FieldAccessor;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.FieldAccessor;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.generics.repository.FieldRepository;
 import sun.reflect.generics.factory.CoreReflectionFactory;
 import sun.reflect.generics.factory.GenericsFactory;
--- a/src/java.base/share/classes/java/lang/reflect/Method.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Method.java	Fri Apr 22 01:04:01 2016 -0700
@@ -27,9 +27,9 @@
 
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.SharedSecrets;
-import sun.reflect.CallerSensitive;
-import sun.reflect.MethodAccessor;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.MethodAccessor;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.generics.repository.MethodRepository;
 import sun.reflect.generics.factory.CoreReflectionFactory;
 import sun.reflect.generics.factory.GenericsFactory;
--- a/src/java.base/share/classes/java/lang/reflect/Modifier.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Modifier.java	Fri Apr 22 01:04:01 2016 -0700
@@ -27,8 +27,8 @@
 
 import java.security.AccessController;
 import java.util.StringJoiner;
-import sun.reflect.LangReflectAccess;
-import sun.reflect.ReflectionFactory;
+import jdk.internal.reflect.LangReflectAccess;
+import jdk.internal.reflect.ReflectionFactory;
 
 /**
  * The Modifier class provides {@code static} methods and
@@ -51,8 +51,7 @@
      *  packages
      */
     static {
-        sun.reflect.ReflectionFactory factory =
-            AccessController.doPrivileged(
+        ReflectionFactory factory = AccessController.doPrivileged(
                 new ReflectionFactory.GetReflectionFactoryAction());
         factory.setLangReflectAccess(new java.lang.reflect.ReflectAccess());
     }
--- a/src/java.base/share/classes/java/lang/reflect/Module.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Module.java	Fri Apr 22 01:04:01 2016 -0700
@@ -56,8 +56,8 @@
 import jdk.internal.misc.JavaLangReflectModuleAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.module.ServicesCatalog;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.security.util.SecurityConstants;
 
 /**
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Fri Apr 22 01:04:01 2016 -0700
@@ -47,9 +47,10 @@
 import jdk.internal.module.Modules;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
+import sun.security.action.GetPropertyAction;
 import sun.security.util.SecurityConstants;
 
 /**
@@ -581,11 +582,7 @@
         }
 
         private static final String DEBUG =
-            AccessController.doPrivileged(new PrivilegedAction<>() {
-                public String run() {
-                    return System.getProperty("jdk.proxy.debug", "");
-                }
-            });
+                GetPropertyAction.getProperty("jdk.proxy.debug", "");
 
         private static boolean isDebug() {
             return !DEBUG.isEmpty();
--- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1750,7 +1750,7 @@
          * Get or assign the index for a CONSTANT_Float entry.
          */
         public short getFloat(float f) {
-            return getValue(new Float(f));
+            return getValue(f);
         }
 
         /**
--- a/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java	Fri Apr 22 01:04:01 2016 -0700
@@ -25,14 +25,14 @@
 
 package java.lang.reflect;
 
-import sun.reflect.MethodAccessor;
-import sun.reflect.ConstructorAccessor;
+import jdk.internal.reflect.MethodAccessor;
+import jdk.internal.reflect.ConstructorAccessor;
 
 /** Package-private class implementing the
     sun.reflect.LangReflectAccess interface, allowing the java.lang
     package to instantiate objects in this package. */
 
-class ReflectAccess implements sun.reflect.LangReflectAccess {
+class ReflectAccess implements jdk.internal.reflect.LangReflectAccess {
     public Field newField(Class<?> declaringClass,
                           String name,
                           Class<?> type,
--- a/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Fri Apr 22 01:04:01 2016 -0700
@@ -31,6 +31,7 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Collections;
+import sun.security.action.GetPropertyAction;
 
 /**
  * Abstract datagram and multicast socket implementation base class.
@@ -51,9 +52,7 @@
     protected InetAddress connectedAddress = null;
     private int connectedPort = -1;
 
-    private static final String os = AccessController.doPrivileged(
-        new sun.security.action.GetPropertyAction("os.name")
-    );
+    private static final String os = GetPropertyAction.getProperty("os.name");
 
     /**
      * flag set if the native connect() call not to be used
--- a/src/java.base/share/classes/java/net/InetAddress.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/InetAddress.java	Fri Apr 22 01:04:01 2016 -0700
@@ -894,19 +894,17 @@
      */
     private static final class PlatformNameService implements NameService {
 
-                public InetAddress[] lookupAllHostAddr(String host)
-                    throws UnknownHostException {
-
-                    return impl.lookupAllHostAddr(host);
-
-                            }
-
-        public String getHostByAddr(byte[] addr) throws UnknownHostException {
-
-            return impl.getHostByAddr(addr);
-
+        public InetAddress[] lookupAllHostAddr(String host)
+            throws UnknownHostException
+        {
+            return impl.lookupAllHostAddr(host);
         }
 
+        public String getHostByAddr(byte[] addr)
+            throws UnknownHostException
+        {
+            return impl.getHostByAddr(addr);
+        }
     }
 
     /**
@@ -991,7 +989,6 @@
             return host;
         }
 
-
         /**
          * <p>Lookup a host mapping by name. Retrieve the IP addresses
          * associated with a host.
@@ -1004,7 +1001,6 @@
          * @throws UnknownHostException
          *             if no IP address for the {@code host} could be found
          */
-
         public InetAddress[] lookupAllHostAddr(String host)
                 throws UnknownHostException {
             String hostEntry;
@@ -1127,8 +1123,8 @@
      */
     private static NameService createNameService() {
 
-        String hostsFileName = AccessController
-                .doPrivileged(new GetPropertyAction("jdk.net.hosts.file"));
+        String hostsFileName =
+                GetPropertyAction.getProperty("jdk.net.hosts.file");
         NameService theNameService;
         if (hostsFileName != null) {
             theNameService = new HostsFileNameService(hostsFileName);
@@ -1647,8 +1643,7 @@
          * property can vary across implementations of the java.
          * classes.  The default is an empty String "".
          */
-        String prefix = AccessController.doPrivileged(
-                      new GetPropertyAction("impl.prefix", ""));
+        String prefix = GetPropertyAction.getProperty("impl.prefix", "");
         try {
             impl = Class.forName("java.net." + prefix + implName).newInstance();
         } catch (ClassNotFoundException e) {
--- a/src/java.base/share/classes/java/net/SocksSocketImpl.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java	Fri Apr 22 01:04:01 2016 -0700
@@ -33,6 +33,7 @@
 import sun.net.SocksProxy;
 import sun.net.spi.DefaultProxySelector;
 import sun.net.www.ParseUtil;
+import sun.security.action.GetPropertyAction;
 /* import org.ietf.jgss.*; */
 
 /**
@@ -177,8 +178,7 @@
                 userName = pw.getUserName();
                 password = new String(pw.getPassword());
             } else {
-                userName = java.security.AccessController.doPrivileged(
-                        new sun.security.action.GetPropertyAction("user.name"));
+                userName = GetPropertyAction.getProperty("user.name");
             }
             if (userName == null)
                 return false;
@@ -1088,8 +1088,7 @@
                 userName = System.getProperty("user.name");
             } catch (SecurityException se) { /* swallow Exception */ }
         } else {
-            userName = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction("user.name"));
+            userName = GetPropertyAction.getProperty("user.name");
         }
         return userName;
     }
--- a/src/java.base/share/classes/java/net/URL.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/URL.java	Fri Apr 22 01:04:01 2016 -0700
@@ -42,6 +42,7 @@
 import java.util.ServiceLoader;
 
 import sun.security.util.SecurityConstants;
+import sun.security.action.GetPropertyAction;
 
 /**
  * Class {@code URL} represents a Uniform Resource
@@ -1210,12 +1211,8 @@
     }
 
     private static URLStreamHandler lookupViaProperty(String protocol) {
-        String packagePrefixList = java.security.AccessController.doPrivileged(
-                new PrivilegedAction<>() {
-                    public String run() {
-                        return System.getProperty(protocolPathProp, null);
-                    }
-                });
+        String packagePrefixList =
+                GetPropertyAction.getProperty(protocolPathProp);
         if (packagePrefixList == null) {
             // not set
             return null;
--- a/src/java.base/share/classes/java/net/URLConnection.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/URLConnection.java	Fri Apr 22 01:04:01 2016 -0700
@@ -43,6 +43,7 @@
 import java.security.AccessController;
 import sun.security.util.SecurityConstants;
 import sun.net.www.MessageHeader;
+import sun.security.action.GetPropertyAction;
 
 /**
  * The abstract class {@code URLConnection} is the superclass
@@ -1395,8 +1396,8 @@
      * is always the last one on the returned package list.
      */
     private String getContentHandlerPkgPrefixes() {
-        String packagePrefixList = AccessController.doPrivileged(
-            new sun.security.action.GetPropertyAction(contentPathProp, ""));
+        String packagePrefixList =
+                GetPropertyAction.getProperty(contentPathProp, "");
 
         if (packagePrefixList != "") {
             packagePrefixList += "|";
--- a/src/java.base/share/classes/java/net/URLEncoder.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/URLEncoder.java	Fri Apr 22 01:04:01 2016 -0700
@@ -25,19 +25,12 @@
 
 package java.net;
 
-import java.io.ByteArrayOutputStream;
-import java.io.BufferedWriter;
-import java.io.OutputStreamWriter;
-import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.io.CharArrayWriter;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException ;
 import java.util.BitSet;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetBooleanAction;
 import sun.security.action.GetPropertyAction;
 
 /**
@@ -140,9 +133,7 @@
         dontNeedEncoding.set('.');
         dontNeedEncoding.set('*');
 
-        dfltEncName = AccessController.doPrivileged(
-            new GetPropertyAction("file.encoding")
-        );
+        dfltEncName = GetPropertyAction.getProperty("file.encoding");
     }
 
     /**
--- a/src/java.base/share/classes/java/net/URLPermission.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/net/URLPermission.java	Fri Apr 22 01:04:01 2016 -0700
@@ -170,7 +170,8 @@
         parseURI(getName());
         int colon = actions.indexOf(':');
         if (actions.lastIndexOf(':') != colon) {
-            throw new IllegalArgumentException("invalid actions string");
+            throw new IllegalArgumentException(
+                "Invalid actions string: \"" + actions + "\"");
         }
 
         String methods, headers;
@@ -371,7 +372,8 @@
                     l.add(s);
                 b = new StringBuilder();
             } else if (c == ' ' || c == '\t') {
-                throw new IllegalArgumentException("white space not allowed");
+                throw new IllegalArgumentException(
+                    "White space not allowed in methods: \"" + methods + "\"");
             } else {
                 if (c >= 'a' && c <= 'z') {
                     c += 'A' - 'a';
@@ -398,7 +400,8 @@
                 }
                 b.append(c);
             } else if (c == ' ' || c == '\t') {
-                throw new IllegalArgumentException("white space not allowed");
+                throw new IllegalArgumentException(
+                    "White space not allowed in headers: \"" + headers + "\"");
             } else if (c == '-') {
                     capitalizeNext = true;
                 b.append(c);
@@ -423,14 +426,16 @@
         int len = url.length();
         int delim = url.indexOf(':');
         if (delim == -1 || delim + 1 == len) {
-            throw new IllegalArgumentException("invalid URL string");
+            throw new IllegalArgumentException(
+                "Invalid URL string: \"" + url + "\"");
         }
         scheme = url.substring(0, delim).toLowerCase();
         this.ssp = url.substring(delim + 1);
 
         if (!ssp.startsWith("//")) {
             if (!ssp.equals("*")) {
-                throw new IllegalArgumentException("invalid URL string");
+                throw new IllegalArgumentException(
+                    "Invalid URL string: \"" + url + "\"");
             }
             this.authority = new Authority(scheme, "*");
             return;
--- a/src/java.base/share/classes/java/nio/charset/Charset.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/nio/charset/Charset.java	Fri Apr 22 01:04:01 2016 -0700
@@ -283,8 +283,8 @@
         if (level == null) {
             if (!VM.isBooted())
                 return false;
-            bugLevel = level = AccessController.doPrivileged(
-                new GetPropertyAction("sun.nio.cs.bugLevel", ""));
+            bugLevel = level =
+                    GetPropertyAction.getProperty("sun.nio.cs.bugLevel", "");
         }
         return level.equals(bl);
     }
@@ -609,8 +609,7 @@
     public static Charset defaultCharset() {
         if (defaultCharset == null) {
             synchronized (Charset.class) {
-                String csn = AccessController.doPrivileged(
-                    new GetPropertyAction("file.encoding"));
+                String csn = GetPropertyAction.getProperty("file.encoding");
                 Charset cs = lookup(csn);
                 if (cs != null)
                     defaultCharset = cs;
--- a/src/java.base/share/classes/java/nio/file/TempFileHelper.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/nio/file/TempFileHelper.java	Fri Apr 22 01:04:01 2016 -0700
@@ -28,7 +28,6 @@
 import java.util.Set;
 import java.util.EnumSet;
 import java.security.SecureRandom;
-import static java.security.AccessController.*;
 import java.io.IOException;
 import java.nio.file.attribute.FileAttribute;
 import java.nio.file.attribute.PosixFilePermission;
@@ -47,7 +46,7 @@
 
     // temporary directory location
     private static final Path tmpdir =
-        Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+        Paths.get(GetPropertyAction.getProperty("java.io.tmpdir"));
 
     private static final boolean isPosix =
         FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
--- a/src/java.base/share/classes/java/security/AccessController.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/security/AccessController.java	Fri Apr 22 01:04:01 2016 -0700
@@ -26,8 +26,8 @@
 package java.security;
 
 import sun.security.util.Debug;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 /**
  * <p> The AccessController class is used for access control operations
--- a/src/java.base/share/classes/java/text/ChoiceFormat.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/text/ChoiceFormat.java	Fri Apr 22 01:04:01 2016 -0700
@@ -437,7 +437,7 @@
         if (status.index == start) {
             status.errorIndex = furthest;
         }
-        return new Double(bestNumber);
+        return Double.valueOf(bestNumber);
     }
 
     /**
--- a/src/java.base/share/classes/java/text/DecimalFormat.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/text/DecimalFormat.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1996,7 +1996,7 @@
         // special case NaN
         if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
             pos.index = pos.index + symbols.getNaN().length();
-            return new Double(Double.NaN);
+            return Double.valueOf(Double.NaN);
         }
 
         boolean[] status = new boolean[STATUS_LENGTH];
@@ -2007,19 +2007,19 @@
         // special case INFINITY
         if (status[STATUS_INFINITE]) {
             if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
-                return new Double(Double.POSITIVE_INFINITY);
+                return Double.valueOf(Double.POSITIVE_INFINITY);
             } else {
-                return new Double(Double.NEGATIVE_INFINITY);
+                return Double.valueOf(Double.NEGATIVE_INFINITY);
             }
         }
 
         if (multiplier == 0) {
             if (digitList.isZero()) {
-                return new Double(Double.NaN);
+                return Double.valueOf(Double.NaN);
             } else if (status[STATUS_POSITIVE]) {
-                return new Double(Double.POSITIVE_INFINITY);
+                return Double.valueOf(Double.POSITIVE_INFINITY);
             } else {
-                return new Double(Double.NEGATIVE_INFINITY);
+                return Double.valueOf(Double.NEGATIVE_INFINITY);
             }
         }
 
@@ -2093,8 +2093,8 @@
                             !isParseIntegerOnly();
             }
 
-            return gotDouble ?
-                (Number)new Double(doubleResult) : (Number)Long.valueOf(longResult);
+            // cast inside of ?: because of binary numeric promotion, JLS 15.25
+            return gotDouble ? (Number)doubleResult : (Number)longResult;
         }
     }
 
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1539,8 +1539,8 @@
      * <pre>
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffsetPrefixed(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffsetPrefixed(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT);
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL);
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -3519,9 +3519,7 @@
                 return false;
             }
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                buf.append(gmtText);
-            }
+            buf.append(gmtText);
             int totalSecs = Math.toIntExact(offsetSecs);
             if (totalSecs != 0) {
                 int absHours = Math.abs((totalSecs / 3600) % 100);  // anything larger than 99 silently dropped
@@ -3565,14 +3563,12 @@
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
             int pos = position;
-            int end = pos + text.length();
+            int end = text.length();
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
+            if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
                     return ~position;
                 }
-                pos += gmtText.length();
-            }
+            pos += gmtText.length();
             // parse normal plus/minus offset
             int negative = 0;
             if (pos == end) {
--- a/src/java.base/share/classes/java/util/Locale.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/Locale.java	Fri Apr 22 01:04:01 2016 -0700
@@ -45,7 +45,6 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
 import java.io.Serializable;
-import java.security.AccessController;
 import java.text.MessageFormat;
 import java.util.spi.LocaleNameProvider;
 
@@ -859,11 +858,10 @@
 
     private static Locale initDefault() {
         String language, region, script, country, variant;
-        language = AccessController.doPrivileged(
-            new GetPropertyAction("user.language", "en"));
+        Properties props = GetPropertyAction.getProperties();
+        language = props.getProperty("user.language", "en");
         // for compatibility, check for old user.region property
-        region = AccessController.doPrivileged(
-            new GetPropertyAction("user.region"));
+        region = props.getProperty("user.region");
         if (region != null) {
             // region can be of form country, country_variant, or _variant
             int i = region.indexOf('_');
@@ -876,27 +874,25 @@
             }
             script = "";
         } else {
-            script = AccessController.doPrivileged(
-                new GetPropertyAction("user.script", ""));
-            country = AccessController.doPrivileged(
-                new GetPropertyAction("user.country", ""));
-            variant = AccessController.doPrivileged(
-                new GetPropertyAction("user.variant", ""));
+            script = props.getProperty("user.script", "");
+            country = props.getProperty("user.country", "");
+            variant = props.getProperty("user.variant", "");
         }
 
         return getInstance(language, script, country, variant, null);
     }
 
     private static Locale initDefault(Locale.Category category) {
+        Properties props = GetPropertyAction.getProperties();
         return getInstance(
-            AccessController.doPrivileged(
-                new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())),
-            AccessController.doPrivileged(
-                new GetPropertyAction(category.scriptKey, defaultLocale.getScript())),
-            AccessController.doPrivileged(
-                new GetPropertyAction(category.countryKey, defaultLocale.getCountry())),
-            AccessController.doPrivileged(
-                new GetPropertyAction(category.variantKey, defaultLocale.getVariant())),
+            props.getProperty(category.languageKey,
+                    defaultLocale.getLanguage()),
+            props.getProperty(category.scriptKey,
+                    defaultLocale.getScript()),
+            props.getProperty(category.countryKey,
+                    defaultLocale.getCountry()),
+            props.getProperty(category.variantKey,
+                    defaultLocale.getVariant()),
             null);
     }
 
--- a/src/java.base/share/classes/java/util/PropertyResourceBundle.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/PropertyResourceBundle.java	Fri Apr 22 01:04:01 2016 -0700
@@ -43,7 +43,6 @@
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.IOException;
-import java.nio.charset.Charset;
 import java.nio.charset.MalformedInputException;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.UnmappableCharacterException;
@@ -142,8 +141,8 @@
     // Check whether the strict encoding is specified.
     // The possible encoding is either "ISO-8859-1" or "UTF-8".
     private static final String encoding =
-        AccessController.doPrivileged(
-            new GetPropertyAction("java.util.PropertyResourceBundle.encoding", ""))
+        GetPropertyAction
+                .getProperty("java.util.PropertyResourceBundle.encoding", "")
         .toUpperCase(Locale.ROOT);
 
     /**
--- a/src/java.base/share/classes/java/util/ResourceBundle.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/ResourceBundle.java	Fri Apr 22 01:04:01 2016 -0700
@@ -64,8 +64,8 @@
 
 import jdk.internal.misc.JavaUtilResourceBundleAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import sun.util.locale.BaseLocale;
 import sun.util.locale.LocaleObjectCache;
 import sun.util.locale.provider.ResourceBundleProviderSupport;
--- a/src/java.base/share/classes/java/util/ServiceLoader.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java	Fri Apr 22 01:04:01 2016 -0700
@@ -51,8 +51,8 @@
 import jdk.internal.module.ServicesCatalog;
 import jdk.internal.module.ServicesCatalog.ServiceProvider;
 
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 
 /**
--- a/src/java.base/share/classes/java/util/TimeZone.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/TimeZone.java	Fri Apr 22 01:04:01 2016 -0700
@@ -660,14 +660,12 @@
     private static synchronized TimeZone setDefaultZone() {
         TimeZone tz;
         // get the time zone ID from the system properties
-        String zoneID = AccessController.doPrivileged(
-                new GetPropertyAction("user.timezone"));
+        String zoneID = GetPropertyAction.getProperty("user.timezone");
 
         // if the time zone ID is not set (yet), perform the
         // platform to Java time zone ID mapping.
         if (zoneID == null || zoneID.isEmpty()) {
-            String javaHome = AccessController.doPrivileged(
-                    new GetPropertyAction("java.home"));
+            String javaHome = GetPropertyAction.getProperty("java.home");
             try {
                 zoneID = getSystemTimeZoneID(javaHome);
                 if (zoneID == null) {
--- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Fri Apr 22 01:04:01 2016 -0700
@@ -455,7 +455,7 @@
             s = v1 * v1 + v2 * v2;
         } while (s >= 1 || s == 0);
         double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
-        nextLocalGaussian.set(new Double(v2 * multiplier));
+        nextLocalGaussian.set(Double.valueOf(v2 * multiplier));
         return v1 * multiplier;
     }
 
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Fri Apr 22 01:04:01 2016 -0700
@@ -42,8 +42,8 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 /**
  * A reflection-based utility that enables atomic updates to
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Fri Apr 22 01:04:01 2016 -0700
@@ -42,8 +42,8 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 /**
  * A reflection-based utility that enables atomic updates to
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Fri Apr 22 01:04:01 2016 -0700
@@ -42,8 +42,8 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 /**
  * A reflection-based utility that enables atomic updates to
--- a/src/java.base/share/classes/java/util/jar/JarFile.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/jar/JarFile.java	Fri Apr 22 01:04:01 2016 -0700
@@ -34,7 +34,6 @@
 import java.util.zip.*;
 import java.security.CodeSigner;
 import java.security.cert.Certificate;
-import java.security.AccessController;
 import java.security.CodeSource;
 import jdk.internal.misc.SharedSecrets;
 import sun.security.action.GetPropertyAction;
@@ -155,16 +154,16 @@
 
         BASE_VERSION = 8;  // one less than lowest version for versioned entries
         int runtimeVersion = jdk.Version.current().major();
-        String jarVersion = AccessController.doPrivileged(
-                new GetPropertyAction("jdk.util.jar.version"));
+        String jarVersion =
+                GetPropertyAction.getProperty("jdk.util.jar.version");
         if (jarVersion != null) {
             int jarVer = Integer.parseInt(jarVersion);
             runtimeVersion = (jarVer > runtimeVersion)
                     ? runtimeVersion : Math.max(jarVer, 0);
         }
         RUNTIME_VERSION = runtimeVersion;
-        String enableMultiRelease = AccessController.doPrivileged(
-                new GetPropertyAction("jdk.util.jar.enableMultiRelease", "true"));
+        String enableMultiRelease = GetPropertyAction
+                .getProperty("jdk.util.jar.enableMultiRelease", "true");
         switch (enableMultiRelease) {
             case "true":
             default:
--- a/src/java.base/share/classes/java/util/jar/Pack200.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/jar/Pack200.java	Fri Apr 22 01:04:01 2016 -0700
@@ -29,6 +29,7 @@
 import java.io.OutputStream;
 import java.io.File;
 import java.io.IOException;
+import sun.security.action.GetPropertyAction;
 
 
 /**
@@ -694,8 +695,7 @@
             Class<?> impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl;
             if (impl == null) {
                 // The first time, we must decide which class to use.
-                implName = java.security.AccessController.doPrivileged(
-                    new sun.security.action.GetPropertyAction(prop,""));
+                implName = GetPropertyAction.getProperty(prop,"");
                 if (implName != null && !implName.equals(""))
                     impl = Class.forName(implName);
                 else if (PACK_PROVIDER.equals(prop))
--- a/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java	Fri Apr 22 01:04:01 2016 -0700
@@ -94,8 +94,7 @@
     }
 
     private static final String nl =
-        java.security.AccessController
-            .doPrivileged(new GetPropertyAction("line.separator"));
+            GetPropertyAction.getProperty("line.separator");
 
     /**
      * Returns a multi-line string containing the description of the syntax
--- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java	Fri Apr 22 01:04:01 2016 -0700
@@ -33,6 +33,7 @@
 import java.util.HashSet;
 import static java.util.zip.ZipConstants64.*;
 import static java.util.zip.ZipUtils.*;
+import sun.security.action.GetPropertyAction;
 
 /**
  * This class implements an output stream filter for writing files in the
@@ -54,9 +55,7 @@
      */
     private static final boolean inhibitZip64 =
         Boolean.parseBoolean(
-            java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                    "jdk.util.zip.inhibitZip64", "false")));
+            GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64"));
 
     private static class XEntry {
         final ZipEntry entry;
--- a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java	Fri Apr 22 01:04:01 2016 -0700
@@ -51,9 +51,9 @@
     static final boolean DEBUG;
 
     static {
-        String s = java.security.AccessController.doPrivileged(
-            new GetPropertyAction("javax.net.debug", "")).toLowerCase(
-                                                            Locale.ENGLISH);
+        String s = GetPropertyAction.getProperty("javax.net.debug", "")
+                .toLowerCase(Locale.ENGLISH);
+
         DEBUG = s.contains("all") || s.contains("ssl");
     }
 
--- a/src/java.base/share/classes/jdk/Version.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/Version.java	Fri Apr 22 01:04:01 2016 -0700
@@ -26,8 +26,6 @@
 package jdk;
 
 import java.math.BigInteger;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -35,6 +33,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import sun.security.action.GetPropertyAction;
 
 /**
  * A representation of the JDK version-string which contains a version
@@ -274,12 +273,7 @@
      */
     public static Version current() {
         if (current == null) {
-            current = parse(AccessController.doPrivileged(
-                new PrivilegedAction<>() {
-                    public String run() {
-                        return System.getProperty("java.version");
-                    }
-                }));
+            current = parse(GetPropertyAction.getProperty("java.version"));
         }
         return current;
     }
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Fri Apr 22 01:04:01 2016 -0700
@@ -136,7 +136,7 @@
         private final BasicFileAttributes fileAttrs;
         private boolean completed;
 
-        Node(String name, BasicFileAttributes fileAttrs) {
+        protected Node(String name, BasicFileAttributes fileAttrs) {
             this.name = Objects.requireNonNull(name);
             this.fileAttrs = Objects.requireNonNull(fileAttrs);
         }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileAttributes.java	Thu Apr 21 15:04:00 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jrtfs;
-
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.Formatter;
-
-/**
- * Base class for file attributes supported by jrt file systems.
- *
- * @implNote This class needs to maintain JDK 8 source compatibility.
- *
- * It is used internally in the JDK to implement jimage/jrtfs access,
- * but also compiled and delivered as part of the jrtfs.jar to support access
- * to the jimage file provided by the shipped JDK by tools running on JDK 8.
- */
-public abstract class AbstractJrtFileAttributes implements BasicFileAttributes {
-
-    // jrt fs specific attributes
-    /**
-     * Compressed resource file. If not available or not applicable, 0L is
-     * returned.
-     *
-     * @return the compressed resource size for compressed resources.
-     */
-    public abstract long compressedSize();
-
-    /**
-     * "file" extension of a file resource.
-     *
-     * @return extension string for the file resource
-     */
-    public abstract String extension();
-
-    @Override
-    public final String toString() {
-        StringBuilder sb = new StringBuilder(1024);
-        try (Formatter fm = new Formatter(sb)) {
-            if (creationTime() != null) {
-                fm.format("    creationTime    : %tc%n", creationTime().toMillis());
-            } else {
-                fm.format("    creationTime    : null%n");
-            }
-
-            if (lastAccessTime() != null) {
-                fm.format("    lastAccessTime  : %tc%n", lastAccessTime().toMillis());
-            } else {
-                fm.format("    lastAccessTime  : null%n");
-            }
-            fm.format("    lastModifiedTime: %tc%n", lastModifiedTime().toMillis());
-            fm.format("    isRegularFile   : %b%n", isRegularFile());
-            fm.format("    isDirectory     : %b%n", isDirectory());
-            fm.format("    isSymbolicLink  : %b%n", isSymbolicLink());
-            fm.format("    isOther         : %b%n", isOther());
-            fm.format("    fileKey         : %s%n", fileKey());
-            fm.format("    size            : %d%n", size());
-            fm.format("    compressedSize  : %d%n", compressedSize());
-            fm.format("    extension       : %s%n", extension());
-        }
-        return sb.toString();
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java	Thu Apr 21 15:04:00 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jrtfs;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
-import java.nio.channels.NonWritableChannelException;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.SeekableByteChannel;
-import java.nio.charset.Charset;
-import java.nio.file.ClosedFileSystemException;
-import java.nio.file.CopyOption;
-import java.nio.file.FileStore;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystemNotFoundException;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
-import java.nio.file.PathMatcher;
-import java.nio.file.ReadOnlyFileSystemException;
-import java.nio.file.StandardOpenOption;
-import java.nio.file.WatchService;
-import java.nio.file.attribute.FileAttribute;
-import java.nio.file.attribute.FileTime;
-import java.nio.file.attribute.UserPrincipalLookupService;
-import java.nio.file.spi.FileSystemProvider;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-/**
- * Base class for jrt file systems. jrt filesystem implementations are currently
- * available on top of .jimage file and on top "exploded" build directories.
- *
- * @implNote This class needs to maintain JDK 8 source compatibility.
- *
- * It is used internally in the JDK to implement jimage/jrtfs access,
- * but also compiled and delivered as part of the jrtfs.jar to support access
- * to the jimage file provided by the shipped JDK by tools running on JDK 8.
- */
-abstract class AbstractJrtFileSystem extends FileSystem {
-
-    private final JrtFileSystemProvider provider;
-
-    AbstractJrtFileSystem(JrtFileSystemProvider provider, Map<String, ?> options) {
-        this.provider = provider;
-    }
-
-    private static final Charset UTF_8 = Charset.forName("UTF-8");
-
-    // static utility methods
-    static ReadOnlyFileSystemException readOnly() {
-        return new ReadOnlyFileSystemException();
-    }
-
-    // if a Path does not exist, throw exception
-    static void checkExists(Path path) {
-        if (Files.notExists(path)) {
-            throw new FileSystemNotFoundException(path.toString());
-        }
-    }
-
-    static byte[] getBytes(String name) {
-        return name.getBytes(UTF_8);
-    }
-
-    static String getString(byte[] name) {
-        return new String(name, UTF_8);
-    }
-
-    // do the supplied options imply that we have to chase symlinks?
-    static boolean followLinks(LinkOption... options) {
-        if (options != null) {
-            for (LinkOption lo : options) {
-                if (lo == LinkOption.NOFOLLOW_LINKS) {
-                    return false;
-                } else if (lo == null) {
-                    throw new NullPointerException();
-                } else {
-                    throw new AssertionError("should not reach here");
-                }
-            }
-        }
-        return true;
-    }
-
-    // check that the options passed are supported by (read-only) jrt file system
-    static void checkOptions(Set<? extends OpenOption> options) {
-        // check for options of null type and option is an intance of StandardOpenOption
-        for (OpenOption option : options) {
-            if (option == null) {
-                throw new NullPointerException();
-            }
-            if (!(option instanceof StandardOpenOption)) {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        if (options.contains(StandardOpenOption.WRITE)
-                || options.contains(StandardOpenOption.APPEND)) {
-            throw readOnly();
-        }
-    }
-
-    // FileSystem method implementations
-    @Override
-    public FileSystemProvider provider() {
-        return provider;
-    }
-
-    @Override
-    public Iterable<Path> getRootDirectories() {
-        ArrayList<Path> pathArr = new ArrayList<>();
-        pathArr.add(getRootPath());
-        return pathArr;
-    }
-
-    @Override
-    public AbstractJrtPath getPath(String first, String... more) {
-        String path;
-        if (more.length == 0) {
-            path = first;
-        } else {
-            StringBuilder sb = new StringBuilder();
-            sb.append(first);
-            for (String segment : more) {
-                if (segment.length() > 0) {
-                    if (sb.length() > 0) {
-                        sb.append('/');
-                    }
-                    sb.append(segment);
-                }
-            }
-            path = sb.toString();
-        }
-        return getRootPath().newJrtPath(getBytes(path));
-    }
-
-    @Override
-    public final boolean isReadOnly() {
-        return true;
-    }
-
-    @Override
-    public final UserPrincipalLookupService getUserPrincipalLookupService() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public final WatchService newWatchService() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public final Iterable<FileStore> getFileStores() {
-        ArrayList<FileStore> list = new ArrayList<>(1);
-        list.add(getFileStore(getRootPath()));
-        return list;
-    }
-
-    private static final Set<String> supportedFileAttributeViews
-            = Collections.unmodifiableSet(
-                    new HashSet<String>(Arrays.asList("basic", "jrt")));
-
-    @Override
-    public final Set<String> supportedFileAttributeViews() {
-        return supportedFileAttributeViews;
-    }
-
-    @Override
-    public final String toString() {
-        return "jrt:/";
-    }
-
-    @Override
-    public final String getSeparator() {
-        return "/";
-    }
-
-    private static final String GLOB_SYNTAX = "glob";
-    private static final String REGEX_SYNTAX = "regex";
-
-    @Override
-    public PathMatcher getPathMatcher(String syntaxAndInput) {
-        int pos = syntaxAndInput.indexOf(':');
-        if (pos <= 0 || pos == syntaxAndInput.length()) {
-            throw new IllegalArgumentException();
-        }
-        String syntax = syntaxAndInput.substring(0, pos);
-        String input = syntaxAndInput.substring(pos + 1);
-        String expr;
-        if (syntax.equalsIgnoreCase(GLOB_SYNTAX)) {
-            expr = JrtUtils.toRegexPattern(input);
-        } else {
-            if (syntax.equalsIgnoreCase(REGEX_SYNTAX)) {
-                expr = input;
-            } else {
-                throw new UnsupportedOperationException("Syntax '" + syntax
-                        + "' not recognized");
-            }
-        }
-        // return matcher
-        final Pattern pattern = Pattern.compile(expr);
-        return (Path path) -> pattern.matcher(path.toString()).matches();
-    }
-
-    // These methods throw read only file system exception
-    final void setTimes(AbstractJrtPath jrtPath, FileTime mtime, FileTime atime, FileTime ctime)
-            throws IOException {
-        throw readOnly();
-    }
-
-    final void createDirectory(AbstractJrtPath jrtPath, FileAttribute<?>... attrs) throws IOException {
-        throw readOnly();
-    }
-
-    final void deleteFile(AbstractJrtPath jrtPath, boolean failIfNotExists)
-            throws IOException {
-        throw readOnly();
-    }
-
-    final OutputStream newOutputStream(AbstractJrtPath jrtPath, OpenOption... options)
-            throws IOException {
-        throw readOnly();
-    }
-
-    final void copyFile(boolean deletesrc, AbstractJrtPath srcPath, AbstractJrtPath dstPath, CopyOption... options)
-            throws IOException {
-        throw readOnly();
-    }
-
-    final FileChannel newFileChannel(AbstractJrtPath jrtPath,
-            Set<? extends OpenOption> options,
-            FileAttribute<?>... attrs)
-            throws IOException {
-        throw new UnsupportedOperationException("newFileChannel");
-    }
-
-    final InputStream newInputStream(AbstractJrtPath jrtPath) throws IOException {
-        return new ByteArrayInputStream(getFileContent(jrtPath));
-    }
-
-    final SeekableByteChannel newByteChannel(AbstractJrtPath jrtPath,
-            Set<? extends OpenOption> options,
-            FileAttribute<?>... attrs)
-            throws IOException {
-        checkOptions(options);
-
-        byte[] buf = getFileContent(jrtPath);
-        final ReadableByteChannel rbc
-                = Channels.newChannel(new ByteArrayInputStream(buf));
-        final long size = buf.length;
-        return new SeekableByteChannel() {
-            long read = 0;
-
-            @Override
-            public boolean isOpen() {
-                return rbc.isOpen();
-            }
-
-            @Override
-            public long position() throws IOException {
-                return read;
-            }
-
-            @Override
-            public SeekableByteChannel position(long pos)
-                    throws IOException {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public int read(ByteBuffer dst) throws IOException {
-                int n = rbc.read(dst);
-                if (n > 0) {
-                    read += n;
-                }
-                return n;
-            }
-
-            @Override
-            public SeekableByteChannel truncate(long size)
-                    throws IOException {
-                throw new NonWritableChannelException();
-            }
-
-            @Override
-            public int write(ByteBuffer src) throws IOException {
-                throw new NonWritableChannelException();
-            }
-
-            @Override
-            public long size() throws IOException {
-                return size;
-            }
-
-            @Override
-            public void close() throws IOException {
-                rbc.close();
-            }
-        };
-    }
-
-    final JrtFileStore getFileStore(AbstractJrtPath jrtPath) {
-        return new JrtFileStore(jrtPath);
-    }
-
-    final void ensureOpen() throws IOException {
-        if (!isOpen()) {
-            throw new ClosedFileSystemException();
-        }
-    }
-
-    // abstract methods to be implemented by a particular jrt file system
-    abstract AbstractJrtPath getRootPath();
-
-    abstract boolean isSameFile(AbstractJrtPath jrtPath1, AbstractJrtPath jrtPath2) throws IOException;
-
-    abstract boolean isLink(AbstractJrtPath jrtPath) throws IOException;
-
-    abstract AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException;
-
-    abstract AbstractJrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException;
-
-    abstract boolean exists(AbstractJrtPath jrtPath) throws IOException;
-
-    abstract boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException;
-
-    /**
-     * returns the list of child paths of the given directory "path"
-     *
-     * @param path name of the directory whose content is listed
-     * @return iterator for child paths of the given directory path
-     */
-    abstract Iterator<Path> iteratorOf(AbstractJrtPath jrtPath) throws IOException;
-
-    // returns the content of the file resource specified by the path
-    abstract byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException;
-}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java	Thu Apr 21 15:04:00 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,935 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jrtfs;
-
-import java.io.*;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.DirectoryStream.Filter;
-import java.nio.file.attribute.*;
-import java.util.*;
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
-
-/**
- * Base class for Path implementation of jrt file systems.
- *
- * @implNote This class needs to maintain JDK 8 source compatibility.
- *
- * It is used internally in the JDK to implement jimage/jrtfs access,
- * but also compiled and delivered as part of the jrtfs.jar to support access
- * to the jimage file provided by the shipped JDK by tools running on JDK 8.
- */
-abstract class AbstractJrtPath implements Path {
-
-    protected final AbstractJrtFileSystem jrtfs;
-    private final byte[] path;
-    private volatile int[] offsets;
-    private int hashcode = 0;  // cached hashcode (created lazily)
-
-    AbstractJrtPath(AbstractJrtFileSystem jrtfs, byte[] path) {
-        this(jrtfs, path, false);
-        this.resolved = null;
-    }
-
-    AbstractJrtPath(AbstractJrtFileSystem jrtfs, byte[] path, boolean normalized) {
-        this.resolved = null;
-        this.jrtfs = jrtfs;
-        if (normalized) {
-            this.path = path;
-        } else {
-            this.path = normalize(path);
-        }
-    }
-
-    // factory methods to create subtypes of AbstractJrtPath
-    protected abstract AbstractJrtPath newJrtPath(byte[] path);
-
-    protected abstract AbstractJrtPath newJrtPath(byte[] path, boolean normalized);
-
-    final byte[] getName() {
-        return path;
-    }
-
-    @Override
-    public final AbstractJrtPath getRoot() {
-        if (this.isAbsolute()) {
-            return jrtfs.getRootPath();
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    public final AbstractJrtPath getFileName() {
-        initOffsets();
-        int count = offsets.length;
-        if (count == 0) {
-            return null;  // no elements so no name
-        }
-        if (count == 1 && path[0] != '/') {
-            return this;
-        }
-        int lastOffset = offsets[count - 1];
-        int len = path.length - lastOffset;
-        byte[] result = new byte[len];
-        System.arraycopy(path, lastOffset, result, 0, len);
-        return newJrtPath(result);
-    }
-
-    @Override
-    public final AbstractJrtPath getParent() {
-        initOffsets();
-        int count = offsets.length;
-        if (count == 0) // no elements so no parent
-        {
-            return null;
-        }
-        int len = offsets[count - 1] - 1;
-        if (len <= 0) // parent is root only (may be null)
-        {
-            return getRoot();
-        }
-        byte[] result = new byte[len];
-        System.arraycopy(path, 0, result, 0, len);
-        return newJrtPath(result);
-    }
-
-    @Override
-    public final int getNameCount() {
-        initOffsets();
-        return offsets.length;
-    }
-
-    @Override
-    public final AbstractJrtPath getName(int index) {
-        initOffsets();
-        if (index < 0 || index >= offsets.length) {
-            throw new IllegalArgumentException();
-        }
-        int begin = offsets[index];
-        int len;
-        if (index == (offsets.length - 1)) {
-            len = path.length - begin;
-        } else {
-            len = offsets[index + 1] - begin - 1;
-        }
-        // construct result
-        byte[] result = new byte[len];
-        System.arraycopy(path, begin, result, 0, len);
-        return newJrtPath(result);
-    }
-
-    @Override
-    public final AbstractJrtPath subpath(int beginIndex, int endIndex) {
-        initOffsets();
-        if (beginIndex < 0
-                || beginIndex >= offsets.length
-                || endIndex > offsets.length
-                || beginIndex >= endIndex) {
-            throw new IllegalArgumentException();
-        }
-
-        // starting offset and length
-        int begin = offsets[beginIndex];
-        int len;
-        if (endIndex == offsets.length) {
-            len = path.length - begin;
-        } else {
-            len = offsets[endIndex] - begin - 1;
-        }
-        // construct result
-        byte[] result = new byte[len];
-        System.arraycopy(path, begin, result, 0, len);
-        return newJrtPath(result);
-    }
-
-    @Override
-    public final AbstractJrtPath toRealPath(LinkOption... options) throws IOException {
-        AbstractJrtPath realPath = newJrtPath(getResolvedPath()).toAbsolutePath();
-        realPath = JrtFileSystem.followLinks(options) ? jrtfs.resolveLink(this) : realPath;
-        realPath.checkAccess();
-        return realPath;
-    }
-
-    final AbstractJrtPath readSymbolicLink() throws IOException {
-        if (!jrtfs.isLink(this)) {
-            throw new IOException("not a symbolic link");
-        }
-
-        return jrtfs.resolveLink(this);
-    }
-
-    final boolean isHidden() {
-        return false;
-    }
-
-    @Override
-    public final AbstractJrtPath toAbsolutePath() {
-        if (isAbsolute()) {
-            return this;
-        } else {
-            //add / bofore the existing path
-            byte[] tmp = new byte[path.length + 1];
-            tmp[0] = '/';
-            System.arraycopy(path, 0, tmp, 1, path.length);
-            return newJrtPath(tmp).normalize();
-        }
-    }
-
-    @Override
-    public final URI toUri() {
-        try {
-            return new URI("jrt",
-                    JrtFileSystem.getString(toAbsolutePath().path),
-                    null);
-        } catch (URISyntaxException ex) {
-            throw new AssertionError(ex);
-        }
-    }
-
-    private boolean equalsNameAt(AbstractJrtPath other, int index) {
-        int mbegin = offsets[index];
-        int mlen;
-        if (index == (offsets.length - 1)) {
-            mlen = path.length - mbegin;
-        } else {
-            mlen = offsets[index + 1] - mbegin - 1;
-        }
-        int obegin = other.offsets[index];
-        int olen;
-        if (index == (other.offsets.length - 1)) {
-            olen = other.path.length - obegin;
-        } else {
-            olen = other.offsets[index + 1] - obegin - 1;
-        }
-        if (mlen != olen) {
-            return false;
-        }
-        int n = 0;
-        while (n < mlen) {
-            if (path[mbegin + n] != other.path[obegin + n]) {
-                return false;
-            }
-            n++;
-        }
-        return true;
-    }
-
-    @Override
-    public final AbstractJrtPath relativize(Path other) {
-        final AbstractJrtPath o = checkPath(other);
-        if (o.equals(this)) {
-            return newJrtPath(new byte[0], true);
-        }
-        if (/* this.getFileSystem() != o.getFileSystem() || */this.isAbsolute() != o.isAbsolute()) {
-            throw new IllegalArgumentException();
-        }
-        int mc = this.getNameCount();
-        int oc = o.getNameCount();
-        int n = Math.min(mc, oc);
-        int i = 0;
-        while (i < n) {
-            if (!equalsNameAt(o, i)) {
-                break;
-            }
-            i++;
-        }
-        int dotdots = mc - i;
-        int len = dotdots * 3 - 1;
-        if (i < oc) {
-            len += (o.path.length - o.offsets[i] + 1);
-        }
-        byte[] result = new byte[len];
-
-        int pos = 0;
-        while (dotdots > 0) {
-            result[pos++] = (byte) '.';
-            result[pos++] = (byte) '.';
-            if (pos < len) // no tailing slash at the end
-            {
-                result[pos++] = (byte) '/';
-            }
-            dotdots--;
-        }
-        if (i < oc) {
-            System.arraycopy(o.path, o.offsets[i],
-                    result, pos,
-                    o.path.length - o.offsets[i]);
-        }
-        return newJrtPath(result);
-    }
-
-    @Override
-    public AbstractJrtFileSystem getFileSystem() {
-        return jrtfs;
-    }
-
-    @Override
-    public final boolean isAbsolute() {
-        return (this.path.length > 0 && path[0] == '/');
-    }
-
-    @Override
-    public final AbstractJrtPath resolve(Path other) {
-        final AbstractJrtPath o = checkPath(other);
-        if (o.isAbsolute()) {
-            return o;
-        }
-        byte[] res;
-        if (this.path[path.length - 1] == '/') {
-            res = new byte[path.length + o.path.length];
-            System.arraycopy(path, 0, res, 0, path.length);
-            System.arraycopy(o.path, 0, res, path.length, o.path.length);
-        } else {
-            res = new byte[path.length + 1 + o.path.length];
-            System.arraycopy(path, 0, res, 0, path.length);
-            res[path.length] = '/';
-            System.arraycopy(o.path, 0, res, path.length + 1, o.path.length);
-        }
-        return newJrtPath(res);
-    }
-
-    @Override
-    public final Path resolveSibling(Path other) {
-        if (other == null) {
-            throw new NullPointerException();
-        }
-        Path parent = getParent();
-        return (parent == null) ? other : parent.resolve(other);
-    }
-
-    @Override
-    public final boolean startsWith(Path other) {
-        final AbstractJrtPath o = checkPath(other);
-        if (o.isAbsolute() != this.isAbsolute()
-                || o.path.length > this.path.length) {
-            return false;
-        }
-        int olast = o.path.length;
-        for (int i = 0; i < olast; i++) {
-            if (o.path[i] != this.path[i]) {
-                return false;
-            }
-        }
-        olast--;
-        return o.path.length == this.path.length
-                || o.path[olast] == '/'
-                || this.path[olast + 1] == '/';
-    }
-
-    @Override
-    public final boolean endsWith(Path other) {
-        final AbstractJrtPath o = checkPath(other);
-        int olast = o.path.length - 1;
-        if (olast > 0 && o.path[olast] == '/') {
-            olast--;
-        }
-        int last = this.path.length - 1;
-        if (last > 0 && this.path[last] == '/') {
-            last--;
-        }
-        if (olast == -1) // o.path.length == 0
-        {
-            return last == -1;
-        }
-        if ((o.isAbsolute() && (!this.isAbsolute() || olast != last))
-                || (last < olast)) {
-            return false;
-        }
-        for (; olast >= 0; olast--, last--) {
-            if (o.path[olast] != this.path[last]) {
-                return false;
-            }
-        }
-        return o.path[olast + 1] == '/'
-                || last == -1 || this.path[last] == '/';
-    }
-
-    @Override
-    public final AbstractJrtPath resolve(String other) {
-        return resolve(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final Path resolveSibling(String other) {
-        return resolveSibling(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final boolean startsWith(String other) {
-        return startsWith(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final boolean endsWith(String other) {
-        return endsWith(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final AbstractJrtPath normalize() {
-        byte[] res = getResolved();
-        if (res == path) // no change
-        {
-            return this;
-        }
-        return newJrtPath(res, true);
-    }
-
-    private AbstractJrtPath checkPath(Path path) {
-        if (path == null) {
-            throw new NullPointerException();
-        }
-        if (!(path instanceof AbstractJrtPath)) {
-            throw new ProviderMismatchException();
-        }
-        return (AbstractJrtPath) path;
-    }
-
-    // create offset list if not already created
-    private void initOffsets() {
-        if (offsets == null) {
-            int count, index;
-            // count names
-            count = 0;
-            index = 0;
-            while (index < path.length) {
-                byte c = path[index++];
-                if (c != '/') {
-                    count++;
-                    while (index < path.length && path[index] != '/') {
-                        index++;
-                    }
-                }
-            }
-            // populate offsets
-            int[] result = new int[count];
-            count = 0;
-            index = 0;
-            while (index < path.length) {
-                byte c = path[index];
-                if (c == '/') {
-                    index++;
-                } else {
-                    result[count++] = index++;
-                    while (index < path.length && path[index] != '/') {
-                        index++;
-                    }
-                }
-            }
-            synchronized (this) {
-                if (offsets == null) {
-                    offsets = result;
-                }
-            }
-        }
-    }
-
-    private volatile byte[] resolved;
-
-    final byte[] getResolvedPath() {
-        byte[] r = resolved;
-        if (r == null) {
-            if (isAbsolute()) {
-                r = getResolved();
-            } else {
-                r = toAbsolutePath().getResolvedPath();
-            }
-            resolved = r;
-        }
-        return resolved;
-    }
-
-    // removes redundant slashs, replace "\" to separator "/"
-    // and check for invalid characters
-    private static byte[] normalize(byte[] path) {
-        if (path.length == 0) {
-            return path;
-        }
-        byte prevC = 0;
-        for (int i = 0; i < path.length; i++) {
-            byte c = path[i];
-            if (c == '\\') {
-                return normalize(path, i);
-            }
-            if (c == (byte) '/' && prevC == '/') {
-                return normalize(path, i - 1);
-            }
-            if (c == '\u0000') {
-                throw new InvalidPathException(JrtFileSystem.getString(path),
-                        "Path: nul character not allowed");
-            }
-            prevC = c;
-        }
-
-        if (path.length > 1 && path[path.length - 1] == '/') {
-            return Arrays.copyOf(path, path.length - 1);
-        }
-
-        return path;
-    }
-
-    private static byte[] normalize(byte[] path, int off) {
-        byte[] to = new byte[path.length];
-        int n = 0;
-        while (n < off) {
-            to[n] = path[n];
-            n++;
-        }
-        int m = n;
-        byte prevC = 0;
-        while (n < path.length) {
-            byte c = path[n++];
-            if (c == (byte) '\\') {
-                c = (byte) '/';
-            }
-            if (c == (byte) '/' && prevC == (byte) '/') {
-                continue;
-            }
-            if (c == '\u0000') {
-                throw new InvalidPathException(JrtFileSystem.getString(path),
-                        "Path: nul character not allowed");
-            }
-            to[m++] = c;
-            prevC = c;
-        }
-        if (m > 1 && to[m - 1] == '/') {
-            m--;
-        }
-        return (m == to.length) ? to : Arrays.copyOf(to, m);
-    }
-
-    // Remove DotSlash(./) and resolve DotDot (..) components
-    private byte[] getResolved() {
-        if (path.length == 0) {
-            return path;
-        }
-        for (int i = 0; i < path.length; i++) {
-            byte c = path[i];
-            if (c == (byte) '.') {
-                return resolve0();
-            }
-        }
-
-        return path;
-    }
-
-    // TBD: performance, avoid initOffsets
-    private byte[] resolve0() {
-        byte[] to = new byte[path.length];
-        int nc = getNameCount();
-        int[] lastM = new int[nc];
-        int lastMOff = -1;
-        int m = 0;
-        for (int i = 0; i < nc; i++) {
-            int n = offsets[i];
-            int len = (i == offsets.length - 1)
-                    ? (path.length - n) : (offsets[i + 1] - n - 1);
-            if (len == 1 && path[n] == (byte) '.') {
-                if (m == 0 && path[0] == '/') // absolute path
-                {
-                    to[m++] = '/';
-                }
-                continue;
-            }
-            if (len == 2 && path[n] == '.' && path[n + 1] == '.') {
-                if (lastMOff >= 0) {
-                    m = lastM[lastMOff--];  // retreat
-                    continue;
-                }
-                if (path[0] == '/') {  // "/../xyz" skip
-                    if (m == 0) {
-                        to[m++] = '/';
-                    }
-                } else {               // "../xyz" -> "../xyz"
-                    if (m != 0 && to[m - 1] != '/') {
-                        to[m++] = '/';
-                    }
-                    while (len-- > 0) {
-                        to[m++] = path[n++];
-                    }
-                }
-                continue;
-            }
-            if (m == 0 && path[0] == '/' || // absolute path
-                    m != 0 && to[m - 1] != '/') {   // not the first name
-                to[m++] = '/';
-            }
-            lastM[++lastMOff] = m;
-            while (len-- > 0) {
-                to[m++] = path[n++];
-            }
-        }
-        if (m > 1 && to[m - 1] == '/') {
-            m--;
-        }
-        return (m == to.length) ? to : Arrays.copyOf(to, m);
-    }
-
-    @Override
-    public final String toString() {
-        return JrtFileSystem.getString(path);
-    }
-
-    @Override
-    public final int hashCode() {
-        int h = hashcode;
-        if (h == 0) {
-            hashcode = h = Arrays.hashCode(path);
-        }
-        return h;
-    }
-
-    @Override
-    public final boolean equals(Object obj) {
-        return obj != null
-                && obj instanceof AbstractJrtPath
-                && this.jrtfs == ((AbstractJrtPath) obj).jrtfs
-                && compareTo((Path) obj) == 0;
-    }
-
-    @Override
-    public final int compareTo(Path other) {
-        final AbstractJrtPath o = checkPath(other);
-        int len1 = this.path.length;
-        int len2 = o.path.length;
-
-        int n = Math.min(len1, len2);
-        byte v1[] = this.path;
-        byte v2[] = o.path;
-
-        int k = 0;
-        while (k < n) {
-            int c1 = v1[k] & 0xff;
-            int c2 = v2[k] & 0xff;
-            if (c1 != c2) {
-                return c1 - c2;
-            }
-            k++;
-        }
-        return len1 - len2;
-    }
-
-    @Override
-    public final WatchKey register(
-            WatchService watcher,
-            WatchEvent.Kind<?>[] events,
-            WatchEvent.Modifier... modifiers) {
-        if (watcher == null || events == null || modifiers == null) {
-            throw new NullPointerException();
-        }
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public final WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) {
-        return register(watcher, events, new WatchEvent.Modifier[0]);
-    }
-
-    @Override
-    public final File toFile() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public final Iterator<Path> iterator() {
-        return new Iterator<Path>() {
-            private int i = 0;
-
-            @Override
-            public boolean hasNext() {
-                return (i < getNameCount());
-            }
-
-            @Override
-            public Path next() {
-                if (i < getNameCount()) {
-                    Path result = getName(i);
-                    i++;
-                    return result;
-                } else {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            @Override
-            public void remove() {
-                throw new ReadOnlyFileSystemException();
-            }
-        };
-    }
-
-    /////////////////////////////////////////////////////////////////////
-    // Helpers for JrtFileSystemProvider and JrtFileSystem
-    final int getPathLength() {
-        return path.length;
-    }
-
-    final void createDirectory(FileAttribute<?>... attrs)
-            throws IOException {
-        jrtfs.createDirectory(this, attrs);
-    }
-
-    final InputStream newInputStream(OpenOption... options) throws IOException {
-        if (options.length > 0) {
-            for (OpenOption opt : options) {
-                if (opt != READ) {
-                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
-                }
-            }
-        }
-        return jrtfs.newInputStream(this);
-    }
-
-    final DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
-            throws IOException {
-        return new JrtDirectoryStream(this, filter);
-    }
-
-    final void delete() throws IOException {
-        jrtfs.deleteFile(this, true);
-    }
-
-    final void deleteIfExists() throws IOException {
-        jrtfs.deleteFile(this, false);
-    }
-
-    final AbstractJrtFileAttributes getAttributes(LinkOption... options) throws IOException {
-        AbstractJrtFileAttributes zfas = jrtfs.getFileAttributes(this, options);
-        if (zfas == null) {
-            throw new NoSuchFileException(toString());
-        }
-        return zfas;
-    }
-
-    final void setAttribute(String attribute, Object value, LinkOption... options)
-            throws IOException {
-        String type;
-        String attr;
-        int colonPos = attribute.indexOf(':');
-        if (colonPos == -1) {
-            type = "basic";
-            attr = attribute;
-        } else {
-            type = attribute.substring(0, colonPos++);
-            attr = attribute.substring(colonPos);
-        }
-        JrtFileAttributeView view = JrtFileAttributeView.get(this, type, options);
-        if (view == null) {
-            throw new UnsupportedOperationException("view <" + view + "> is not supported");
-        }
-        view.setAttribute(attr, value);
-    }
-
-    final void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
-            throws IOException {
-        jrtfs.setTimes(this, mtime, atime, ctime);
-    }
-
-    final Map<String, Object> readAttributes(String attributes, LinkOption... options)
-            throws IOException {
-        String view;
-        String attrs;
-        int colonPos = attributes.indexOf(':');
-        if (colonPos == -1) {
-            view = "basic";
-            attrs = attributes;
-        } else {
-            view = attributes.substring(0, colonPos++);
-            attrs = attributes.substring(colonPos);
-        }
-        JrtFileAttributeView jrtfv = JrtFileAttributeView.get(this, view, options);
-        if (jrtfv == null) {
-            throw new UnsupportedOperationException("view not supported");
-        }
-        return jrtfv.readAttributes(attrs);
-    }
-
-    final FileStore getFileStore() throws IOException {
-        // each JrtFileSystem only has one root (as requested for now)
-        if (exists()) {
-            return jrtfs.getFileStore(this);
-        }
-        throw new NoSuchFileException(JrtFileSystem.getString(path));
-    }
-
-    final boolean isSameFile(Path other) throws IOException {
-        if (this.equals(other)) {
-            return true;
-        }
-        if (other == null
-                || this.getFileSystem() != other.getFileSystem()) {
-            return false;
-        }
-        this.checkAccess();
-        AbstractJrtPath target = (AbstractJrtPath) other;
-        target.checkAccess();
-        return Arrays.equals(this.getResolvedPath(), target.getResolvedPath())
-                || jrtfs.isSameFile(this, target);
-    }
-
-    final SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
-            FileAttribute<?>... attrs)
-            throws IOException {
-        return jrtfs.newByteChannel(this, options, attrs);
-    }
-
-    final FileChannel newFileChannel(Set<? extends OpenOption> options,
-            FileAttribute<?>... attrs)
-            throws IOException {
-        return jrtfs.newFileChannel(this, options, attrs);
-    }
-
-    final void checkAccess(AccessMode... modes) throws IOException {
-        boolean w = false;
-        boolean x = false;
-        for (AccessMode mode : modes) {
-            switch (mode) {
-                case READ:
-                    break;
-                case WRITE:
-                    w = true;
-                    break;
-                case EXECUTE:
-                    x = true;
-                    break;
-                default:
-                    throw new UnsupportedOperationException();
-            }
-        }
-
-        BasicFileAttributes attrs = jrtfs.getFileAttributes(this);
-        if (attrs == null && (path.length != 1 || path[0] != '/')) {
-            throw new NoSuchFileException(toString());
-        }
-        if (w) {
-//            if (jrtfs.isReadOnly())
-            throw new AccessDeniedException(toString());
-        }
-        if (x) {
-            throw new AccessDeniedException(toString());
-        }
-    }
-
-    final boolean exists() {
-        try {
-            return jrtfs.exists(this);
-        } catch (IOException x) {
-        }
-        return false;
-    }
-
-    final OutputStream newOutputStream(OpenOption... options) throws IOException {
-        if (options.length == 0) {
-            return jrtfs.newOutputStream(this,
-                    CREATE_NEW, WRITE);
-        }
-        return jrtfs.newOutputStream(this, options);
-    }
-
-    final void move(AbstractJrtPath target, CopyOption... options)
-            throws IOException {
-        if (this.jrtfs == target.jrtfs) {
-            jrtfs.copyFile(true,
-                    this, target,
-                    options);
-        } else {
-            copyToTarget(target, options);
-            delete();
-        }
-    }
-
-    final void copy(AbstractJrtPath target, CopyOption... options)
-            throws IOException {
-        if (this.jrtfs == target.jrtfs) {
-            jrtfs.copyFile(false,
-                    this, target,
-                    options);
-        } else {
-            copyToTarget(target, options);
-        }
-    }
-
-    private void copyToTarget(AbstractJrtPath target, CopyOption... options)
-            throws IOException {
-        boolean replaceExisting = false;
-        boolean copyAttrs = false;
-        for (CopyOption opt : options) {
-            if (opt == REPLACE_EXISTING) {
-                replaceExisting = true;
-            } else if (opt == COPY_ATTRIBUTES) {
-                copyAttrs = true;
-            }
-        }
-        // attributes of source file
-        BasicFileAttributes jrtfas = getAttributes();
-        // check if target exists
-        boolean exists;
-        if (replaceExisting) {
-            try {
-                target.deleteIfExists();
-                exists = false;
-            } catch (DirectoryNotEmptyException x) {
-                exists = true;
-            }
-        } else {
-            exists = target.exists();
-        }
-        if (exists) {
-            throw new FileAlreadyExistsException(target.toString());
-        }
-
-        if (jrtfas.isDirectory()) {
-            // create directory or file
-            target.createDirectory();
-        } else {
-            try (InputStream is = jrtfs.newInputStream(this); OutputStream os = target.newOutputStream()) {
-                byte[] buf = new byte[8192];
-                int n;
-                while ((n = is.read(buf)) != -1) {
-                    os.write(buf, 0, n);
-                }
-            }
-        }
-        if (copyAttrs) {
-            BasicFileAttributeView view
-                    = JrtFileAttributeView.get(target, BasicFileAttributeView.class);
-            try {
-                view.setTimes(jrtfas.lastModifiedTime(),
-                        jrtfas.lastAccessTime(),
-                        jrtfas.creationTime());
-            } catch (IOException x) {
-                // rollback?
-                try {
-                    target.delete();
-                } catch (IOException ignore) {
-                }
-                throw x;
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/ExplodedImage.java	Fri Apr 22 01:04:01 2016 -0700
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.internal.jimage.ImageReader.Node;
+
+/**
+ * A jrt file system built on $JAVA_HOME/modules directory ('exploded modules
+ * build')
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+class ExplodedImage extends SystemImage {
+
+    private static final String MODULES = "/modules/";
+    private static final String PACKAGES = "/packages/";
+    private static final int PACKAGES_LEN = PACKAGES.length();
+
+    private final FileSystem defaultFS;
+    private final String separator;
+    private final Map<String, PathNode> nodes = Collections.synchronizedMap(new HashMap<>());
+    private final BasicFileAttributes modulesDirAttrs;
+
+    ExplodedImage(Path modulesDir) throws IOException {
+        defaultFS = FileSystems.getDefault();
+        String str = defaultFS.getSeparator();
+        separator = str.equals("/") ? null : str;
+        modulesDirAttrs = Files.readAttributes(modulesDir, BasicFileAttributes.class);
+        initNodes();
+    }
+
+    // A Node that is backed by actual default file system Path
+    private final class PathNode extends Node {
+
+        // Path in underlying default file system
+        private Path path;
+        private PathNode link;
+        private List<Node> children;
+
+        PathNode(String name, Path path, BasicFileAttributes attrs) {  // path
+            super(name, attrs);
+            this.path = path;
+        }
+
+        PathNode(String name, Node link) {              // link
+            super(name, link.getFileAttributes());
+            this.link = (PathNode)link;
+        }
+
+        PathNode(String name, List<Node> children) {    // dir
+            super(name, modulesDirAttrs);
+            this.children = children;
+        }
+
+        @Override
+        public boolean isDirectory() {
+            return children != null ||
+                   (link == null && getFileAttributes().isDirectory());
+        }
+
+        @Override
+        public boolean isLink() {
+            return link != null;
+        }
+
+        @Override
+        public PathNode resolveLink(boolean recursive) {
+            if (link == null)
+                return this;
+            return recursive && link.isLink() ? link.resolveLink(true) : link;
+        }
+
+        byte[] getContent() throws IOException {
+            if (!getFileAttributes().isRegularFile())
+                throw new FileSystemException(getName() + " is not file");
+            return Files.readAllBytes(path);
+        }
+
+        @Override
+        public List<Node> getChildren() {
+            if (!isDirectory())
+                throw new IllegalArgumentException("not a directory: " + getNameString());
+            if (children == null) {
+                List<Node> list = new ArrayList<>();
+                try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
+                    for (Path p : stream) {
+                        p = explodedModulesDir.relativize(p);
+                        String pName = MODULES + nativeSlashToFrontSlash(p.toString());
+                        Node node = findNode(pName);
+                        if (node != null) {  // findNode may choose to hide certain files!
+                            list.add(node);
+                        }
+                    }
+                } catch (IOException x) {
+                    return null;
+                }
+                children = list;
+            }
+            return children;
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        nodes.clear();
+    }
+
+    @Override
+    public byte[] getResource(Node node) throws IOException {
+        return ((PathNode)node).getContent();
+    }
+
+    // find Node for the given Path
+    @Override
+    public synchronized Node findNode(String str) {
+        Node node = findModulesNode(str);
+        if (node != null) {
+            return node;
+        }
+        // lazily created for paths like /packages/<package>/<module>/xyz
+        // For example /packages/java.lang/java.base/java/lang/
+        if (str.startsWith(PACKAGES)) {
+            // pkgEndIdx marks end of <package> part
+            int pkgEndIdx = str.indexOf('/', PACKAGES_LEN);
+            if (pkgEndIdx != -1) {
+                // modEndIdx marks end of <module> part
+                int modEndIdx = str.indexOf('/', pkgEndIdx + 1);
+                if (modEndIdx != -1) {
+                    // make sure we have such module link!
+                    // ie., /packages/<package>/<module> is valid
+                    Node linkNode = nodes.get(str.substring(0, modEndIdx));
+                    if (linkNode == null || !linkNode.isLink()) {
+                        return null;
+                    }
+                    // map to "/modules/zyz" path and return that node
+                    // For example, "/modules/java.base/java/lang" for
+                    // "/packages/java.lang/java.base/java/lang".
+                    String mod = MODULES + str.substring(pkgEndIdx + 1);
+                    return findModulesNode(mod);
+                }
+            }
+        }
+        return null;
+    }
+
+    // find a Node for a path that starts like "/modules/..."
+    Node findModulesNode(String str) {
+        PathNode node = nodes.get(str);
+        if (node != null) {
+            return node;
+        }
+        // lazily created "/modules/xyz/abc/" Node
+        // This is mapped to default file system path "<JDK_MODULES_DIR>/xyz/abc"
+        Path p = underlyingPath(str);
+        if (p != null) {
+            try {
+                BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class);
+                if (attrs.isRegularFile()) {
+                    Path f = p.getFileName();
+                    if (f.toString().startsWith("_the."))
+                        return null;
+                }
+                node = new PathNode(str, p, attrs);
+                nodes.put(str, node);
+                return node;
+            } catch (IOException x) {
+                // does not exists or unable to determine
+            }
+        }
+        return null;
+    }
+
+    Path underlyingPath(String str) {
+        if (str.startsWith(MODULES)) {
+            str = frontSlashToNativeSlash(str.substring("/modules".length()));
+            return defaultFS.getPath(explodedModulesDir.toString(), str);
+        }
+        return null;
+    }
+
+    // convert "/" to platform path separator
+    private String frontSlashToNativeSlash(String str) {
+        return separator == null ? str : str.replace("/", separator);
+    }
+
+    // convert platform path separator to "/"
+    private String nativeSlashToFrontSlash(String str) {
+        return separator == null ? str : str.replace(separator, "/");
+    }
+
+    // convert "/"s to "."s
+    private String slashesToDots(String str) {
+        return str.replace(separator != null ? separator : "/", ".");
+    }
+
+    // initialize file system Nodes
+    private void initNodes() throws IOException {
+        // same package prefix may exist in mutliple modules. This Map
+        // is filled by walking "jdk modules" directory recursively!
+        Map<String, List<String>> packageToModules = new HashMap<>();
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(explodedModulesDir)) {
+            for (Path module : stream) {
+                if (Files.isDirectory(module)) {
+                    String moduleName = module.getFileName().toString();
+                    // make sure "/modules/<moduleName>" is created
+                    findModulesNode(MODULES + moduleName);
+                    Files.walk(module).filter(Files::isDirectory).forEach((p) -> {
+                        p = module.relativize(p);
+                        String pkgName = slashesToDots(p.toString());
+                        // skip META-INFO and empty strings
+                        if (!pkgName.isEmpty() && !pkgName.startsWith("META-INF")) {
+                            List<String> moduleNames = packageToModules.get(pkgName);
+                            if (moduleNames == null) {
+                                moduleNames = new ArrayList<>();
+                                packageToModules.put(pkgName, moduleNames);
+                            }
+                            moduleNames.add(moduleName);
+                        }
+                    });
+                }
+            }
+        }
+        // create "/modules" directory
+        // "nodes" map contains only /modules/<foo> nodes only so far and so add all as children of /modules
+        PathNode modulesDir = new PathNode("/modules", new ArrayList<>(nodes.values()));
+        nodes.put(modulesDir.getName(), modulesDir);
+
+        // create children under "/packages"
+        List<Node> packagesChildren = new ArrayList<>(packageToModules.size());
+        for (Map.Entry<String, List<String>> entry : packageToModules.entrySet()) {
+            String pkgName = entry.getKey();
+            List<String> moduleNameList = entry.getValue();
+            List<Node> moduleLinkNodes = new ArrayList<>(moduleNameList.size());
+            for (String moduleName : moduleNameList) {
+                Node moduleNode = findModulesNode(MODULES + moduleName);
+                PathNode linkNode = new PathNode(PACKAGES + pkgName + "/" + moduleName, moduleNode);
+                nodes.put(linkNode.getName(), linkNode);
+                moduleLinkNodes.add(linkNode);
+            }
+            PathNode pkgDir = new PathNode(PACKAGES + pkgName, moduleLinkNodes);
+            nodes.put(pkgDir.getName(), pkgDir);
+            packagesChildren.add(pkgDir);
+        }
+        // "/packages" dir
+        PathNode packagesDir = new PathNode("/packages", packagesChildren);
+        nodes.put(packagesDir.getName(), packagesDir);
+
+        // finally "/" dir!
+        List<Node> rootChildren = new ArrayList<>();
+        rootChildren.add(packagesDir);
+        rootChildren.add(modulesDir);
+        PathNode root = new PathNode("/", rootChildren);
+        nodes.put(root.getName(), root);
+    }
+}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java	Fri Apr 22 01:04:01 2016 -0700
@@ -30,6 +30,7 @@
 import java.nio.file.NotDirectoryException;
 import java.nio.file.Path;
 import java.util.Iterator;
+import java.util.Objects;
 import java.util.NoSuchElementException;
 import java.io.IOException;
 
@@ -44,115 +45,47 @@
  */
 final class JrtDirectoryStream implements DirectoryStream<Path> {
 
-    private final AbstractJrtFileSystem jrtfs;
-    private final AbstractJrtPath dir;
+    private final JrtPath dir;
     private final DirectoryStream.Filter<? super Path> filter;
     private volatile boolean isClosed;
     private volatile Iterator<Path> itr;
 
-    JrtDirectoryStream(AbstractJrtPath jrtPath,
+    JrtDirectoryStream(JrtPath dir,
             DirectoryStream.Filter<? super java.nio.file.Path> filter)
-            throws IOException {
-        this.jrtfs = jrtPath.getFileSystem();
-        this.dir = jrtPath;
-        // sanity check
-        if (!jrtfs.isDirectory(dir, true)) {
-            throw new NotDirectoryException(jrtPath.toString());
+            throws IOException
+    {
+        this.dir = dir;
+        if (!dir.jrtfs.isDirectory(dir, true)) {  // sanity check
+            throw new NotDirectoryException(dir.toString());
         }
-
         this.filter = filter;
     }
 
     @Override
     public synchronized Iterator<Path> iterator() {
-        if (isClosed) {
+        if (isClosed)
             throw new ClosedDirectoryStreamException();
-        }
-        if (itr != null) {
+        if (itr != null)
             throw new IllegalStateException("Iterator has already been returned");
-        }
-
         try {
-            itr = jrtfs.iteratorOf(dir);
+            itr = dir.jrtfs.iteratorOf(dir, filter);
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
         return new Iterator<Path>() {
-            /*
-             * next Path value to return from this iterator.
-             * null value means hasNext() not called yet
-             * or last hasNext() returned false or resulted
-             * in exception. If last hasNext() returned true,
-             * then this field has non-null value.
-             */
             private Path next;
-
-            // get-and-clear and set-next by these methods
-            private Path getAndClearNext() {
-                assert next != null;
-                Path result = this.next;
-                this.next = null;
-                return result;
-            }
-
-            private void setNext(Path path) {
-                assert path != null;
-                this.next = path;
-            }
-
-            // if hasNext() returns true, 'next' field has non-null Path
             @Override
             public synchronized boolean hasNext() {
-                if (next != null) {
-                    return true;
-                }
-
-                if (isClosed) {
+                if (isClosed)
                     return false;
-                }
-
-                if (filter == null) {
-                    if (itr.hasNext()) {
-                        setNext(itr.next());
-                        return true;
-                    } else {
-                        return false;
-                    }
-                } else {
-                    while (itr.hasNext()) {
-                        Path tmpPath = itr.next();
-                        try {
-                            if (filter.accept(tmpPath)) {
-                                setNext(tmpPath);
-                                return true;
-                            }
-                        } catch (IOException ioe) {
-                            throw new DirectoryIteratorException(ioe);
-                        }
-                    }
-
-                    return false;
-                }
+                return itr.hasNext();
             }
 
             @Override
             public synchronized Path next() {
-                if (next != null) {
-                    return getAndClearNext();
-                }
-
-                if (isClosed) {
+                if (isClosed)
                     throw new NoSuchElementException();
-                }
-
-                if (next == null && itr.hasNext()) {
-                    // missing hasNext() between next() calls.
-                    if (hasNext()) {
-                        return getAndClearNext();
-                    }
-                }
-
-                throw new NoSuchElementException();
+                return itr.next();
             }
 
             @Override
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileAttributes.java	Thu Apr 21 15:04:00 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jrtfs;
-
-import java.io.IOException;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.FileTime;
-import jdk.internal.jrtfs.JrtExplodedFileSystem.Node;
-
-/**
- * jrt file system attributes implementation on top of 'exploded file system'
- * Node.
- *
- * @implNote This class needs to maintain JDK 8 source compatibility.
- *
- * It is used internally in the JDK to implement jimage/jrtfs access,
- * but also compiled and delivered as part of the jrtfs.jar to support access
- * to the jimage file provided by the shipped JDK by tools running on JDK 8.
- */
-final class JrtExplodedFileAttributes extends AbstractJrtFileAttributes {
-
-    private final Node node;
-    private final BasicFileAttributes attrs;
-
-    JrtExplodedFileAttributes(Node node) throws IOException {
-        this.node = node;
-        this.attrs = node.getBasicAttrs();
-    }
-
-    @Override
-    public FileTime creationTime() {
-        return attrs.creationTime();
-    }
-
-    @Override
-    public boolean isDirectory() {
-        return node.isDirectory();
-    }
-
-    @Override
-    public boolean isOther() {
-        return false;
-    }
-
-    @Override
-    public boolean isRegularFile() {
-        return node.isFile();
-    }
-
-    @Override
-    public FileTime lastAccessTime() {
-        return attrs.lastAccessTime();
-    }
-
-    @Override
-    public FileTime lastModifiedTime() {
-        return attrs.lastModifiedTime();
-    }
-
-    @Override
-    public long size() {
-        return isRegularFile() ? attrs.size() : 0L;
-    }
-
-    @Override
-    public boolean isSymbolicLink() {
-        return node.isLink();
-    }
-
-    @Override
-    public Object fileKey() {
-        return node.resolveLink(true);
-    }
-
-    @Override
-    public long compressedSize() {
-        return 0L;
-    }
-
-    @Override
-    public String extension() {
-        return node.getExtension();
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java	Thu Apr 21 15:04:00 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,528 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jrtfs;
-
-import java.io.IOException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystemException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.NotDirectoryException;
-import java.nio.file.Path;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import static java.util.stream.Collectors.toList;
-import static jdk.internal.jrtfs.AbstractJrtFileSystem.getString;
-
-/**
- * A jrt file system built on $JAVA_HOME/modules directory ('exploded modules
- * build')
- *
- * @implNote This class needs to maintain JDK 8 source compatibility.
- *
- * It is used internally in the JDK to implement jimage/jrtfs access,
- * but also compiled and delivered as part of the jrtfs.jar to support access
- * to the jimage file provided by the shipped JDK by tools running on JDK 8.
- */
-class JrtExplodedFileSystem extends AbstractJrtFileSystem {
-
-    private static final String MODULES = "/modules/";
-    private static final String PACKAGES = "/packages/";
-    private static final int PACKAGES_LEN = PACKAGES.length();
-
-    // root path
-    private final JrtExplodedPath rootPath;
-    private volatile boolean isOpen;
-    private final FileSystem defaultFS;
-    private final String separator;
-    private final Map<String, Node> nodes = Collections.synchronizedMap(new HashMap<>());
-    private final BasicFileAttributes modulesDirAttrs;
-
-    JrtExplodedFileSystem(JrtFileSystemProvider provider,
-            Map<String, ?> env)
-            throws IOException {
-
-        super(provider, env);
-        checkExists(SystemImages.explodedModulesDir());
-        byte[] root = new byte[]{'/'};
-        rootPath = new JrtExplodedPath(this, root);
-        isOpen = true;
-        defaultFS = FileSystems.getDefault();
-        String str = defaultFS.getSeparator();
-        separator = str.equals(getSeparator()) ? null : str;
-        modulesDirAttrs = Files.readAttributes(SystemImages.explodedModulesDir(), BasicFileAttributes.class);
-        initNodes();
-    }
-
-    @Override
-    public void close() throws IOException {
-        cleanup();
-    }
-
-    @Override
-    public boolean isOpen() {
-        return isOpen;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        cleanup();
-        super.finalize();
-    }
-
-    private synchronized void cleanup() {
-        isOpen = false;
-        nodes.clear();
-    }
-
-    @Override
-    JrtExplodedPath getRootPath() {
-        return rootPath;
-    }
-
-    // Base class for Nodes of this file system
-    abstract class Node {
-
-        private final String name;
-
-        Node(String name) {
-            this.name = name;
-        }
-
-        final String getName() {
-            return name;
-        }
-
-        final String getExtension() {
-            if (isFile()) {
-                final int index = name.lastIndexOf(".");
-                if (index != -1) {
-                    return name.substring(index + 1);
-                }
-            }
-
-            return null;
-        }
-
-        BasicFileAttributes getBasicAttrs() throws IOException {
-            return modulesDirAttrs;
-        }
-
-        boolean isLink() {
-            return false;
-        }
-
-        boolean isDirectory() {
-            return false;
-        }
-
-        boolean isFile() {
-            return false;
-        }
-
-        byte[] getContent() throws IOException {
-            if (!isFile()) {
-                throw new FileSystemException(name + " is not file");
-            }
-
-            throw new AssertionError("ShouldNotReachHere");
-        }
-
-        List<Node> getChildren() throws IOException {
-            if (!isDirectory()) {
-                throw new NotDirectoryException(name);
-            }
-
-            throw new AssertionError("ShouldNotReachHere");
-        }
-
-        final Node resolveLink() {
-            return resolveLink(false);
-        }
-
-        Node resolveLink(boolean recursive) {
-            return this;
-        }
-    }
-
-    // A Node that is backed by actual default file system Path
-    private final class PathNode extends Node {
-
-        // Path in underlying default file system
-        private final Path path;
-        private final boolean file;
-        // lazily initialized, don't read attributes unless required!
-        private BasicFileAttributes attrs;
-
-        PathNode(String name, Path path) {
-            super(name);
-            this.path = path;
-            this.file = Files.isRegularFile(path);
-        }
-
-        @Override
-        synchronized BasicFileAttributes getBasicAttrs() throws IOException {
-            if (attrs == null) {
-                attrs = Files.readAttributes(path, BasicFileAttributes.class);
-            }
-            return attrs;
-        }
-
-        @Override
-        boolean isDirectory() {
-            return !file;
-        }
-
-        @Override
-        boolean isFile() {
-            return file;
-        }
-
-        @Override
-        byte[] getContent() throws IOException {
-            if (!isFile()) {
-                throw new FileSystemException(getName() + " is not file");
-            }
-
-            return Files.readAllBytes(path);
-        }
-
-        @Override
-        List<Node> getChildren() throws IOException {
-            if (!isDirectory()) {
-                throw new NotDirectoryException(getName());
-            }
-
-            List<Node> children = new ArrayList<>();
-            try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
-                for (Path cp : stream) {
-                    cp = SystemImages.explodedModulesDir().relativize(cp);
-                    String cpName = MODULES + nativeSlashToFrontSlash(cp.toString());
-                    try {
-                        children.add(findNode(cpName));
-                    } catch (NoSuchFileException nsfe) {
-                        // findNode may choose to hide certain files!
-                    }
-                }
-            }
-
-            return children;
-        }
-    }
-
-    // A Node that links to another Node
-    private final class LinkNode extends Node {
-
-        // underlying linked Node
-        private final Node link;
-
-        LinkNode(String name, Node link) {
-            super(name);
-            this.link = link;
-        }
-
-        @Override
-        BasicFileAttributes getBasicAttrs() throws IOException {
-            return link.getBasicAttrs();
-        }
-
-        @Override
-        public boolean isLink() {
-            return true;
-        }
-
-        @Override
-        Node resolveLink(boolean recursive) {
-            return recursive && (link instanceof LinkNode) ? ((LinkNode) link).resolveLink(true) : link;
-        }
-    }
-
-    // A directory Node with it's children Nodes
-    private final class DirNode extends Node {
-
-        // children Nodes of this Node.
-        private final List<Node> children;
-
-        DirNode(String name, List<Node> children) {
-            super(name);
-            this.children = children;
-        }
-
-        @Override
-        boolean isDirectory() {
-            return true;
-        }
-
-        @Override
-        List<Node> getChildren() throws IOException {
-            return children;
-        }
-    }
-
-    private JrtExplodedPath toJrtExplodedPath(String path) {
-        return toJrtExplodedPath(getBytes(path));
-    }
-
-    private JrtExplodedPath toJrtExplodedPath(byte[] path) {
-        return new JrtExplodedPath(this, path);
-    }
-
-    @Override
-    boolean isSameFile(AbstractJrtPath jrtPath1, AbstractJrtPath jrtPath2) throws IOException {
-        Node n1 = checkNode(jrtPath1);
-        Node n2 = checkNode(jrtPath2);
-        return n1 == n2;
-    }
-
-    @Override
-    boolean isLink(AbstractJrtPath jrtPath) throws IOException {
-        return checkNode(jrtPath).isLink();
-    }
-
-    @Override
-    AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException {
-        String name = checkNode(jrtPath).resolveLink().getName();
-        return toJrtExplodedPath(name);
-    }
-
-    @Override
-    AbstractJrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException {
-        Node node = checkNode(jrtPath);
-        if (node.isLink() && followLinks(options)) {
-            node = node.resolveLink(true);
-        }
-        return new JrtExplodedFileAttributes(node);
-    }
-
-    @Override
-    boolean exists(AbstractJrtPath jrtPath) throws IOException {
-        try {
-            checkNode(jrtPath);
-            return true;
-        } catch (NoSuchFileException nsfe) {
-            return false;
-        }
-    }
-
-    @Override
-    boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException {
-        Node node = checkNode(jrtPath);
-        return resolveLinks && node.isLink()
-                ? node.resolveLink(true).isDirectory()
-                : node.isDirectory();
-    }
-
-    @Override
-    Iterator<Path> iteratorOf(AbstractJrtPath dir) throws IOException {
-        Node node = checkNode(dir).resolveLink(true);
-        if (!node.isDirectory()) {
-            throw new NotDirectoryException(getString(dir.getName()));
-        }
-
-        Function<Node, Path> nodeToPath =
-            child -> dir.resolve(
-                toJrtExplodedPath(child.getName()).
-                getFileName());
-
-        return node.getChildren().stream().
-                   map(nodeToPath).collect(toList()).
-                   iterator();
-    }
-
-    @Override
-    byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException {
-        return checkNode(jrtPath).getContent();
-    }
-
-    private Node checkNode(AbstractJrtPath jrtPath) throws IOException {
-        return checkNode(jrtPath.getResolvedPath());
-    }
-
-    private Node checkNode(byte[] path) throws IOException {
-        ensureOpen();
-        return findNode(path);
-    }
-
-    synchronized Node findNode(byte[] path) throws IOException {
-        return findNode(getString(path));
-    }
-
-    // find Node for the given Path
-    synchronized Node findNode(String str) throws IOException {
-        Node node = findModulesNode(str);
-        if (node != null) {
-            return node;
-        }
-
-        // lazily created for paths like /packages/<package>/<module>/xyz
-        // For example /packages/java.lang/java.base/java/lang/
-        if (str.startsWith(PACKAGES)) {
-            // pkgEndIdx marks end of <package> part
-            int pkgEndIdx = str.indexOf('/', PACKAGES_LEN);
-            if (pkgEndIdx != -1) {
-                // modEndIdx marks end of <module> part
-                int modEndIdx = str.indexOf('/', pkgEndIdx + 1);
-                if (modEndIdx != -1) {
-                    // make sure we have such module link!
-                    // ie., /packages/<package>/<module> is valid
-                    Node linkNode = nodes.get(str.substring(0, modEndIdx));
-                    if (linkNode == null || !linkNode.isLink()) {
-                        throw new NoSuchFileException(str);
-                    }
-
-                    // map to "/modules/zyz" path and return that node
-                    // For example, "/modules/java.base/java/lang" for
-                    // "/packages/java.lang/java.base/java/lang".
-                    String mod = MODULES + str.substring(pkgEndIdx + 1);
-                    return findNode(mod);
-                }
-            }
-        }
-
-        throw new NoSuchFileException(str);
-    }
-
-    // find a Node for a path that starts like "/modules/..."
-    synchronized Node findModulesNode(String str) throws IOException {
-        Node node = nodes.get(str);
-        if (node != null) {
-            return node;
-        }
-
-        // lazily created "/modules/xyz/abc/" Node
-        // This is mapped to default file system path "<JDK_MODULES_DIR>/xyz/abc"
-        Path p = underlyingPath(str);
-        if (p != null) {
-            if (Files.isRegularFile(p)) {
-                Path file = p.getFileName();
-                if (file.toString().startsWith("_the.")) {
-                    return null;
-                }
-            }
-            node = new PathNode(str, p);
-            nodes.put(str, node);
-            return node;
-        }
-
-        return null;
-    }
-
-    Path underlyingPath(String str) {
-        if (str.startsWith(MODULES)) {
-            str = frontSlashToNativeSlash(str.substring("/modules".length()));
-            return defaultFS.getPath(SystemImages.explodedModulesDir().toString(), str);
-        }
-        return null;
-    }
-
-    // convert "/" to platform path separator
-    private String frontSlashToNativeSlash(String str) {
-        return separator == null ? str : str.replace("/", separator);
-    }
-
-    // convert platform path separator to "/"
-    private String nativeSlashToFrontSlash(String str) {
-        return separator == null ? str : str.replace(separator, "/");
-    }
-
-    // convert "/"s to "."s
-    private String slashesToDots(String str) {
-        return str.replace(separator != null ? separator : "/", ".");
-    }
-
-    // initialize file system Nodes
-    private void initNodes() throws IOException {
-        // same package prefix may exist in mutliple modules. This Map
-        // is filled by walking "jdk modules" directory recursively!
-        Map<String, List<String>> packageToModules = new HashMap<>();
-
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(SystemImages.explodedModulesDir())) {
-            for (Path module : stream) {
-                if (Files.isDirectory(module)) {
-                    String moduleName = module.getFileName().toString();
-                    // make sure "/modules/<moduleName>" is created
-                    findModulesNode(MODULES + moduleName);
-
-                    Files.walk(module).filter(Files::isDirectory).forEach((p) -> {
-                        p = module.relativize(p);
-                        String pkgName = slashesToDots(p.toString());
-                        // skip META-INFO and empty strings
-                        if (!pkgName.isEmpty() && !pkgName.startsWith("META-INF")) {
-                            List<String> moduleNames = packageToModules.get(pkgName);
-                            if (moduleNames == null) {
-                                moduleNames = new ArrayList<>();
-                                packageToModules.put(pkgName, moduleNames);
-                            }
-                            moduleNames.add(moduleName);
-                        }
-                    });
-                }
-            }
-        }
-
-        // create "/modules" directory
-        // "nodes" map contains only /modules/<foo> nodes only so far and so add all as children of /modules
-        DirNode modulesDir = new DirNode("/modules", new ArrayList<>(nodes.values()));
-        nodes.put(modulesDir.getName(), modulesDir);
-
-        // create children under "/packages"
-        List<Node> packagesChildren = new ArrayList<>(packageToModules.size());
-        for (Map.Entry<String, List<String>> entry : packageToModules.entrySet()) {
-            String pkgName = entry.getKey();
-            List<String> moduleNameList = entry.getValue();
-            List<Node> moduleLinkNodes = new ArrayList<>(moduleNameList.size());
-            for (String moduleName : moduleNameList) {
-                Node moduleNode = findModulesNode(MODULES + moduleName);
-                LinkNode linkNode = new LinkNode(PACKAGES + pkgName + "/" + moduleName, moduleNode);
-                nodes.put(linkNode.getName(), linkNode);
-                moduleLinkNodes.add(linkNode);
-            }
-
-            DirNode pkgDir = new DirNode(PACKAGES + pkgName, moduleLinkNodes);
-            nodes.put(pkgDir.getName(), pkgDir);
-            packagesChildren.add(pkgDir);
-        }
-
-        // "/packages" dir
-        DirNode packagesDir = new DirNode("/packages", packagesChildren);
-        nodes.put(packagesDir.getName(), packagesDir);
-
-        // finally "/" dir!
-        List<Node> rootChildren = new ArrayList<>();
-        rootChildren.add(modulesDir);
-        rootChildren.add(packagesDir);
-        DirNode root = new DirNode("/", rootChildren);
-        nodes.put(root.getName(), root);
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedPath.java	Thu Apr 21 15:04:00 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jrtfs;
-
-/**
- * Path implementation for jrt file system on JDK exploded modules build.
- *
- * @implNote This class needs to maintain JDK 8 source compatibility.
- *
- * It is used internally in the JDK to implement jimage/jrtfs access,
- * but also compiled and delivered as part of the jrtfs.jar to support access
- * to the jimage file provided by the shipped JDK by tools running on JDK 8.
- */
-final class JrtExplodedPath extends AbstractJrtPath {
-
-    JrtExplodedPath(AbstractJrtFileSystem jrtfs, byte[] path) {
-        super(jrtfs, path);
-    }
-
-    JrtExplodedPath(AbstractJrtFileSystem jrtfs, byte[] path, boolean normalized) {
-        super(jrtfs, path, normalized);
-    }
-
-    @Override
-    protected AbstractJrtPath newJrtPath(byte[] path) {
-        return new JrtExplodedPath(jrtfs, path);
-    }
-
-    @Override
-    protected AbstractJrtPath newJrtPath(byte[] path, boolean normalized) {
-        return new JrtExplodedPath(jrtfs, path, normalized);
-    }
-
-    @Override
-    public JrtExplodedFileSystem getFileSystem() {
-        return (JrtExplodedFileSystem) jrtfs;
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java	Fri Apr 22 01:04:01 2016 -0700
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * File attribute view for jrt file system.
@@ -42,7 +43,6 @@
 final class JrtFileAttributeView implements BasicFileAttributeView {
 
     private static enum AttrID {
-
         size,
         creationTime,
         lastAccessTime,
@@ -56,21 +56,19 @@
         extension
     };
 
-    private final AbstractJrtPath path;
+    private final JrtPath path;
     private final boolean isJrtView;
     private final LinkOption[] options;
 
-    private JrtFileAttributeView(AbstractJrtPath path, boolean isJrtView, LinkOption... options) {
+    private JrtFileAttributeView(JrtPath path, boolean isJrtView, LinkOption... options) {
         this.path = path;
         this.isJrtView = isJrtView;
         this.options = options;
     }
 
     @SuppressWarnings("unchecked") // Cast to V
-    static <V extends FileAttributeView> V get(AbstractJrtPath path, Class<V> type, LinkOption... options) {
-        if (type == null) {
-            throw new NullPointerException();
-        }
+    static <V extends FileAttributeView> V get(JrtPath path, Class<V> type, LinkOption... options) {
+        Objects.requireNonNull(type);
         if (type == BasicFileAttributeView.class) {
             return (V) new JrtFileAttributeView(path, false, options);
         }
@@ -80,10 +78,8 @@
         return null;
     }
 
-    static JrtFileAttributeView get(AbstractJrtPath path, String type, LinkOption... options) {
-        if (type == null) {
-            throw new NullPointerException();
-        }
+    static JrtFileAttributeView get(JrtPath path, String type, LinkOption... options) {
+        Objects.requireNonNull(type);
         if (type.equals("basic")) {
             return new JrtFileAttributeView(path, false, options);
         }
@@ -99,61 +95,74 @@
     }
 
     @Override
-    public AbstractJrtFileAttributes readAttributes() throws IOException {
+    public JrtFileAttributes readAttributes() throws IOException {
         return path.getAttributes(options);
     }
 
     @Override
     public void setTimes(FileTime lastModifiedTime,
-            FileTime lastAccessTime,
-            FileTime createTime)
-            throws IOException {
+                         FileTime lastAccessTime,
+                         FileTime createTime) throws IOException {
         path.setTimes(lastModifiedTime, lastAccessTime, createTime);
     }
 
-    void setAttribute(String attribute, Object value)
+    static void setAttribute(JrtPath path, String attribute, Object value)
             throws IOException {
+        int colonPos = attribute.indexOf(':');
+        if (colonPos != -1) {    // type = "basic", if no ":"
+            String type = attribute.substring(0, colonPos++);
+            if (!type.equals("basic") && !type.equals("jrt")) {
+                throw new UnsupportedOperationException(
+                    "view <" + type + "> is not supported");
+            }
+            attribute = attribute.substring(colonPos);
+        }
         try {
-            if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime) {
-                setTimes((FileTime) value, null, null);
-            }
-            if (AttrID.valueOf(attribute) == AttrID.lastAccessTime) {
-                setTimes(null, (FileTime) value, null);
-            }
-            if (AttrID.valueOf(attribute) == AttrID.creationTime) {
-                setTimes(null, null, (FileTime) value);
+            AttrID id = AttrID.valueOf(attribute);
+            if (id == AttrID.lastModifiedTime) {
+                path.setTimes((FileTime) value, null, null);
+            } else if (id == AttrID.lastAccessTime) {
+                path.setTimes(null, (FileTime) value, null);
+            } else if (id == AttrID.creationTime) {
+                path.setTimes(null, null, (FileTime) value);
             }
             return;
-        } catch (IllegalArgumentException x) {
-        }
+        } catch (IllegalArgumentException x) {}
         throw new UnsupportedOperationException("'" + attribute
                 + "' is unknown or read-only attribute");
     }
 
-    Map<String, Object> readAttributes(String attributes)
+    static Map<String, Object> readAttributes(JrtPath path, String attributes,
+                                              LinkOption... options)
             throws IOException {
-        AbstractJrtFileAttributes jrtfas = readAttributes();
+        int colonPos = attributes.indexOf(':');
+        boolean isJrtView = false;
+        if (colonPos != -1) {    // type = "basic", if no ":"
+            String type = attributes.substring(0, colonPos++);
+            if (!type.equals("basic") && !type.equals("jrt")) {
+                throw new UnsupportedOperationException("view <" + type +
+                                                        "> is not supported");
+            }
+            isJrtView = true;
+            attributes = attributes.substring(colonPos);
+        }
+        JrtFileAttributes jrtfas = path.getAttributes();
         LinkedHashMap<String, Object> map = new LinkedHashMap<>();
         if ("*".equals(attributes)) {
             for (AttrID id : AttrID.values()) {
-                try {
-                    map.put(id.name(), attribute(id, jrtfas));
-                } catch (IllegalArgumentException x) {
-                }
+                map.put(id.name(), attribute(id, jrtfas, isJrtView));
             }
         } else {
             String[] as = attributes.split(",");
             for (String a : as) {
-                try {
-                    map.put(a, attribute(AttrID.valueOf(a), jrtfas));
-                } catch (IllegalArgumentException x) {
-                }
+                //throw IllegalArgumentException
+                map.put(a, attribute(AttrID.valueOf(a), jrtfas, isJrtView));
             }
         }
         return map;
     }
 
-    Object attribute(AttrID id, AbstractJrtFileAttributes jrtfas) {
+    static Object attribute(AttrID id, JrtFileAttributes jrtfas, boolean isJrtView) {
         switch (id) {
             case size:
                 return jrtfas.size();
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,9 @@
  */
 package jdk.internal.jrtfs;
 
+import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileTime;
+import java.util.Formatter;
 import jdk.internal.jimage.ImageReader.Node;
 
 /**
@@ -36,7 +38,7 @@
  * but also compiled and delivered as part of the jrtfs.jar to support access
  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
-final class JrtFileAttributes extends AbstractJrtFileAttributes {
+final class JrtFileAttributes  implements BasicFileAttributes {
 
     private final Node node;
 
@@ -90,14 +92,50 @@
         return node.resolveLink(true);
     }
 
-    ///////// jrt entry attributes ///////////
-    @Override
+    ///////// jrtfs specific attributes ///////////
+    /**
+     * Compressed resource file. If not available or not applicable, 0L is
+     * returned.
+     *
+     * @return the compressed resource size for compressed resources.
+     */
     public long compressedSize() {
         return node.compressedSize();
     }
 
-    @Override
+    /**
+     * "file" extension of a file resource.
+     *
+     * @return extension string for the file resource
+     */
     public String extension() {
         return node.extension();
     }
+
+    @Override
+    public final String toString() {
+        StringBuilder sb = new StringBuilder(1024);
+        try (Formatter fm = new Formatter(sb)) {
+            if (creationTime() != null) {
+                fm.format("    creationTime    : %tc%n", creationTime().toMillis());
+            } else {
+                fm.format("    creationTime    : null%n");
+            }
+            if (lastAccessTime() != null) {
+                fm.format("    lastAccessTime  : %tc%n", lastAccessTime().toMillis());
+            } else {
+                fm.format("    lastAccessTime  : null%n");
+            }
+            fm.format("    lastModifiedTime: %tc%n", lastModifiedTime().toMillis());
+            fm.format("    isRegularFile   : %b%n", isRegularFile());
+            fm.format("    isDirectory     : %b%n", isDirectory());
+            fm.format("    isSymbolicLink  : %b%n", isSymbolicLink());
+            fm.format("    isOther         : %b%n", isOther());
+            fm.format("    fileKey         : %s%n", fileKey());
+            fm.format("    size            : %d%n", size());
+            fm.format("    compressedSize  : %d%n", compressedSize());
+            fm.format("    extension       : %s%n", extension());
+        }
+        return sb.toString();
+    }
 }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java	Fri Apr 22 01:04:01 2016 -0700
@@ -30,6 +30,7 @@
 import java.nio.file.attribute.FileAttributeView;
 import java.nio.file.attribute.BasicFileAttributeView;
 import java.nio.file.attribute.FileStoreAttributeView;
+import java.util.Objects;
 
 /**
  * File store implementation for jrt file systems.
@@ -44,7 +45,7 @@
 
     protected final FileSystem jrtfs;
 
-    JrtFileStore(AbstractJrtPath jrtPath) {
+    JrtFileStore(JrtPath jrtPath) {
         this.jrtfs = jrtPath.getFileSystem();
     }
 
@@ -71,9 +72,7 @@
     @Override
     @SuppressWarnings("unchecked")
     public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
-        if (type == null) {
-            throw new NullPointerException();
-        }
+        Objects.requireNonNull(type, "type");
         return (V) null;
     }
 
@@ -99,7 +98,7 @@
 
     @Override
     public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
-        return (type == BasicFileAttributeView.class
-                || type == JrtFileAttributeView.class);
+        return type == BasicFileAttributeView.class ||
+               type == JrtFileAttributeView.class;
     }
 }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java	Fri Apr 22 01:04:01 2016 -0700
@@ -24,23 +24,47 @@
  */
 package jdk.internal.jrtfs;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.nio.file.LinkOption;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.ClosedFileSystemException;
+import java.nio.file.CopyOption;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
 import java.nio.file.FileSystemException;
 import java.nio.file.InvalidPathException;
+import java.nio.file.LinkOption;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.NotDirectoryException;
+import java.nio.file.OpenOption;
 import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.ReadOnlyFileSystemException;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.WatchService;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.nio.file.spi.FileSystemProvider;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
-import java.util.function.Function;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Pattern;
+import jdk.internal.jimage.ImageReader.Node;
 import static java.util.stream.Collectors.toList;
-import jdk.internal.jimage.ImageReader;
-import jdk.internal.jimage.ImageReader.Node;
-
 
 /**
  * jrt file system implementation built on System jimage files.
@@ -51,33 +75,21 @@
  * but also compiled and delivered as part of the jrtfs.jar to support access
  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
-class JrtFileSystem extends AbstractJrtFileSystem {
+class JrtFileSystem extends FileSystem {
 
-    // System image reader
-    private ImageReader bootImage;
-    // root path
-    private final JrtPath rootPath;
+    private final JrtFileSystemProvider provider;
+    private final JrtPath rootPath = new JrtPath(this, "/");
     private volatile boolean isOpen;
+    private volatile boolean isClosable;
+    private SystemImage image;
 
-    // open a .jimage and build directory structure
-    private static ImageReader openImage(Path path) throws IOException {
-        ImageReader image = ImageReader.open(path);
-        image.getRootDirectory();
-        return image;
-    }
-
-    JrtFileSystem(JrtFileSystemProvider provider,
-            Map<String, ?> env)
-            throws IOException {
-        super(provider, env);
-        checkExists(SystemImages.moduleImageFile());
-
-        // open image file
-        this.bootImage = openImage(SystemImages.moduleImageFile());
-
-        byte[] root = new byte[]{'/'};
-        rootPath = new JrtPath(this, root);
-        isOpen = true;
+    JrtFileSystem(JrtFileSystemProvider provider, Map<String, ?> env)
+            throws IOException
+    {
+        this.provider = provider;
+        this.image = SystemImage.open();  // open image file
+        this.isOpen = true;
+        this.isClosable = env != null;
     }
 
     // FileSystem method implementations
@@ -88,6 +100,8 @@
 
     @Override
     public void close() throws IOException {
+        if (!isClosable)
+            throw new UnsupportedOperationException();
         cleanup();
     }
 
@@ -95,237 +109,397 @@
     protected void finalize() throws Throwable {
         try {
             cleanup();
-        } catch (IOException ignored) {
-        }
-        super.finalize();
-    }
-
-    // AbstractJrtFileSystem method implementations
-    @Override
-    JrtPath getRootPath() {
-        return rootPath;
+        } catch (IOException ignored) {}
     }
 
     @Override
-    boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException {
-        ensureOpen();
-        Node node1 = findNode(p1);
-        Node node2 = findNode(p2);
-        return node1.equals(node2);
+    public FileSystemProvider provider() {
+        return provider;
     }
 
     @Override
-    boolean isLink(AbstractJrtPath jrtPath) throws IOException {
-        return checkNode(jrtPath).isLink();
+    public Iterable<Path> getRootDirectories() {
+        ArrayList<Path> dirs = new ArrayList<>();
+        dirs.add(getRootPath());
+        return dirs;
     }
 
     @Override
-    AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException {
-        Node node = checkNode(jrtPath);
-        if (node.isLink()) {
-            node = node.resolveLink();
-            return toJrtPath(getBytes(node.getName()));
+    public JrtPath getPath(String first, String... more) {
+        if (more.length == 0) {
+            return new JrtPath(this, first);
         }
-
-        return jrtPath;
+        StringBuilder sb = new StringBuilder();
+        sb.append(first);
+        for (String path : more) {
+            if (path.length() > 0) {
+                if (sb.length() > 0) {
+                    sb.append('/');
+                }
+                sb.append(path);
+            }
+        }
+        return new JrtPath(this, sb.toString());
     }
 
     @Override
-    JrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options)
+    public final boolean isReadOnly() {
+        return true;
+    }
+
+    @Override
+    public final UserPrincipalLookupService getUserPrincipalLookupService() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final WatchService newWatchService() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final Iterable<FileStore> getFileStores() {
+        ArrayList<FileStore> list = new ArrayList<>(1);
+        list.add(getFileStore(getRootPath()));
+        return list;
+    }
+
+    private static final Set<String> supportedFileAttributeViews
+            = Collections.unmodifiableSet(
+                    new HashSet<String>(Arrays.asList("basic", "jrt")));
+
+    @Override
+    public final Set<String> supportedFileAttributeViews() {
+        return supportedFileAttributeViews;
+    }
+
+    @Override
+    public final String toString() {
+        return "jrt:/";
+    }
+
+    @Override
+    public final String getSeparator() {
+        return "/";
+    }
+
+    @Override
+    public PathMatcher getPathMatcher(String syntaxAndInput) {
+        int pos = syntaxAndInput.indexOf(':');
+        if (pos <= 0 || pos == syntaxAndInput.length()) {
+            throw new IllegalArgumentException();
+        }
+        String syntax = syntaxAndInput.substring(0, pos);
+        String input = syntaxAndInput.substring(pos + 1);
+        String expr;
+        if (syntax.equalsIgnoreCase("glob")) {
+            expr = JrtUtils.toRegexPattern(input);
+        } else if (syntax.equalsIgnoreCase("regex")) {
+            expr = input;
+        } else {
+                throw new UnsupportedOperationException("Syntax '" + syntax
+                        + "' not recognized");
+        }
+        // return matcher
+        final Pattern pattern = Pattern.compile(expr);
+        return (Path path) -> pattern.matcher(path.toString()).matches();
+    }
+
+    JrtPath resolveLink(JrtPath path) throws IOException {
+        Node node = checkNode(path);
+        if (node.isLink()) {
+            node = node.resolveLink();
+            return new JrtPath(this, node.getName());  // TBD, normalized?
+        }
+        return path;
+    }
+
+    JrtFileAttributes getFileAttributes(JrtPath path, LinkOption... options)
             throws IOException {
-        Node node = checkNode(jrtPath);
+        Node node = checkNode(path);
         if (node.isLink() && followLinks(options)) {
             return new JrtFileAttributes(node.resolveLink(true));
         }
         return new JrtFileAttributes(node);
     }
 
-    @Override
-    boolean exists(AbstractJrtPath jrtPath) throws IOException {
+    /**
+     * returns the list of child paths of the given directory "path"
+     *
+     * @param path name of the directory whose content is listed
+     * @return iterator for child paths of the given directory path
+     */
+    Iterator<Path> iteratorOf(JrtPath path, DirectoryStream.Filter<? super Path> filter)
+            throws IOException {
+        Node node = checkNode(path).resolveLink(true);
+        if (!node.isDirectory()) {
+            throw new NotDirectoryException(path.getName());
+        }
+        if (filter == null) {
+            return node.getChildren()
+                       .stream()
+                       .map(child -> (Path)(path.resolve(new JrtPath(this, child.getNameString()).getFileName())))
+                       .iterator();
+        }
+        return node.getChildren()
+                   .stream()
+                   .map(child -> (Path)(path.resolve(new JrtPath(this, child.getNameString()).getFileName())))
+                   .filter(p ->  { try { return filter.accept(p);
+                                   } catch (IOException x) {}
+                                   return false;
+                                  })
+                   .iterator();
+    }
+
+    // returns the content of the file resource specified by the path
+    byte[] getFileContent(JrtPath path) throws IOException {
+        Node node = checkNode(path);
+        if (node.isDirectory()) {
+            throw new FileSystemException(path + " is a directory");
+        }
+        //assert node.isResource() : "resource node expected here";
+        return image.getResource(node);
+    }
+
+    /////////////// Implementation details below this point //////////
+
+    // static utility methods
+    static ReadOnlyFileSystemException readOnly() {
+        return new ReadOnlyFileSystemException();
+    }
+
+    // do the supplied options imply that we have to chase symlinks?
+    static boolean followLinks(LinkOption... options) {
+        if (options != null) {
+            for (LinkOption lo : options) {
+                Objects.requireNonNull(lo);
+                if (lo == LinkOption.NOFOLLOW_LINKS) {
+                    return false;
+                } else {
+                    throw new AssertionError("should not reach here");
+                }
+            }
+        }
+        return true;
+    }
+
+    // check that the options passed are supported by (read-only) jrt file system
+    static void checkOptions(Set<? extends OpenOption> options) {
+        // check for options of null type and option is an intance of StandardOpenOption
+        for (OpenOption option : options) {
+            Objects.requireNonNull(option);
+            if (!(option instanceof StandardOpenOption)) {
+                throw new IllegalArgumentException();
+            }
+        }
+        if (options.contains(StandardOpenOption.WRITE) ||
+            options.contains(StandardOpenOption.APPEND)) {
+            throw readOnly();
+        }
+    }
+
+    // clean up this file system - called from finalize and close
+    void cleanup() throws IOException {
+        if (!isOpen) {
+            return;
+        }
+        synchronized (this) {
+            isOpen = false;
+            // close image reader and null out
+            image.close();
+            image = null;
+        }
+    }
+
+    // These methods throw read only file system exception
+    final void setTimes(JrtPath jrtPath, FileTime mtime, FileTime atime, FileTime ctime)
+            throws IOException {
+        throw readOnly();
+    }
+
+    // These methods throw read only file system exception
+    final void createDirectory(JrtPath jrtPath, FileAttribute<?>... attrs) throws IOException {
+        throw readOnly();
+    }
+
+    final void deleteFile(JrtPath jrtPath, boolean failIfNotExists)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final OutputStream newOutputStream(JrtPath jrtPath, OpenOption... options)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final void copyFile(boolean deletesrc, JrtPath srcPath, JrtPath dstPath, CopyOption... options)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final FileChannel newFileChannel(JrtPath path,
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        throw new UnsupportedOperationException("newFileChannel");
+    }
+
+    final InputStream newInputStream(JrtPath path) throws IOException {
+        return new ByteArrayInputStream(getFileContent(path));
+    }
+
+    final SeekableByteChannel newByteChannel(JrtPath path,
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        checkOptions(options);
+
+        byte[] buf = getFileContent(path);
+        final ReadableByteChannel rbc
+                = Channels.newChannel(new ByteArrayInputStream(buf));
+        final long size = buf.length;
+        return new SeekableByteChannel() {
+            long read = 0;
+
+            @Override
+            public boolean isOpen() {
+                return rbc.isOpen();
+            }
+
+            @Override
+            public long position() throws IOException {
+                return read;
+            }
+
+            @Override
+            public SeekableByteChannel position(long pos)
+                    throws IOException {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int read(ByteBuffer dst) throws IOException {
+                int n = rbc.read(dst);
+                if (n > 0) {
+                    read += n;
+                }
+                return n;
+            }
+
+            @Override
+            public SeekableByteChannel truncate(long size)
+                    throws IOException {
+                throw new NonWritableChannelException();
+            }
+
+            @Override
+            public int write(ByteBuffer src) throws IOException {
+                throw new NonWritableChannelException();
+            }
+
+            @Override
+            public long size() throws IOException {
+                return size;
+            }
+
+            @Override
+            public void close() throws IOException {
+                rbc.close();
+            }
+        };
+    }
+
+    final JrtFileStore getFileStore(JrtPath path) {
+        return new JrtFileStore(path);
+    }
+
+    final void ensureOpen() throws IOException {
+        if (!isOpen()) {
+            throw new ClosedFileSystemException();
+        }
+    }
+
+    final JrtPath getRootPath() {
+        return rootPath;
+    }
+
+    boolean isSameFile(JrtPath path1, JrtPath path2) throws IOException {
+        return checkNode(path1) == checkNode(path2);
+    }
+
+    boolean isLink(JrtPath path) throws IOException {
+        return checkNode(path).isLink();
+    }
+
+    boolean exists(JrtPath path) throws IOException {
         try {
-            checkNode(jrtPath);
+            checkNode(path);
         } catch (NoSuchFileException exp) {
             return false;
         }
         return true;
     }
 
-    @Override
-    boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks)
+    boolean isDirectory(JrtPath path, boolean resolveLinks)
             throws IOException {
-        Node node = checkNode(jrtPath);
+        Node node = checkNode(path);
         return resolveLinks && node.isLink()
                 ? node.resolveLink(true).isDirectory()
                 : node.isDirectory();
     }
 
-    @Override
-    Iterator<Path> iteratorOf(AbstractJrtPath jrtPath) throws IOException {
-        Node node = checkNode(jrtPath).resolveLink(true);
-        if (!node.isDirectory()) {
-            throw new NotDirectoryException(getString(jrtPath.getName()));
+    JrtPath toRealPath(JrtPath path, LinkOption... options)
+            throws IOException {
+        Node node = checkNode(path);
+        if (followLinks(options) && node.isLink()) {
+            node = node.resolveLink();
         }
-
-        if (node.isRootDir()) {
-            return rootDirIterator(jrtPath);
-        } else if (node.isModulesDir()) {
-            return modulesDirIterator(jrtPath);
-        } else if (node.isPackagesDir()) {
-            return packagesDirIterator(jrtPath);
-        }
-
-        return nodesToIterator(jrtPath, node.getChildren());
+        // image node holds the real/absolute path name
+        return new JrtPath(this, node.getName(), true);
     }
 
-    @Override
-    byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException {
-        final Node node = checkResource(jrtPath);
-        return bootImage.getResource(node);
-    }
-
-    // Implementation details below this point
-    // clean up this file system - called from finalize and close
-    private void cleanup() throws IOException {
-        if (!isOpen) {
-            return;
-        }
-
-        synchronized (this) {
-            isOpen = false;
-
-            // close all image reader and null out
-            bootImage.close();
-            bootImage = null;
+    private Node lookup(String path) {
+        try {
+            return image.findNode(path);
+        } catch (RuntimeException re) {
+            throw new InvalidPathException(path, re.toString());
         }
     }
 
-    private Node lookup(byte[] path) {
-        Node node = null;
-        try {
-            node = bootImage.findNode(getString(path));
-        } catch (RuntimeException re) {
-            throw new InvalidPathException(getString(path), re.toString());
+    private Node lookupSymbolic(String path) {
+        int i = 1;
+        while (i < path.length()) {
+            i = path.indexOf('/', i);
+            if (i == -1) {
+                break;
+            }
+            String prefix = path.substring(0, i);
+            Node node = lookup(prefix);
+            if (node == null) {
+                break;
+            }
+            if (node.isLink()) {
+                Node link = node.resolveLink(true);
+                // resolved symbolic path concatenated to the rest of the path
+                String resPath = link.getName() + path.substring(i);
+                node = lookup(resPath);
+                return node != null ? node : lookupSymbolic(resPath);
+            }
+            i++;
         }
-        return node;
-    }
-
-    private Node lookupSymbolic(byte[] path) {
-        for (int i = 1; i < path.length; i++) {
-            if (path[i] == (byte) '/') {
-                byte[] prefix = Arrays.copyOfRange(path, 0, i);
-                Node node = lookup(prefix);
-                if (node == null) {
-                    break;
-                }
-
-                if (node.isLink()) {
-                    Node link = node.resolveLink(true);
-                    // resolved symbolic path concatenated to the rest of the path
-                    String resPath = link.getName() + getString(path).substring(i);
-                    byte[] resPathBytes = getBytes(resPath);
-                    node = lookup(resPathBytes);
-                    return node != null ? node : lookupSymbolic(resPathBytes);
-                }
-            }
-        }
-
         return null;
     }
 
-    private Node findNode(AbstractJrtPath jrtPath) throws IOException {
-        return findNode(jrtPath.getResolvedPath());
-    }
-
-    private Node findNode(byte[] path) throws IOException {
-        Node node = lookup(path);
+    Node checkNode(JrtPath path) throws IOException {
+        ensureOpen();
+        String p = path.getResolvedPath();
+        Node node = lookup(p);
         if (node == null) {
-            node = lookupSymbolic(path);
+            node = lookupSymbolic(p);
             if (node == null) {
-                throw new NoSuchFileException(getString(path));
+                throw new NoSuchFileException(p);
             }
         }
         return node;
     }
-
-    private Node checkNode(AbstractJrtPath jrtPath) throws IOException {
-        return checkNode(jrtPath.getResolvedPath());
-    }
-
-    private Node checkNode(byte[] path) throws IOException {
-        ensureOpen();
-        return findNode(path);
-    }
-
-    private Node checkResource(AbstractJrtPath jrtPath) throws IOException {
-        return checkResource(jrtPath.getResolvedPath());
-    }
-
-    private Node checkResource(byte[] path) throws IOException {
-        Node node = checkNode(path);
-        if (node.isDirectory()) {
-            throw new FileSystemException(getString(path) + " is a directory");
-        }
-
-        assert node.isResource() : "resource node expected here";
-        return node;
-    }
-
-    private JrtPath toJrtPath(String path) {
-        return toJrtPath(getBytes(path));
-    }
-
-    private JrtPath toJrtPath(byte[] path) {
-        return new JrtPath(this, path);
-    }
-
-    private Iterator<Path> nodesToIterator(AbstractJrtPath dir, List<Node> childNodes) {
-        Function<Node, Path> nodeToPath =
-            child -> dir.resolve(
-                toJrtPath(child.getNameString()).getFileName());
-        return childNodes.stream().
-                map(nodeToPath).collect(toList()).
-                iterator();
-    }
-
-    private List<Node> rootChildren;
-
-    private synchronized void initRootChildren(AbstractJrtPath jrtPath) throws IOException {
-        if (rootChildren == null) {
-            rootChildren = new ArrayList<>();
-            rootChildren.addAll(findNode(jrtPath).getChildren());
-        }
-    }
-
-    private Iterator<Path> rootDirIterator(AbstractJrtPath jrtPath) throws IOException {
-        initRootChildren(jrtPath);
-        return nodesToIterator(jrtPath, rootChildren);
-    }
-
-    private List<Node> modulesChildren;
-
-    private synchronized void initModulesChildren(AbstractJrtPath jrtPath) throws IOException {
-        if (modulesChildren == null) {
-            modulesChildren = new ArrayList<>();
-            modulesChildren.addAll(findNode(jrtPath).getChildren());
-        }
-    }
-
-    private Iterator<Path> modulesDirIterator(AbstractJrtPath jrtPath) throws IOException {
-        initModulesChildren(jrtPath);
-        return nodesToIterator(jrtPath, modulesChildren);
-    }
-
-    private List<Node> packagesChildren;
-
-    private synchronized void initPackagesChildren(AbstractJrtPath jrtPath) throws IOException {
-        if (packagesChildren == null) {
-            packagesChildren = new ArrayList<>();
-            packagesChildren.addAll(findNode(jrtPath).getChildren());
-        }
-    }
-
-    private Iterator<Path> packagesDirIterator(AbstractJrtPath jrtPath) throws IOException {
-        initPackagesChildren(jrtPath);
-        return nodesToIterator(jrtPath, packagesChildren);
-    }
 }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,7 +70,7 @@
     private void checkPermission() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            String home = SystemImages.RUNTIME_HOME;
+            String home = SystemImage.RUNTIME_HOME;
             FilePermission perm
                     = new FilePermission(home + File.separator + "-", "read");
             sm.checkPermission(perm);
@@ -101,15 +101,13 @@
     @Override
     public FileSystem newFileSystem(URI uri, Map<String, ?> env)
             throws IOException {
+        Objects.requireNonNull(env);
         checkPermission();
         checkUri(uri);
-
-        if (env != null && env.containsKey("java.home")) {
+        if (env.containsKey("java.home")) {
             return newFileSystem((String)env.get("java.home"), uri, env);
         } else {
-            return SystemImages.hasModulesImage()
-                    ? new JrtFileSystem(this, env)
-                    : new JrtExplodedFileSystem(this, env);
+            return new JrtFileSystem(this, env);
         }
     }
 
@@ -121,7 +119,6 @@
         if (Files.notExists(jrtfs)) {
             throw new IOException(jrtfs.toString() + " not exist");
         }
-
         Map<String,?> newEnv = new HashMap<>(env);
         newEnv.remove("java.home");
         ClassLoader cl = newJrtFsLoader(jrtfs);
@@ -139,7 +136,6 @@
         JrtFsLoader(URL[] urls) {
             super(urls);
         }
-
         @Override
         protected Class<?> loadClass(String cn, boolean resolve)
                 throws ClassNotFoundException
@@ -208,21 +204,7 @@
                 fs = this.theFileSystem;
                 if (fs == null) {
                     try {
-                        if (SystemImages.hasModulesImage()) {
-                            this.theFileSystem = fs = new JrtFileSystem(this, null) {
-                                @Override
-                                public void close() {
-                                    throw new UnsupportedOperationException();
-                                }
-                            };
-                        } else {
-                            this.theFileSystem = fs = new JrtExplodedFileSystem(this, null) {
-                                @Override
-                                public void close() {
-                                    throw new UnsupportedOperationException();
-                                }
-                            };
-                        }
+                        this.theFileSystem = fs = new JrtFileSystem(this, null);
                     } catch (IOException ioe) {
                         throw new InternalError(ioe);
                     }
@@ -240,69 +222,67 @@
     }
 
     // Checks that the given file is a JrtPath
-    static final AbstractJrtPath toAbstractJrtPath(Path path) {
-        if (path == null) {
-            throw new NullPointerException();
-        }
-        if (!(path instanceof AbstractJrtPath)) {
+    static final JrtPath toJrtPath(Path path) {
+        Objects.requireNonNull(path, "path");
+        if (!(path instanceof JrtPath)) {
             throw new ProviderMismatchException();
         }
-        return (AbstractJrtPath) path;
+        return (JrtPath) path;
     }
 
     @Override
     public void checkAccess(Path path, AccessMode... modes) throws IOException {
-        toAbstractJrtPath(path).checkAccess(modes);
+        toJrtPath(path).checkAccess(modes);
     }
 
     @Override
     public Path readSymbolicLink(Path link) throws IOException {
-        return toAbstractJrtPath(link).readSymbolicLink();
+        return toJrtPath(link).readSymbolicLink();
     }
 
     @Override
     public void copy(Path src, Path target, CopyOption... options)
             throws IOException {
-        toAbstractJrtPath(src).copy(toAbstractJrtPath(target), options);
+        toJrtPath(src).copy(toJrtPath(target), options);
     }
 
     @Override
     public void createDirectory(Path path, FileAttribute<?>... attrs)
             throws IOException {
-        toAbstractJrtPath(path).createDirectory(attrs);
+        toJrtPath(path).createDirectory(attrs);
     }
 
     @Override
     public final void delete(Path path) throws IOException {
-        toAbstractJrtPath(path).delete();
+        toJrtPath(path).delete();
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public <V extends FileAttributeView> V
             getFileAttributeView(Path path, Class<V> type, LinkOption... options) {
-        return JrtFileAttributeView.get(toAbstractJrtPath(path), type, options);
+        return JrtFileAttributeView.get(toJrtPath(path), type, options);
     }
 
     @Override
     public FileStore getFileStore(Path path) throws IOException {
-        return toAbstractJrtPath(path).getFileStore();
+        return toJrtPath(path).getFileStore();
     }
 
     @Override
     public boolean isHidden(Path path) {
-        return toAbstractJrtPath(path).isHidden();
+        return toJrtPath(path).isHidden();
     }
 
     @Override
     public boolean isSameFile(Path path, Path other) throws IOException {
-        return toAbstractJrtPath(path).isSameFile(other);
+        return toJrtPath(path).isSameFile(other);
     }
 
     @Override
     public void move(Path src, Path target, CopyOption... options)
             throws IOException {
-        toAbstractJrtPath(src).move(toAbstractJrtPath(target), options);
+        toJrtPath(src).move(toJrtPath(target), options);
     }
 
     @Override
@@ -319,13 +299,13 @@
             Set<? extends OpenOption> options,
             FileAttribute<?>... attrs)
             throws IOException {
-        return toAbstractJrtPath(path).newByteChannel(options, attrs);
+        return toJrtPath(path).newByteChannel(options, attrs);
     }
 
     @Override
     public DirectoryStream<Path> newDirectoryStream(
             Path path, Filter<? super Path> filter) throws IOException {
-        return toAbstractJrtPath(path).newDirectoryStream(filter);
+        return toJrtPath(path).newDirectoryStream(filter);
     }
 
     @Override
@@ -333,19 +313,19 @@
             Set<? extends OpenOption> options,
             FileAttribute<?>... attrs)
             throws IOException {
-        return toAbstractJrtPath(path).newFileChannel(options, attrs);
+        return toJrtPath(path).newFileChannel(options, attrs);
     }
 
     @Override
     public InputStream newInputStream(Path path, OpenOption... options)
             throws IOException {
-        return toAbstractJrtPath(path).newInputStream(options);
+        return toJrtPath(path).newInputStream(options);
     }
 
     @Override
     public OutputStream newOutputStream(Path path, OpenOption... options)
             throws IOException {
-        return toAbstractJrtPath(path).newOutputStream(options);
+        return toJrtPath(path).newOutputStream(options);
     }
 
     @Override
@@ -354,7 +334,7 @@
             readAttributes(Path path, Class<A> type, LinkOption... options)
             throws IOException {
         if (type == BasicFileAttributes.class || type == JrtFileAttributes.class) {
-            return (A) toAbstractJrtPath(path).getAttributes(options);
+            return (A) toJrtPath(path).getAttributes(options);
         }
         return null;
     }
@@ -363,13 +343,13 @@
     public Map<String, Object>
             readAttributes(Path path, String attribute, LinkOption... options)
             throws IOException {
-        return toAbstractJrtPath(path).readAttributes(attribute, options);
+        return toJrtPath(path).readAttributes(attribute, options);
     }
 
     @Override
     public void setAttribute(Path path, String attribute,
             Object value, LinkOption... options)
             throws IOException {
-        toAbstractJrtPath(path).setAttribute(attribute, value, options);
+        toJrtPath(path).setAttribute(attribute, value, options);
     }
 }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java	Thu Apr 21 15:04:00 2016 -0400
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java	Fri Apr 22 01:04:01 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,30 @@
  */
 package jdk.internal.jrtfs;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.*;
+import java.nio.file.DirectoryStream.Filter;;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileTime;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
 /**
- * jrt Path implementation for jrt on .jimage files.
+ * Base class for Path implementation of jrt file systems.
  *
  * @implNote This class needs to maintain JDK 8 source compatibility.
  *
@@ -33,23 +55,756 @@
  * but also compiled and delivered as part of the jrtfs.jar to support access
  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
-final class JrtPath extends AbstractJrtPath {
+final class JrtPath implements Path {
 
-    JrtPath(AbstractJrtFileSystem jrtfs, byte[] path) {
-        this(jrtfs, path, false);
+    final JrtFileSystem jrtfs;
+    private final String path;
+    private volatile int[] offsets;
+
+    JrtPath(JrtFileSystem jrtfs, String path) {
+        this.jrtfs = jrtfs;
+        this.path = normalize(path);
+        this.resolved = null;
     }
 
-    JrtPath(AbstractJrtFileSystem jrtfs, byte[] path, boolean normalized) {
-        super(jrtfs, path, normalized);
+    JrtPath(JrtFileSystem jrtfs, String path, boolean normalized) {
+        this.jrtfs = jrtfs;
+        this.path = normalized ? path : normalize(path);
+        this.resolved = null;
+    }
+
+    final String getName() {
+        return path;
     }
 
     @Override
-    protected JrtPath newJrtPath(byte[] path) {
-        return new JrtPath(jrtfs, path);
+    public final JrtPath getRoot() {
+        if (this.isAbsolute()) {
+            return jrtfs.getRootPath();
+        } else {
+            return null;
+        }
     }
 
     @Override
-    protected JrtPath newJrtPath(byte[] path, boolean normalized) {
-        return new JrtPath(jrtfs, path, normalized);
+    public final JrtPath getFileName() {
+        if (path.length() == 0)
+            return this;
+        if (path.length() == 1 && path.charAt(0) == '/')
+            return null;
+        int off = path.lastIndexOf('/');
+        if (off == -1)
+            return this;
+        return new JrtPath(jrtfs, path.substring(off + 1), true);
+    }
+
+    @Override
+    public final JrtPath getParent() {
+        initOffsets();
+        int count = offsets.length;
+        if (count == 0) {     // no elements so no parent
+            return null;
+        }
+        int off = offsets[count - 1] - 1;
+        if (off <= 0) {       // parent is root only (may be null)
+            return getRoot();
+        }
+        return new JrtPath(jrtfs, path.substring(0, off));
+    }
+
+    @Override
+    public final int getNameCount() {
+        initOffsets();
+        return offsets.length;
+    }
+
+    @Override
+    public final JrtPath getName(int index) {
+        initOffsets();
+        if (index < 0 || index >= offsets.length) {
+            throw new IllegalArgumentException();
+        }
+        int begin = offsets[index];
+        int end;
+        if (index == (offsets.length - 1)) {
+            end = path.length();
+        } else {
+            end = offsets[index + 1];
+        }
+        return new JrtPath(jrtfs, path.substring(begin, end));
+    }
+
+    @Override
+    public final JrtPath subpath(int beginIndex, int endIndex) {
+        initOffsets();
+        if (beginIndex < 0 || endIndex > offsets.length ||
+            beginIndex >= endIndex) {
+            throw new IllegalArgumentException();
+        }
+        // starting/ending offsets
+        int begin = offsets[beginIndex];
+        int end;
+        if (endIndex == offsets.length) {
+            end = path.length();
+        } else {
+            end = offsets[endIndex];
+        }
+        return new JrtPath(jrtfs, path.substring(begin, end));
+    }
+
+    @Override
+    public final JrtPath toRealPath(LinkOption... options) throws IOException {
+        return jrtfs.toRealPath(this, options);
+    }
+
+    @Override
+    public final JrtPath toAbsolutePath() {
+        if (isAbsolute())
+            return this;
+        return new JrtPath(jrtfs, "/" + path, true);
+    }
+
+    @Override
+    public final URI toUri() {
+        try {
+            return new URI("jrt", toAbsolutePath().path, null);
+        } catch (URISyntaxException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    private boolean equalsNameAt(JrtPath other, int index) {
+        int mbegin = offsets[index];
+        int mlen;
+        if (index == (offsets.length - 1)) {
+            mlen = path.length() - mbegin;
+        } else {
+            mlen = offsets[index + 1] - mbegin - 1;
+        }
+        int obegin = other.offsets[index];
+        int olen;
+        if (index == (other.offsets.length - 1)) {
+            olen = other.path.length() - obegin;
+        } else {
+            olen = other.offsets[index + 1] - obegin - 1;
+        }
+        if (mlen != olen) {
+            return false;
+        }
+        int n = 0;
+        while (n < mlen) {
+            if (path.charAt(mbegin + n) != other.path.charAt(obegin + n)) {
+                return false;
+            }
+            n++;
+        }
+        return true;
+    }
+
+    @Override
+    public final JrtPath relativize(Path other) {
+        final JrtPath o = checkPath(other);
+        if (o.equals(this)) {
+            return new JrtPath(jrtfs, "", true);
+        }
+        if (path.length() == 0) {
+            return o;
+        }
+        if (jrtfs != o.jrtfs || isAbsolute() != o.isAbsolute()) {
+            throw new IllegalArgumentException();
+        }
+        final String tp = this.path;
+        final String op = o.path;
+        if (op.startsWith(tp)) {    // fast path
+            int off = tp.length();
+            if (op.charAt(off - 1) == '/')
+                return new JrtPath(jrtfs, op.substring(off), true);
+            if (op.charAt(off) == '/')
+                return new JrtPath(jrtfs, op.substring(off + 1), true);
+        }
+        int mc = this.getNameCount();
+        int oc = o.getNameCount();
+        int n = Math.min(mc, oc);
+        int i = 0;
+        while (i < n) {
+            if (!equalsNameAt(o, i)) {
+                break;
+            }
+            i++;
+        }
+        int dotdots = mc - i;
+        int len = dotdots * 3 - 1;
+        if (i < oc) {
+            len += (o.path.length() - o.offsets[i] + 1);
+        }
+        StringBuilder sb  = new StringBuilder(len);
+        while (dotdots > 0) {
+            sb.append("..");
+            if (sb.length() < len) {  // no tailing slash at the end
+                sb.append('/');
+            }
+            dotdots--;
+        }
+        if (i < oc) {
+            sb.append(o.path, o.offsets[i], o.path.length());
+        }
+        return new JrtPath(jrtfs, sb.toString(), true);
+    }
+
+    @Override
+    public JrtFileSystem getFileSystem() {
+        return jrtfs;
+    }
+
+    @Override
+    public final boolean isAbsolute() {
+        return path.length() > 0 && path.charAt(0) == '/';
+    }
+
+    @Override
+    public final JrtPath resolve(Path other) {
+        final JrtPath o = checkPath(other);
+        if (this.path.length() == 0 || o.isAbsolute()) {
+            return o;
+        }
+        if (o.path.length() == 0) {
+            return this;
+        }
+        StringBuilder sb = new StringBuilder(path.length() + o.path.length());
+        sb.append(path);
+        if (path.charAt(path.length() - 1) != '/')
+            sb.append('/');
+        sb.append(o.path);
+        return new JrtPath(jrtfs, sb.toString(), true);
+    }
+
+    @Override
+    public final Path resolveSibling(Path other) {
+        Objects.requireNonNull(other, "other");
+        Path parent = getParent();
+        return (parent == null) ? other : parent.resolve(other);
+    }
+
+    @Override
+    public final boolean startsWith(Path other) {
+        if (!(Objects.requireNonNull(other) instanceof JrtPath))
+            return false;
+        final JrtPath o = (JrtPath)other;
+        final String tp = this.path;
+        final String op = o.path;
+        if (isAbsolute() != o.isAbsolute() || !tp.startsWith(op)) {
+            return false;
+        }
+        int off = op.length();
+        if (off == 0) {
+            return tp.length() == 0;
+        }
+        // check match is on name boundary
+        return tp.length() == off || tp.charAt(off) == '/' ||
+               off == 0 || op.charAt(off - 1) == '/';
+    }
+
+    @Override
+    public final boolean endsWith(Path other) {
+        if (!(Objects.requireNonNull(other) instanceof JrtPath))
+            return false;
+        final JrtPath o = (JrtPath)other;
+        final JrtPath t = this;
+        int olast = o.path.length() - 1;
+        if (olast > 0 && o.path.charAt(olast) == '/') {
+            olast--;
+        }
+        int last = t.path.length() - 1;
+        if (last > 0 && t.path.charAt(last) == '/') {
+            last--;
+        }
+        if (olast == -1) {  // o.path.length == 0
+            return last == -1;
+        }
+        if ((o.isAbsolute() && (!t.isAbsolute() || olast != last))
+            || last < olast) {
+            return false;
+        }
+        for (; olast >= 0; olast--, last--) {
+            if (o.path.charAt(olast) != t.path.charAt(last)) {
+                return false;
+            }
+        }
+        return o.path.charAt(olast + 1) == '/' ||
+               last == -1 || t.path.charAt(last) == '/';
+    }
+
+    @Override
+    public final JrtPath resolve(String other) {
+        return resolve(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final Path resolveSibling(String other) {
+        return resolveSibling(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final boolean startsWith(String other) {
+        return startsWith(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final boolean endsWith(String other) {
+        return endsWith(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final JrtPath normalize() {
+        String res = getResolved();
+        if (res == path) {  // no change
+            return this;
+        }
+        return new JrtPath(jrtfs, res, true);
+    }
+
+    private JrtPath checkPath(Path path) {
+        Objects.requireNonNull(path);
+        if (!(path instanceof JrtPath))
+            throw new ProviderMismatchException();
+        return (JrtPath) path;
+    }
+
+    // create offset list if not already created
+    private void initOffsets() {
+        if (this.offsets == null) {
+            int len = path.length();
+            // count names
+            int count = 0;
+            int off = 0;
+            while (off < len) {
+                char c = path.charAt(off++);
+                if (c != '/') {
+                    count++;
+                    off = path.indexOf('/', off);
+                    if (off == -1)
+                        break;
+                }
+            }
+            // populate offsets
+            int[] offsets = new int[count];
+            count = 0;
+            off = 0;
+            while (off < len) {
+                char c = path.charAt(off);
+                if (c == '/') {
+                    off++;
+                } else {
+                    offsets[count++] = off++;
+                    off = path.indexOf('/', off);
+                    if (off == -1)
+                        break;
+                }
+            }
+            this.offsets = offsets;
+        }
+    }
+
+    private volatile String resolved;
+
+    final String getResolvedPath() {
+        String r = resolved;
+        if (r == null) {
+            if (isAbsolute()) {
+                r = getResolved();
+            } else {
+                r = toAbsolutePath().getResolvedPath();
+            }
+            resolved = r;
+        }
+        return r;
+    }
+
+    // removes redundant slashs, replace "\" to separator "/"
+    // and check for invalid characters
+    private static String normalize(String path) {
+        int len = path.length();
+        if (len == 0) {
+            return path;
+        }
+        char prevC = 0;
+        for (int i = 0; i < len; i++) {
+            char c = path.charAt(i);
+            if (c == '\\' || c == '\u0000') {
+                return normalize(path, i);
+            }
+            if (c == '/' && prevC == '/') {
+                return normalize(path, i - 1);
+            }
+            prevC = c;
+        }
+        if (prevC == '/' && len > 1) {
+            return path.substring(0, len - 1);
+        }
+        return path;
+    }
+
+    private static String normalize(String path, int off) {
+        int len = path.length();
+        StringBuilder to = new StringBuilder(len);
+        to.append(path, 0, off);
+        char prevC = 0;
+        while (off < len) {
+            char c = path.charAt(off++);
+            if (c == '\\') {
+                c = '/';
+            }
+            if (c == '/' && prevC == '/') {
+                continue;
+            }
+            if (c == '\u0000') {
+                throw new InvalidPathException(path,
+                        "Path: nul character not allowed");
+            }
+            to.append(c);
+            prevC = c;
+        }
+        len = to.length();
+        if (len > 1 && to.charAt(len - 1) == '/') {
+            to.deleteCharAt(len - 1);
+        }
+        return to.toString();
+    }
+
+    // Remove DotSlash(./) and resolve DotDot (..) components
+    private String getResolved() {
+        if (path.length() == 0) {
+            return path;
+        }
+        if (path.indexOf('.') == -1) {
+            return path;
+        }
+        int length = path.length();
+        char[] to = new char[length];
+        int nc = getNameCount();
+        int[] lastM = new int[nc];
+        int lastMOff = -1;
+        int m = 0;
+        for (int i = 0; i < nc; i++) {
+            int n = offsets[i];
+            int len = (i == offsets.length - 1) ? length - n
+                                                : offsets[i + 1] - n - 1;
+            if (len == 1 && path.charAt(n) == '.') {
+                if (m == 0 && path.charAt(0) == '/')   // absolute path
+                    to[m++] = '/';
+                continue;
+            }
+            if (len == 2 && path.charAt(n) == '.' && path.charAt(n + 1) == '.') {
+                if (lastMOff >= 0) {
+                    m = lastM[lastMOff--];    // retreat
+                    continue;
+                }
+                if (path.charAt(0) == '/') {  // "/../xyz" skip
+                    if (m == 0)
+                        to[m++] = '/';
+                } else {                      // "../xyz" -> "../xyz"
+                    if (m != 0 && to[m-1] != '/')
+                        to[m++] = '/';
+                    while (len-- > 0)
+                        to[m++] = path.charAt(n++);
+                }
+                continue;
+            }
+            if (m == 0 && path.charAt(0) == '/' ||   // absolute path
+                m != 0 && to[m-1] != '/') {   // not the first name
+                to[m++] = '/';
+            }
+            lastM[++lastMOff] = m;
+            while (len-- > 0)
+                to[m++] = path.charAt(n++);
+        }
+        if (m > 1 && to[m - 1] == '/')
+            m--;
+        return (m == to.length) ? new String(to) : new String(to, 0, m);
+    }
+
+    @Override
+    public final String toString() {
+        return path;
+    }
+
+    @Override
+    public final int hashCode() {
+        return path.hashCode();
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        return obj instanceof JrtPath &&
+               this.path.equals(((JrtPath) obj).path);
+    }
+
+    @Override
+    public final int compareTo(Path other) {
+        final JrtPath o = checkPath(other);
+        return path.compareTo(o.path);
+    }
+
+    @Override
+    public final WatchKey register(
+            WatchService watcher,
+            WatchEvent.Kind<?>[] events,
+            WatchEvent.Modifier... modifiers) {
+        Objects.requireNonNull(watcher, "watcher");
+        Objects.requireNonNull(events, "events");
+        Objects.requireNonNull(modifiers, "modifiers");
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) {
+        return register(watcher, events, new WatchEvent.Modifier[0]);
+    }
+
+    @Override
+    public final File toFile() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final Iterator<Path> iterator() {
+        return new Iterator<Path>() {
+            private int i = 0;
+
+            @Override
+            public boolean hasNext() {
+                return (i < getNameCount());
+            }
+
+            @Override
+            public Path next() {
+                if (i < getNameCount()) {
+                    Path result = getName(i);
+                    i++;
+                    return result;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            @Override
+            public void remove() {
+                throw new ReadOnlyFileSystemException();
+            }
+        };
+    }
+
+    // Helpers for JrtFileSystemProvider and JrtFileSystem
+
+    final JrtPath readSymbolicLink() throws IOException {
+        if (!jrtfs.isLink(this)) {
+            throw new IOException("not a symbolic link");
+        }
+        return jrtfs.resolveLink(this);
+    }
+
+    final boolean isHidden() {
+        return false;
+    }
+
+    final void createDirectory(FileAttribute<?>... attrs)
+            throws IOException {
+        jrtfs.createDirectory(this, attrs);
+    }
+
+    final InputStream newInputStream(OpenOption... options) throws IOException {
+        if (options.length > 0) {
+            for (OpenOption opt : options) {
+                if (opt != READ) {
+                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
+                }
+            }
+        }
+        return jrtfs.newInputStream(this);
+    }
+
+    final DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
+            throws IOException {
+        return new JrtDirectoryStream(this, filter);
+    }
+
+    final void delete() throws IOException {
+        jrtfs.deleteFile(this, true);
+    }
+
+    final void deleteIfExists() throws IOException {
+        jrtfs.deleteFile(this, false);
+    }
+
+    final JrtFileAttributes getAttributes(LinkOption... options) throws IOException {
+        JrtFileAttributes zfas = jrtfs.getFileAttributes(this, options);
+        if (zfas == null) {
+            throw new NoSuchFileException(toString());
+        }
+        return zfas;
+    }
+
+    final void setAttribute(String attribute, Object value, LinkOption... options)
+            throws IOException {
+        JrtFileAttributeView.setAttribute(this, attribute, value);
+    }
+
+    final Map<String, Object> readAttributes(String attributes, LinkOption... options)
+            throws IOException {
+        return JrtFileAttributeView.readAttributes(this, attributes, options);
+    }
+
+    final void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
+            throws IOException {
+        jrtfs.setTimes(this, mtime, atime, ctime);
+    }
+
+    final FileStore getFileStore() throws IOException {
+        // each JrtFileSystem only has one root (as requested for now)
+        if (exists()) {
+            return jrtfs.getFileStore(this);
+        }
+        throw new NoSuchFileException(path);
+    }
+
+    final boolean isSameFile(Path other) throws IOException {
+        if (this == other || this.equals(other)) {
+            return true;
+        }
+        if (other == null || this.getFileSystem() != other.getFileSystem()) {
+            return false;
+        }
+        this.checkAccess();
+        JrtPath o = (JrtPath) other;
+        o.checkAccess();
+        return this.getResolvedPath().equals(o.getResolvedPath()) ||
+               jrtfs.isSameFile(this, o);
+    }
+
+    final SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+                                             FileAttribute<?>... attrs)
+            throws IOException
+    {
+        return jrtfs.newByteChannel(this, options, attrs);
+    }
+
+    final FileChannel newFileChannel(Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        return jrtfs.newFileChannel(this, options, attrs);
+    }
+
+    final void checkAccess(AccessMode... modes) throws IOException {
+        if (modes.length == 0) {    // check if the path exists
+            jrtfs.checkNode(this);  // no need to follow link. the "link" node
+                                    // is built from real node under "/module"
+        } else {
+            boolean w = false;
+            for (AccessMode mode : modes) {
+                switch (mode) {
+                    case READ:
+                        break;
+                    case WRITE:
+                        w = true;
+                        break;
+                    case EXECUTE:
+                        throw new AccessDeniedException(toString());
+                    default:
+                        throw new UnsupportedOperationException();
+                }
+            }
+            jrtfs.checkNode(this);
+            if (w && jrtfs.isReadOnly()) {
+                throw new AccessDeniedException(toString());
+            }
+        }
+    }
+
+    final boolean exists() {
+        try {
+            return jrtfs.exists(this);
+        } catch (IOException x) {}
+        return false;
+    }
+
+    final OutputStream newOutputStream(OpenOption... options) throws IOException {
+        if (options.length == 0) {
+            return jrtfs.newOutputStream(this, CREATE_NEW, WRITE);
+        }
+        return jrtfs.newOutputStream(this, options);
+    }
+
+    final void move(JrtPath target, CopyOption... options) throws IOException {
+        if (this.jrtfs == target.jrtfs) {
+            jrtfs.copyFile(true, this, target, options);
+        } else {
+            copyToTarget(target, options);
+            delete();
+        }
+    }
+
+    final void copy(JrtPath target, CopyOption... options) throws IOException {
+        if (this.jrtfs == target.jrtfs) {
+            jrtfs.copyFile(false, this, target, options);
+        } else {
+            copyToTarget(target, options);
+        }
+    }
+
+    private void copyToTarget(JrtPath target, CopyOption... options)
+            throws IOException {
+        boolean replaceExisting = false;
+        boolean copyAttrs = false;
+        for (CopyOption opt : options) {
+            if (opt == REPLACE_EXISTING) {
+                replaceExisting = true;
+            } else if (opt == COPY_ATTRIBUTES) {
+                copyAttrs = true;
+            }
+        }
+        // attributes of source file
+        BasicFileAttributes jrtfas = getAttributes();
+        // check if target exists
+        boolean exists;
+        if (replaceExisting) {
+            try {
+                target.deleteIfExists();
+                exists = false;
+            } catch (DirectoryNotEmptyException x) {
+                exists = true;
+            }
+        } else {
+            exists = target.exists();
+        }
+        if (exists) {
+            throw new FileAlreadyExistsException(target.toString());
+        }
+        if (jrtfas.isDirectory()) {
+            // create directory or file
+            target.createDirectory();
+        } else {
+            try (InputStream is = jrtfs.newInputStream(this);
+                 OutputStream os = target.newOutputStream()) {
+                byte[] buf = new byte[8192];
+                int n;
+                while ((n = is.read(buf)) != -1) {
+                    os.write(buf, 0, n);
+                }
+            }
+        }
+        if (copyAttrs) {
+            BasicFileAttributeView view =
+                Files.getFileAttributeView(target, BasicFileAttributeView.class);
+            try {
+                view.setTimes(jrtfas.lastModifiedTime(),
+                              jrtfas.lastAccessTime(),
+                              jrtfas.creationTime());
+            } catch (IOException x) {
+                try {
+                    target.delete();  // rollback?
+                } catch (IOException ignore) {}
+                throw x;
+            }
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java	Fri Apr 22 01:04:01 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PrivilegedAction;
+
+import jdk.internal.jimage.ImageReader;
+import jdk.internal.jimage.ImageReader.Node;
+
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+abstract class SystemImage {
+
+    abstract Node findNode(String path);
+    abstract byte[] getResource(Node node) throws IOException;
+    abstract void close() throws IOException;
+
+    static SystemImage open() throws IOException {
+        if (modulesImageExists) {
+            // open a .jimage and build directory structure
+            final ImageReader image = ImageReader.open(moduleImageFile);
+            image.getRootDirectory();
+            retur