changeset 14206:b41d8ad46db8

Merge
author amurillo
date Mon, 18 Apr 2016 15:39:47 -0700
parents 4b78af87def9 dfe21904a466
children d094de1b933d
files make/mapfiles/libjava/mapfile-vers src/java.base/share/classes/java/lang/StackStreamFactory.java 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.rmic/share/classes/jdk/rmi/rmic/Main.java test/java/lang/StackWalker/DumpStackTest.java test/java/lang/StackWalker/StackWalkTest.java test/java/lang/StackWalker/VerifyStackTrace.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 317 files changed, 22698 insertions(+), 14656 deletions(-) [+]
line wrap: on
line diff
--- a/make/launcher/Launcher-jdk.rmic.gmk	Thu Apr 14 19:55:41 2016 -0700
+++ b/make/launcher/Launcher-jdk.rmic.gmk	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/make/mapfiles/libjava/mapfile-vers	Mon Apr 18 15:39:47 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/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Mon Apr 18 15:39:47 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/java/io/ObjectStreamClass.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/io/ObjectStreamField.java	Mon Apr 18 15:39:47 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/lang/Class.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/Class.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Mon Apr 18 15:39:47 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;
 
--- a/src/java.base/share/classes/java/lang/Math.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/Math.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/Package.java	Mon Apr 18 15:39:47 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;
 
 
 /**
--- a/src/java.base/share/classes/java/lang/Runtime.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/Runtime.java	Mon Apr 18 15:39:47 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
--- a/src/java.base/share/classes/java/lang/SecurityManager.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/SecurityManager.java	Mon Apr 18 15:39:47 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;
 
 /**
--- a/src/java.base/share/classes/java/lang/StackStreamFactory.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java	Mon Apr 18 15:39:47 2016 -0700
@@ -24,6 +24,7 @@
  */
 package java.lang;
 
+import jdk.internal.reflect.MethodAccessor;
 import java.lang.StackWalker.Option;
 import java.lang.StackWalker.StackFrame;
 
@@ -978,13 +979,13 @@
     }
 
     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");
     }
 
--- a/src/java.base/share/classes/java/lang/StackWalker.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/StackWalker.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/StrictMath.java	Mon Apr 18 15:39:47 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/System.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/System.java	Mon Apr 18 15:39:47 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;
@@ -1978,7 +1978,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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/Thread.java	Mon Apr 18 15:39:47 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;
 
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Apr 18 15:39:47 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/MethodHandleProxies.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java	Mon Apr 18 15:39:47 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/MethodHandles.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Apr 18 15:39:47 2016 -0700
@@ -37,8 +37,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;
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Field.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Method.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Modifier.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Module.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Mon Apr 18 15:39:47 2016 -0700
@@ -47,8 +47,8 @@
 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.util.SecurityConstants;
 
--- a/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/ReflectAccess.java	Mon Apr 18 15:39:47 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/InetAddress.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/net/InetAddress.java	Mon Apr 18 15:39:47 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;
--- a/src/java.base/share/classes/java/security/AccessController.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/security/AccessController.java	Mon Apr 18 15:39:47 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/util/ResourceBundle.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/util/ResourceBundle.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java	Mon Apr 18 15:39:47 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/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Mon Apr 18 15:39:47 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/jdk/internal/jimage/ImageReader.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ /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 14 19:55:41 2016 -0700
+++ /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 14 19:55:41 2016 -0700
+++ /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	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ /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 14 19:55:41 2016 -0700
+++ /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 14 19:55:41 2016 -0700
+++ /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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java	Mon Apr 18 15:39:47 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 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java	Mon Apr 18 15:39:47 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	Mon Apr 18 15:39:47 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();
+            return new SystemImage() {
+                @Override
+                Node findNode(String path) {
+                    return image.findNode(path);
+                }
+                @Override
+                byte[] getResource(Node node) throws IOException {
+                    return image.getResource(node);
+                }
+                @Override
+                void close() throws IOException {
+                    image.close();
+                }
+            };
+        }
+        if (Files.notExists(explodedModulesDir))
+            throw new FileSystemNotFoundException(explodedModulesDir.toString());
+        return new ExplodedImage(explodedModulesDir);
+    }
+
+    static final String RUNTIME_HOME;
+    // "modules" jimage file Path
+    final static Path moduleImageFile;
+    // "modules" jimage exists or not?
+    final static boolean modulesImageExists;
+    // <JAVA_HOME>/modules directory Path
+    static final Path explodedModulesDir;
+
+    static {
+        PrivilegedAction<String> pa = SystemImage::findHome;
+        RUNTIME_HOME = AccessController.doPrivileged(pa);
+
+        FileSystem fs = FileSystems.getDefault();
+        moduleImageFile = fs.getPath(RUNTIME_HOME, "lib", "modules");
+        explodedModulesDir = fs.getPath(RUNTIME_HOME, "modules");
+
+        modulesImageExists = AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>() {
+                @Override
+                public Boolean run() {
+                    return Files.isRegularFile(moduleImageFile);
+                }
+            });
+    }
+
+    /**
+     * Returns the appropriate JDK home for this usage of the FileSystemProvider.
+     * When the CodeSource is null (null loader) then jrt:/ is the current runtime,
+     * otherwise the JDK home is located relative to jrt-fs.jar.
+     */
+    private static String findHome() {
+        CodeSource cs = SystemImage.class.getProtectionDomain().getCodeSource();
+        if (cs == null)
+            return System.getProperty("java.home");
+
+        // assume loaded from $TARGETJDK/jrt-fs.jar
+        URL url = cs.getLocation();
+        if (!url.getProtocol().equalsIgnoreCase("file"))
+            throw new RuntimeException(url + " loaded in unexpected way");
+        try {
+            return Paths.get(url.toURI()).getParent().toString();
+        } catch (URISyntaxException e) {
+            throw new InternalError(e);
+        }
+    }
+}
--- a/src/java.base/share/classes/jdk/internal/jrtfs/SystemImages.java	Thu Apr 14 19:55:41 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * 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.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.Path;
-import java.nio.file.Paths;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.PrivilegedAction;
-
-/**
- * @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 SystemImages {
-    private SystemImages() {}
-
-
-    static final String RUNTIME_HOME;
-    // "modules" jimage file Path
-    private static final Path moduleImageFile;
-    // "modules" jimage exists or not?
-    private static final boolean modulesImageExists;
-    // <JAVA_HOME>/modules directory Path
-    private static final Path explodedModulesDir;
-
-    static {
-        PrivilegedAction<String> pa = SystemImages::findHome;
-        RUNTIME_HOME = AccessController.doPrivileged(pa);
-
-        FileSystem fs = FileSystems.getDefault();
-        moduleImageFile = fs.getPath(RUNTIME_HOME, "lib", "modules");
-        explodedModulesDir = fs.getPath(RUNTIME_HOME, "modules");
-
-        modulesImageExists = AccessController.doPrivileged(
-            new PrivilegedAction<Boolean>() {
-                @Override
-                public Boolean run() {
-                    return Files.isRegularFile(moduleImageFile);
-                }
-            });
-    }
-
-    static boolean hasModulesImage() {
-        return modulesImageExists;
-    }
-
-    static Path moduleImageFile() {
-        return moduleImageFile;
-    }
-
-    static Path explodedModulesDir() {
-        return explodedModulesDir;
-    }
-
-    /**
-     * Returns the appropriate JDK home for this usage of the FileSystemProvider.
-     * When the CodeSource is null (null loader) then jrt:/ is the current runtime,
-     * otherwise the JDK home is located relative to jrt-fs.jar.
-     */
-    private static String findHome() {
-        CodeSource cs = SystemImages.class.getProtectionDomain().getCodeSource();
-        if (cs == null)
-            return System.getProperty("java.home");
-
-        // assume loaded from $TARGETJDK/jrt-fs.jar
-        URL url = cs.getLocation();
-        if (!url.getProtocol().equalsIgnoreCase("file"))
-            throw new RuntimeException(url + " loaded in unexpected way");
-        try {
-            return Paths.get(url.toURI()).getParent().toString();
-        } catch (URISyntaxException e) {
-            throw new InternalError(e);
-        }
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Mon Apr 18 15:39:47 2016 -0700
@@ -37,7 +37,7 @@
 import java.util.stream.Stream;
 
 import jdk.internal.module.ServicesCatalog;
-import sun.reflect.ConstantPool;
+import jdk.internal.reflect.ConstantPool;
 import sun.reflect.annotation.AnnotationType;
 import sun.nio.ch.Interruptible;
 
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Mon Apr 18 15:39:47 2016 -0700
@@ -28,8 +28,8 @@
 import java.lang.reflect.Field;
 import java.security.ProtectionDomain;
 
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 import jdk.internal.misc.VM;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
@@ -58,7 +58,7 @@
     private static native void registerNatives();
     static {
         registerNatives();
-        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
+        Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
     }
 
     private Unsafe() {}
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingAnnotationAdapter.java	Mon Apr 18 15:39:47 2016 -0700
@@ -65,10 +65,10 @@
 /**
  * An {@link AnnotationVisitor} adapter for type remapping.
  *
- * //@deprecated use {@link AnnotationRemapper} instead.
+ * @deprecated use {@link AnnotationRemapper} instead.
  * @author Eugene Kuleshov
  */
-//@Deprecated
+@Deprecated
 public class RemappingAnnotationAdapter extends AnnotationVisitor {
 
     protected final Remapper remapper;
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java	Thu Apr 14 19:55:41 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java	Mon Apr 18 15:39:47 2016 -0700
@@ -69,10 +69,10 @@
 /**
  * A {@link LocalVariablesSorter} for type mapping.
  *
- * //@deprecated use {@link MethodRemapper} instead.
+ * @deprecated use {@link MethodRemapper} instead.
  * @author Eugene Kuleshov
  */
-//@Deprecated
+@Deprecated
 public class RemappingMethodAdapter extends LocalVariablesSorter {
 
     protected final Remapper remapper;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/AccessorGenerator.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 2001, 2013, 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.reflect;
+
+import java.lang.reflect.*;
+import jdk.internal.misc.Unsafe;
+
+/** Shared functionality for all accessor generators */
+
+class AccessorGenerator implements ClassFileConstants {
+    static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    // Constants because there's no way to say "short integer constant",
+    // i.e., "1S"
+    protected static final short S0 = (short) 0;
+    protected static final short S1 = (short) 1;
+    protected static final short S2 = (short) 2;
+    protected static final short S3 = (short) 3;
+    protected static final short S4 = (short) 4;
+    protected static final short S5 = (short) 5;
+    protected static final short S6 = (short) 6;
+
+    // Instance variables for shared functionality between
+    // FieldAccessorGenerator and MethodAccessorGenerator
+    protected ClassFileAssembler asm;
+    protected int   modifiers;
+    protected short thisClass;
+    protected short superClass;
+    protected short targetClass;
+    // Common constant pool entries to FieldAccessor and MethodAccessor
+    protected short throwableClass;
+    protected short classCastClass;
+    protected short nullPointerClass;
+    protected short illegalArgumentClass;
+    protected short invocationTargetClass;
+    protected short initIdx;
+    protected short initNameAndTypeIdx;
+    protected short initStringNameAndTypeIdx;
+    protected short nullPointerCtorIdx;
+    protected short illegalArgumentCtorIdx;
+    protected short illegalArgumentStringCtorIdx;
+    protected short invocationTargetCtorIdx;
+    protected short superCtorIdx;
+    protected short objectClass;
+    protected short toStringIdx;
+    protected short codeIdx;
+    protected short exceptionsIdx;
+    // Boxing
+    protected short valueOfIdx;
+    protected short booleanIdx;
+    protected short booleanBoxIdx;
+    protected short booleanUnboxIdx;
+    protected short byteIdx;
+    protected short byteBoxIdx;
+    protected short byteUnboxIdx;
+    protected short characterIdx;
+    protected short characterBoxIdx;
+    protected short characterUnboxIdx;
+    protected short doubleIdx;
+    protected short doubleBoxIdx;
+    protected short doubleUnboxIdx;
+    protected short floatIdx;
+    protected short floatBoxIdx;
+    protected short floatUnboxIdx;
+    protected short integerIdx;
+    protected short integerBoxIdx;
+    protected short integerUnboxIdx;
+    protected short longIdx;
+    protected short longBoxIdx;
+    protected short longUnboxIdx;
+    protected short shortIdx;
+    protected short shortBoxIdx;
+    protected short shortUnboxIdx;
+
+    protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30;
+    protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 73;
+
+    // Requires that superClass has been set up
+    protected void emitCommonConstantPoolEntries() {
+        // +   [UTF-8] "java/lang/Throwable"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/ClassCastException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/NullPointerException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/IllegalArgumentException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/InvocationTargetException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "<init>"
+        // +   [UTF-8] "()V"
+        // +   [CONSTANT_NameAndType_info] for above
+        // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
+        // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
+        // +   [UTF-8] "(Ljava/lang/String;)V"
+        // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
+        // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
+        // +   [UTF-8] "(Ljava/lang/Throwable;)V"
+        // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
+        // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
+        // +   [CONSTANT_Methodref_info] for "super()"
+        // +   [UTF-8] "java/lang/Object"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "toString"
+        // +   [UTF-8] "()Ljava/lang/String;"
+        // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
+        // +   [CONSTANT_Methodref_info] for Object's toString method
+        // +   [UTF-8] "Code"
+        // +   [UTF-8] "Exceptions"
+        asm.emitConstantPoolUTF8("java/lang/Throwable");
+        asm.emitConstantPoolClass(asm.cpi());
+        throwableClass = asm.cpi();
+        asm.emitConstantPoolUTF8("java/lang/ClassCastException");
+        asm.emitConstantPoolClass(asm.cpi());
+        classCastClass = asm.cpi();
+        asm.emitConstantPoolUTF8("java/lang/NullPointerException");
+        asm.emitConstantPoolClass(asm.cpi());
+        nullPointerClass = asm.cpi();
+        asm.emitConstantPoolUTF8("java/lang/IllegalArgumentException");
+        asm.emitConstantPoolClass(asm.cpi());
+        illegalArgumentClass = asm.cpi();
+        asm.emitConstantPoolUTF8("java/lang/reflect/InvocationTargetException");
+        asm.emitConstantPoolClass(asm.cpi());
+        invocationTargetClass = asm.cpi();
+        asm.emitConstantPoolUTF8("<init>");
+        initIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("()V");
+        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        initNameAndTypeIdx = asm.cpi();
+        asm.emitConstantPoolMethodref(nullPointerClass, initNameAndTypeIdx);
+        nullPointerCtorIdx = asm.cpi();
+        asm.emitConstantPoolMethodref(illegalArgumentClass, initNameAndTypeIdx);
+        illegalArgumentCtorIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(Ljava/lang/String;)V");
+        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        initStringNameAndTypeIdx = asm.cpi();
+        asm.emitConstantPoolMethodref(illegalArgumentClass, initStringNameAndTypeIdx);
+        illegalArgumentStringCtorIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(Ljava/lang/Throwable;)V");
+        asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(invocationTargetClass, asm.cpi());
+        invocationTargetCtorIdx = asm.cpi();
+        asm.emitConstantPoolMethodref(superClass, initNameAndTypeIdx);
+        superCtorIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("java/lang/Object");
+        asm.emitConstantPoolClass(asm.cpi());
+        objectClass = asm.cpi();
+        asm.emitConstantPoolUTF8("toString");
+        asm.emitConstantPoolUTF8("()Ljava/lang/String;");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(objectClass, asm.cpi());
+        toStringIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("Code");
+        codeIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("Exceptions");
+        exceptionsIdx = asm.cpi();
+    }
+
+    /** Constant pool entries required to be able to box/unbox primitive
+        types. Note that we don't emit these if we don't need them. */
+    protected void emitBoxingContantPoolEntries() {
+        //  *  [UTF-8] "valueOf"
+        //  *  [UTF-8] "java/lang/Boolean"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(Z)Ljava/lang/Boolean;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "booleanValue"
+        //  *  [UTF-8] "()Z"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Byte"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(B)Ljava/lang/Byte;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "byteValue"
+        //  *  [UTF-8] "()B"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Character"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(C)Ljava/lang/Character;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "charValue"
+        //  *  [UTF-8] "()C"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Double"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(D)Ljava/lang/Double;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "doubleValue"
+        //  *  [UTF-8] "()D"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Float"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(F)Ljava/lang/Float;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "floatValue"
+        //  *  [UTF-8] "()F"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Integer"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(I)Ljava/lang/Integer;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "intValue"
+        //  *  [UTF-8] "()I"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Long"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(J)Ljava/lang/Long;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "longValue"
+        //  *  [UTF-8] "()J"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "java/lang/Short"
+        //  *  [CONSTANT_Class_info] for above
+        //  *  [UTF-8] "(S)Ljava/lang/Short;"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+        //  *  [UTF-8] "shortValue"
+        //  *  [UTF-8] "()S"
+        //  *  [CONSTANT_NameAndType_info] for above
+        //  *  [CONSTANT_Methodref_info] for above
+
+        // valueOf-method name
+        asm.emitConstantPoolUTF8("valueOf");
+        valueOfIdx = asm.cpi();
+
+        // Boolean
+        asm.emitConstantPoolUTF8("java/lang/Boolean");
+        asm.emitConstantPoolClass(asm.cpi());
+        booleanIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(Z)Ljava/lang/Boolean;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        booleanBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("booleanValue");
+        asm.emitConstantPoolUTF8("()Z");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        booleanUnboxIdx = asm.cpi();
+
+        // Byte
+        asm.emitConstantPoolUTF8("java/lang/Byte");
+        asm.emitConstantPoolClass(asm.cpi());
+        byteIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(B)Ljava/lang/Byte;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        byteBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("byteValue");
+        asm.emitConstantPoolUTF8("()B");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        byteUnboxIdx = asm.cpi();
+
+        // Character
+        asm.emitConstantPoolUTF8("java/lang/Character");
+        asm.emitConstantPoolClass(asm.cpi());
+        characterIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(C)Ljava/lang/Character;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        characterBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("charValue");
+        asm.emitConstantPoolUTF8("()C");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        characterUnboxIdx = asm.cpi();
+
+        // Double
+        asm.emitConstantPoolUTF8("java/lang/Double");
+        asm.emitConstantPoolClass(asm.cpi());
+        doubleIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(D)Ljava/lang/Double;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        doubleBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("doubleValue");
+        asm.emitConstantPoolUTF8("()D");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        doubleUnboxIdx = asm.cpi();
+
+        // Float
+        asm.emitConstantPoolUTF8("java/lang/Float");
+        asm.emitConstantPoolClass(asm.cpi());
+        floatIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(F)Ljava/lang/Float;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        floatBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("floatValue");
+        asm.emitConstantPoolUTF8("()F");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        floatUnboxIdx = asm.cpi();
+
+        // Integer
+        asm.emitConstantPoolUTF8("java/lang/Integer");
+        asm.emitConstantPoolClass(asm.cpi());
+        integerIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(I)Ljava/lang/Integer;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        integerBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("intValue");
+        asm.emitConstantPoolUTF8("()I");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        integerUnboxIdx = asm.cpi();
+
+        // Long
+        asm.emitConstantPoolUTF8("java/lang/Long");
+        asm.emitConstantPoolClass(asm.cpi());
+        longIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(J)Ljava/lang/Long;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        longBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("longValue");
+        asm.emitConstantPoolUTF8("()J");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        longUnboxIdx = asm.cpi();
+
+        // Short
+        asm.emitConstantPoolUTF8("java/lang/Short");
+        asm.emitConstantPoolClass(asm.cpi());
+        shortIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("(S)Ljava/lang/Short;");
+        asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
+        shortBoxIdx = asm.cpi();
+        asm.emitConstantPoolUTF8("shortValue");
+        asm.emitConstantPoolUTF8("()S");
+        asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
+        asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
+        shortUnboxIdx = asm.cpi();
+    }
+
+    // Necessary because of Java's annoying promotion rules
+    protected static short add(short s1, short s2) {
+        return (short) (s1 + s2);
+    }
+
+    protected static short sub(short s1, short s2) {
+        return (short) (s1 - s2);
+    }
+
+    protected boolean isStatic() {
+        return Modifier.isStatic(modifiers);
+    }
+
+    protected boolean isPrivate() {
+        return Modifier.isPrivate(modifiers);
+    }
+
+    /** Returns class name in "internal" form (i.e., '/' separators
+        instead of '.') */
+    protected static String getClassName
+        (Class<?> c, boolean addPrefixAndSuffixForNonPrimitiveTypes)
+    {
+        if (c.isPrimitive()) {
+            if (c == Boolean.TYPE) {
+                return "Z";
+            } else if (c == Byte.TYPE) {
+                return "B";
+            } else if (c == Character.TYPE) {
+                return "C";
+            } else if (c == Double.TYPE) {
+                return "D";
+            } else if (c == Float.TYPE) {
+                return "F";
+            } else if (c == Integer.TYPE) {
+                return "I";
+            } else if (c == Long.TYPE) {
+                return "J";
+            } else if (c == Short.TYPE) {
+                return "S";
+            } else if (c == Void.TYPE) {
+                return "V";
+            }
+            throw new InternalError("Should have found primitive type");
+        } else if (c.isArray()) {
+            return "[" + getClassName(c.getComponentType(), true);
+        } else {
+            if (addPrefixAndSuffixForNonPrimitiveTypes) {
+                return internalize("L" + c.getName() + ";");
+            } else {
+                return internalize(c.getName());
+            }
+        }
+    }
+
+    private static String internalize(String className) {
+        return className.replace('.', '/');
+    }
+
+    protected void emitConstructor() {
+        // Generate code into fresh code buffer
+        ClassFileAssembler cb = new ClassFileAssembler();
+        // 0 incoming arguments
+        cb.setMaxLocals(1);
+        cb.opc_aload_0();
+        cb.opc_invokespecial(superCtorIdx, 0, 0);
+        cb.opc_return();
+
+        // Emit method
+        emitMethod(initIdx, cb.getMaxLocals(), cb, null, null);
+    }
+
+    // The descriptor's index in the constant pool must be (1 +
+    // nameIdx). "numArgs" must indicate ALL arguments, including the
+    // implicit "this" argument; double and long arguments each count
+    // as 2 in this count. The code buffer must NOT contain the code
+    // length. The exception table may be null, but if non-null must
+    // NOT contain the exception table's length. The checked exception
+    // indices may be null.
+    protected void emitMethod(short nameIdx,
+                              int numArgs,
+                              ClassFileAssembler code,
+                              ClassFileAssembler exceptionTable,
+                              short[] checkedExceptionIndices)
+    {
+        int codeLen = code.getLength();
+        int excLen  = 0;
+        if (exceptionTable != null) {
+            excLen = exceptionTable.getLength();
+            if ((excLen % 8) != 0) {
+                throw new IllegalArgumentException("Illegal exception table");
+            }
+        }
+        int attrLen = 12 + codeLen + excLen;
+        excLen = excLen / 8; // No-op if no exception table
+
+        asm.emitShort(ACC_PUBLIC);
+        asm.emitShort(nameIdx);
+        asm.emitShort(add(nameIdx, S1));
+        if (checkedExceptionIndices == null) {
+            // Code attribute only
+            asm.emitShort(S1);
+        } else {
+            // Code and Exceptions attributes
+            asm.emitShort(S2);
+        }
+        // Code attribute
+        asm.emitShort(codeIdx);
+        asm.emitInt(attrLen);
+        asm.emitShort(code.getMaxStack());
+        asm.emitShort((short) Math.max(numArgs, code.getMaxLocals()));
+        asm.emitInt(codeLen);
+        asm.append(code);
+        asm.emitShort((short) excLen);
+        if (exceptionTable != null) {
+            asm.append(exceptionTable);
+        }
+        asm.emitShort(S0); // No additional attributes for Code attribute
+        if (checkedExceptionIndices != null) {
+            // Exceptions attribute
+            asm.emitShort(exceptionsIdx);
+            asm.emitInt(2 + 2 * checkedExceptionIndices.length);
+            asm.emitShort((short) checkedExceptionIndices.length);
+            for (int i = 0; i < checkedExceptionIndices.length; i++) {
+                asm.emitShort(checkedExceptionIndices[i]);
+            }
+        }
+    }
+
+    protected short indexForPrimitiveType(Class<?> type) {
+        if (type == Boolean.TYPE) {
+            return booleanIdx;
+        } else if (type == Byte.TYPE) {
+            return byteIdx;
+        } else if (type == Character.TYPE) {
+            return characterIdx;
+        } else if (type == Double.TYPE) {
+            return doubleIdx;
+        } else if (type == Float.TYPE) {
+            return floatIdx;
+        } else if (type == Integer.TYPE) {
+            return integerIdx;
+        } else if (type == Long.TYPE) {
+            return longIdx;
+        } else if (type == Short.TYPE) {
+            return shortIdx;
+        }
+        throw new InternalError("Should have found primitive type");
+    }
+
+    protected short boxingMethodForPrimitiveType(Class<?> type) {
+        if (type == Boolean.TYPE) {
+            return booleanBoxIdx;
+        } else if (type == Byte.TYPE) {
+            return byteBoxIdx;
+        } else if (type == Character.TYPE) {
+            return characterBoxIdx;
+        } else if (type == Double.TYPE) {
+            return doubleBoxIdx;
+        } else if (type == Float.TYPE) {
+            return floatBoxIdx;
+        } else if (type == Integer.TYPE) {
+            return integerBoxIdx;
+        } else if (type == Long.TYPE) {
+            return longBoxIdx;
+        } else if (type == Short.TYPE) {
+            return shortBoxIdx;
+        }
+        throw new InternalError("Should have found primitive type");
+    }
+
+    /** Returns true for widening or identity conversions for primitive
+        types only */
+    protected static boolean canWidenTo(Class<?> type, Class<?> otherType) {
+        if (!type.isPrimitive()) {
+            return false;
+        }
+
+        // Widening conversions (from JVM spec):
+        //  byte to short, int, long, float, or double
+        //  short to int, long, float, or double
+        //  char to int, long, float, or double
+        //  int to long, float, or double
+        //  long to float or double
+        //  float to double
+
+        if (type == Boolean.TYPE) {
+            if (otherType == Boolean.TYPE) {
+                return true;
+            }
+        } else if (type == Byte.TYPE) {
+            if (   otherType == Byte.TYPE
+                   || otherType == Short.TYPE
+                   || otherType == Integer.TYPE
+                   || otherType == Long.TYPE
+                   || otherType == Float.TYPE
+                   || otherType == Double.TYPE) {
+                return true;
+            }
+        } else if (type == Short.TYPE) {
+            if (   otherType == Short.TYPE
+                   || otherType == Integer.TYPE
+                   || otherType == Long.TYPE
+                   || otherType == Float.TYPE
+                   || otherType == Double.TYPE) {
+                return true;
+            }
+        } else if (type == Character.TYPE) {
+            if (   otherType == Character.TYPE
+                   || otherType == Integer.TYPE
+                   || otherType == Long.TYPE
+                   || otherType == Float.TYPE
+                   || otherType == Double.TYPE) {
+                return true;
+            }
+        } else if (type == Integer.TYPE) {
+            if (   otherType == Integer.TYPE
+                   || otherType == Long.TYPE
+                   || otherType == Float.TYPE
+                   || otherType == Double.TYPE) {
+                return true;
+            }
+        } else if (type == Long.TYPE) {
+            if (   otherType == Long.TYPE
+                   || otherType == Float.TYPE
+                   || otherType == Double.TYPE) {
+                return true;
+            }
+        } else if (type == Float.TYPE) {
+            if (   otherType == Float.TYPE
+                   || otherType == Double.TYPE) {
+                return true;
+            }
+        } else if (type == Double.TYPE) {
+            if (otherType == Double.TYPE) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /** Emits the widening bytecode for the given primitive conversion
+        (or none if the identity conversion). Requires that a primitive
+        conversion exists; i.e., canWidenTo must have already been
+        called and returned true. */
+    protected static void emitWideningBytecodeForPrimitiveConversion
+        (ClassFileAssembler cb,
+         Class<?> fromType,
+         Class<?> toType)
+    {
+        // Note that widening conversions for integral types (i.e., "b2s",
+        // "s2i") are no-ops since values on the Java stack are
+        // sign-extended.
+
+        // Widening conversions (from JVM spec):
+        //  byte to short, int, long, float, or double
+        //  short to int, long, float, or double
+        //  char to int, long, float, or double
+        //  int to long, float, or double
+        //  long to float or double
+        //  float to double
+
+        if (   fromType == Byte.TYPE
+               || fromType == Short.TYPE
+               || fromType == Character.TYPE
+               || fromType == Integer.TYPE) {
+            if (toType == Long.TYPE) {
+                cb.opc_i2l();
+            } else if (toType == Float.TYPE) {
+                cb.opc_i2f();
+            } else if (toType == Double.TYPE) {
+                cb.opc_i2d();
+            }
+        } else if (fromType == Long.TYPE) {
+            if (toType == Float.TYPE) {
+                cb.opc_l2f();
+            } else if (toType == Double.TYPE) {
+                cb.opc_l2d();
+            }
+        } else if (fromType == Float.TYPE) {
+            if (toType == Double.TYPE) {
+                cb.opc_f2d();
+            }
+        }
+
+        // Otherwise, was identity or no-op conversion. Fall through.
+    }
+
+    protected short unboxingMethodForPrimitiveType(Class<?> primType) {
+        if (primType == Boolean.TYPE) {
+            return booleanUnboxIdx;
+        } else if (primType == Byte.TYPE) {
+            return byteUnboxIdx;
+        } else if (primType == Character.TYPE) {
+            return characterUnboxIdx;
+        } else if (primType == Short.TYPE) {
+            return shortUnboxIdx;
+        } else if (primType == Integer.TYPE) {
+            return integerUnboxIdx;
+        } else if (primType == Long.TYPE) {
+            return longUnboxIdx;
+        } else if (primType == Float.TYPE) {
+            return floatUnboxIdx;
+        } else if (primType == Double.TYPE) {
+            return doubleUnboxIdx;
+        }
+        throw new InternalError("Illegal primitive type " + primType.getName());
+    }
+
+    protected static final Class<?>[] primitiveTypes = new Class<?>[] {
+        Boolean.TYPE,
+        Byte.TYPE,
+        Character.TYPE,
+        Short.TYPE,
+        Integer.TYPE,
+        Long.TYPE,
+        Float.TYPE,
+        Double.TYPE
+    };
+
+    /** We don't consider "Void" to be a primitive type */
+    protected static boolean isPrimitive(Class<?> c) {
+        return (c.isPrimitive() && c != Void.TYPE);
+    }
+
+    protected int typeSizeInStackSlots(Class<?> c) {
+        if (c == Void.TYPE) {
+            return 0;
+        }
+        if (c == Long.TYPE || c == Double.TYPE) {
+            return 2;
+        }
+        return 1;
+    }
+
+    private ClassFileAssembler illegalArgumentCodeBuffer;
+    protected ClassFileAssembler illegalArgumentCodeBuffer() {
+        if (illegalArgumentCodeBuffer == null) {
+            illegalArgumentCodeBuffer = new ClassFileAssembler();
+            illegalArgumentCodeBuffer.opc_new(illegalArgumentClass);
+            illegalArgumentCodeBuffer.opc_dup();
+            illegalArgumentCodeBuffer.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
+            illegalArgumentCodeBuffer.opc_athrow();
+        }
+
+        return illegalArgumentCodeBuffer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/BootstrapConstructorAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001, 2011, 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.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+
+/** Uses Unsafe.allocateObject() to instantiate classes; only used for
+    bootstrapping. */
+
+class BootstrapConstructorAccessorImpl extends ConstructorAccessorImpl {
+    private final Constructor<?> constructor;
+
+    BootstrapConstructorAccessorImpl(Constructor<?> c) {
+        this.constructor = c;
+    }
+
+    public Object newInstance(Object[] args)
+        throws IllegalArgumentException, InvocationTargetException
+    {
+        try {
+            return UnsafeFieldAccessorImpl.unsafe.
+                allocateInstance(constructor.getDeclaringClass());
+        } catch (InstantiationException e) {
+            throw new InvocationTargetException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ByteVector.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+/** A growable array of bytes. */
+
+interface ByteVector {
+    public int  getLength();
+    public byte get(int index);
+    public void put(int index, byte value);
+    public void add(byte value);
+    public void trim();
+    public byte[] getData();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ByteVectorFactory.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+class ByteVectorFactory {
+    static ByteVector create() {
+        return new ByteVectorImpl();
+    }
+
+    static ByteVector create(int sz) {
+        return new ByteVectorImpl(sz);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ByteVectorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+class ByteVectorImpl implements ByteVector {
+    private byte[] data;
+    private int pos;
+
+    public ByteVectorImpl() {
+        this(100);
+    }
+
+    public ByteVectorImpl(int sz) {
+        data = new byte[sz];
+        pos = -1;
+    }
+
+    public int getLength() {
+        return pos + 1;
+    }
+
+    public byte get(int index) {
+        if (index >= data.length) {
+            resize(index);
+            pos = index;
+        }
+        return data[index];
+    }
+
+    public void put(int index, byte value) {
+        if (index >= data.length) {
+            resize(index);
+            pos = index;
+        }
+        data[index] = value;
+    }
+
+    public void add(byte value) {
+        if (++pos >= data.length) {
+            resize(pos);
+        }
+        data[pos] = value;
+    }
+
+    public void trim() {
+        if (pos != data.length - 1) {
+            byte[] newData = new byte[pos + 1];
+            System.arraycopy(data, 0, newData, 0, pos + 1);
+            data = newData;
+        }
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    private void resize(int minSize) {
+        if (minSize <= 2 * data.length) {
+            minSize = 2 * data.length;
+        }
+        byte[] newData = new byte[minSize];
+        System.arraycopy(data, 0, newData, 0, data.length);
+        data = newData;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/CallerSensitive.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, 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.reflect;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+/**
+ * A method annotated @CallerSensitive is sensitive to its calling class,
+ * via {@link jdk.internal.reflect.Reflection#getCallerClass Reflection.getCallerClass},
+ * or via some equivalent.
+ *
+ * @author John R. Rose
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({METHOD})
+public @interface CallerSensitive {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ClassDefiner.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2001, 2011, 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.reflect;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import jdk.internal.misc.Unsafe;
+
+/** Utility class which assists in calling Unsafe.defineClass() by
+    creating a new class loader which delegates to the one needed in
+    order for proper resolution of the given bytecodes to occur. */
+
+class ClassDefiner {
+    static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    /** <P> We define generated code into a new class loader which
+      delegates to the defining loader of the target class. It is
+      necessary for the VM to be able to resolve references to the
+      target class from the generated bytecodes, which could not occur
+      if the generated code was loaded into the bootstrap class
+      loader. </P>
+
+      <P> There are two primary reasons for creating a new loader
+      instead of defining these bytecodes directly into the defining
+      loader of the target class: first, it avoids any possible
+      security risk of having these bytecodes in the same loader.
+      Second, it allows the generated bytecodes to be unloaded earlier
+      than would otherwise be possible, decreasing run-time
+      footprint. </P>
+    */
+    static Class<?> defineClass(String name, byte[] bytes, int off, int len,
+                                final ClassLoader parentClassLoader)
+    {
+        ClassLoader newLoader = AccessController.doPrivileged(
+            new PrivilegedAction<ClassLoader>() {
+                public ClassLoader run() {
+                        return new DelegatingClassLoader(parentClassLoader);
+                    }
+                });
+        return unsafe.defineClass(name, bytes, off, len, newLoader, null);
+    }
+}
+
+
+// NOTE: this class's name and presence are known to the virtual
+// machine as of the fix for 4474172.
+class DelegatingClassLoader extends ClassLoader {
+    DelegatingClassLoader(ClassLoader parent) {
+        super(parent);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ClassFileAssembler.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2001, 2004, 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.reflect;
+
+class ClassFileAssembler implements ClassFileConstants {
+    private ByteVector vec;
+    private short cpIdx = 0;
+
+    public ClassFileAssembler() {
+        this(ByteVectorFactory.create());
+    }
+
+    public ClassFileAssembler(ByteVector vec) {
+        this.vec = vec;
+    }
+
+    public ByteVector getData() {
+        return vec;
+    }
+
+    /** Length in bytes */
+    public short getLength() {
+        return (short) vec.getLength();
+    }
+
+    public void emitMagicAndVersion() {
+        emitInt(0xCAFEBABE);
+        emitShort((short) 0);
+        emitShort((short) 49);
+    }
+
+    public void emitInt(int val) {
+        emitByte((byte) (val >> 24));
+        emitByte((byte) ((val >> 16) & 0xFF));
+        emitByte((byte) ((val >> 8) & 0xFF));
+        emitByte((byte) (val & 0xFF));
+    }
+
+    public void emitShort(short val) {
+        emitByte((byte) ((val >> 8) & 0xFF));
+        emitByte((byte) (val & 0xFF));
+    }
+
+    // Support for labels; package-private
+    void emitShort(short bci, short val) {
+        vec.put(bci,     (byte) ((val >> 8) & 0xFF));
+        vec.put(bci + 1, (byte) (val & 0xFF));
+    }
+
+    public void emitByte(byte val) {
+        vec.add(val);
+    }
+
+    public void append(ClassFileAssembler asm) {
+        append(asm.vec);
+    }
+
+    public void append(ByteVector vec) {
+        for (int i = 0; i < vec.getLength(); i++) {
+            emitByte(vec.get(i));
+        }
+    }
+
+    /** Keeps track of the current (one-based) constant pool index;
+        incremented after emitting one of the following constant pool
+        entries. Can fetch the current constant pool index for use in
+        later entries.  Index points at the last valid constant pool
+        entry; initially invalid. It is illegal to fetch the constant
+        pool index before emitting at least one constant pool entry. */
+    public short cpi() {
+        if (cpIdx == 0) {
+            throw new RuntimeException("Illegal use of ClassFileAssembler");
+        }
+        return cpIdx;
+    }
+
+    public void emitConstantPoolUTF8(String str) {
+        // NOTE: can not use str.getBytes("UTF-8") here because of
+        // bootstrapping issues with the character set converters.
+        byte[] bytes = UTF8.encode(str);
+        emitByte(CONSTANT_Utf8);
+        emitShort((short) bytes.length);
+        for (int i = 0; i < bytes.length; i++) {
+            emitByte(bytes[i]);
+        }
+        cpIdx++;
+    }
+
+    public void emitConstantPoolClass(short index) {
+        emitByte(CONSTANT_Class);
+        emitShort(index);
+        cpIdx++;
+    }
+
+    public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) {
+        emitByte(CONSTANT_NameAndType);
+        emitShort(nameIndex);
+        emitShort(typeIndex);
+        cpIdx++;
+    }
+
+    public void emitConstantPoolFieldref
+        (short classIndex, short nameAndTypeIndex)
+    {
+        emitByte(CONSTANT_Fieldref);
+        emitShort(classIndex);
+        emitShort(nameAndTypeIndex);
+        cpIdx++;
+    }
+
+    public void emitConstantPoolMethodref
+        (short classIndex, short nameAndTypeIndex)
+    {
+        emitByte(CONSTANT_Methodref);
+        emitShort(classIndex);
+        emitShort(nameAndTypeIndex);
+        cpIdx++;
+    }
+
+    public void emitConstantPoolInterfaceMethodref
+        (short classIndex, short nameAndTypeIndex)
+    {
+        emitByte(CONSTANT_InterfaceMethodref);
+        emitShort(classIndex);
+        emitShort(nameAndTypeIndex);
+        cpIdx++;
+    }
+
+    public void emitConstantPoolString(short utf8Index) {
+        emitByte(CONSTANT_String);
+        emitShort(utf8Index);
+        cpIdx++;
+    }
+
+    //----------------------------------------------------------------------
+    // Opcodes. Keeps track of maximum stack and locals. Make a new
+    // assembler for each piece of assembled code, then append the
+    // result to the previous assembler's class file.
+    //
+
+    private int stack     = 0;
+    private int maxStack  = 0;
+    private int maxLocals = 0;
+
+    private void incStack() {
+        setStack(stack + 1);
+    }
+
+    private void decStack() {
+        --stack;
+    }
+
+    public short getMaxStack() {
+        return (short) maxStack;
+    }
+
+    public short getMaxLocals() {
+        return (short) maxLocals;
+    }
+
+    /** It's necessary to be able to specify the number of arguments at
+        the beginning of the method (which translates to the initial
+        value of max locals) */
+    public void setMaxLocals(int maxLocals) {
+        this.maxLocals = maxLocals;
+    }
+
+    /** Needed to do flow control. Returns current stack depth. */
+    public int getStack() {
+        return stack;
+    }
+
+    /** Needed to do flow control. */
+    public void setStack(int value) {
+        stack = value;
+        if (stack > maxStack) {
+            maxStack = stack;
+        }
+    }
+
+    ///////////////
+    // Constants //
+    ///////////////
+
+    public void opc_aconst_null() {
+        emitByte(opc_aconst_null);
+        incStack();
+    }
+
+    public void opc_sipush(short constant) {
+        emitByte(opc_sipush);
+        emitShort(constant);
+        incStack();
+    }
+
+    public void opc_ldc(byte cpIdx) {
+        emitByte(opc_ldc);
+        emitByte(cpIdx);
+        incStack();
+    }
+
+    /////////////////////////////////////
+    // Local variable loads and stores //
+    /////////////////////////////////////
+
+    public void opc_iload_0() {
+        emitByte(opc_iload_0);
+        if (maxLocals < 1) maxLocals = 1;
+        incStack();
+    }
+
+    public void opc_iload_1() {
+        emitByte(opc_iload_1);
+        if (maxLocals < 2) maxLocals = 2;
+        incStack();
+    }
+
+    public void opc_iload_2() {
+        emitByte(opc_iload_2);
+        if (maxLocals < 3) maxLocals = 3;
+        incStack();
+    }
+
+    public void opc_iload_3() {
+        emitByte(opc_iload_3);
+        if (maxLocals < 4) maxLocals = 4;
+        incStack();
+    }
+
+    public void opc_lload_0() {
+        emitByte(opc_lload_0);
+        if (maxLocals < 2) maxLocals = 2;
+        incStack();
+        incStack();
+    }
+
+    public void opc_lload_1() {
+        emitByte(opc_lload_1);
+        if (maxLocals < 3) maxLocals = 3;
+        incStack();
+        incStack();
+    }
+
+    public void opc_lload_2() {
+        emitByte(opc_lload_2);
+        if (maxLocals < 4) maxLocals = 4;
+        incStack();
+        incStack();
+    }
+
+    public void opc_lload_3() {
+        emitByte(opc_lload_3);
+        if (maxLocals < 5) maxLocals = 5;
+        incStack();
+        incStack();
+    }
+
+    public void opc_fload_0() {
+        emitByte(opc_fload_0);
+        if (maxLocals < 1) maxLocals = 1;
+        incStack();
+    }
+
+    public void opc_fload_1() {
+        emitByte(opc_fload_1);
+        if (maxLocals < 2) maxLocals = 2;
+        incStack();
+    }
+
+    public void opc_fload_2() {
+        emitByte(opc_fload_2);
+        if (maxLocals < 3) maxLocals = 3;
+        incStack();
+    }
+
+    public void opc_fload_3() {
+        emitByte(opc_fload_3);
+        if (maxLocals < 4) maxLocals = 4;
+        incStack();
+    }
+
+    public void opc_dload_0() {
+        emitByte(opc_dload_0);
+        if (maxLocals < 2) maxLocals = 2;
+        incStack();
+        incStack();
+    }
+
+    public void opc_dload_1() {
+        emitByte(opc_dload_1);
+        if (maxLocals < 3) maxLocals = 3;
+        incStack();
+        incStack();
+    }
+
+    public void opc_dload_2() {
+        emitByte(opc_dload_2);
+        if (maxLocals < 4) maxLocals = 4;
+        incStack();
+        incStack();
+    }
+
+    public void opc_dload_3() {
+        emitByte(opc_dload_3);
+        if (maxLocals < 5) maxLocals = 5;
+        incStack();
+        incStack();
+    }
+
+    public void opc_aload_0() {
+        emitByte(opc_aload_0);
+        if (maxLocals < 1) maxLocals = 1;
+        incStack();
+    }
+
+    public void opc_aload_1() {
+        emitByte(opc_aload_1);
+        if (maxLocals < 2) maxLocals = 2;
+        incStack();
+    }
+
+    public void opc_aload_2() {
+        emitByte(opc_aload_2);
+        if (maxLocals < 3) maxLocals = 3;
+        incStack();
+    }
+
+    public void opc_aload_3() {
+        emitByte(opc_aload_3);
+        if (maxLocals < 4) maxLocals = 4;
+        incStack();
+    }
+
+    public void opc_aaload() {
+        emitByte(opc_aaload);
+        decStack();
+    }
+
+    public void opc_astore_0() {
+        emitByte(opc_astore_0);
+        if (maxLocals < 1) maxLocals = 1;
+        decStack();
+    }
+
+    public void opc_astore_1() {
+        emitByte(opc_astore_1);
+        if (maxLocals < 2) maxLocals = 2;
+        decStack();
+    }
+
+    public void opc_astore_2() {
+        emitByte(opc_astore_2);
+        if (maxLocals < 3) maxLocals = 3;
+        decStack();
+    }
+
+    public void opc_astore_3() {
+        emitByte(opc_astore_3);
+        if (maxLocals < 4) maxLocals = 4;
+        decStack();
+    }
+
+    ////////////////////////
+    // Stack manipulation //
+    ////////////////////////
+
+    public void opc_pop() {
+        emitByte(opc_pop);
+        decStack();
+    }
+
+    public void opc_dup() {
+        emitByte(opc_dup);
+        incStack();
+    }
+
+    public void opc_dup_x1() {
+        emitByte(opc_dup_x1);
+        incStack();
+    }
+
+    public void opc_swap() {
+        emitByte(opc_swap);
+    }
+
+    ///////////////////////////////
+    // Widening conversions only //
+    ///////////////////////////////
+
+    public void opc_i2l() {
+        emitByte(opc_i2l);
+    }
+
+    public void opc_i2f() {
+        emitByte(opc_i2f);
+    }
+
+    public void opc_i2d() {
+        emitByte(opc_i2d);
+    }
+
+    public void opc_l2f() {
+        emitByte(opc_l2f);
+    }
+
+    public void opc_l2d() {
+        emitByte(opc_l2d);
+    }
+
+    public void opc_f2d() {
+        emitByte(opc_f2d);
+    }
+
+    //////////////////
+    // Control flow //
+    //////////////////
+
+    public void opc_ifeq(short bciOffset) {
+        emitByte(opc_ifeq);
+        emitShort(bciOffset);
+        decStack();
+    }
+
+    /** Control flow with forward-reference BCI. Stack assumes
+        straight-through control flow. */
+    public void opc_ifeq(Label l) {
+        short instrBCI = getLength();
+        emitByte(opc_ifeq);
+        l.add(this, instrBCI, getLength(), getStack() - 1);
+        emitShort((short) -1); // Must be patched later
+    }
+
+    public void opc_if_icmpeq(short bciOffset) {
+        emitByte(opc_if_icmpeq);
+        emitShort(bciOffset);
+        setStack(getStack() - 2);
+    }
+
+    /** Control flow with forward-reference BCI. Stack assumes straight
+        control flow. */
+    public void opc_if_icmpeq(Label l) {
+        short instrBCI = getLength();
+        emitByte(opc_if_icmpeq);
+        l.add(this, instrBCI, getLength(), getStack() - 2);
+        emitShort((short) -1); // Must be patched later
+    }
+
+    public void opc_goto(short bciOffset) {
+        emitByte(opc_goto);
+        emitShort(bciOffset);
+    }
+
+    /** Control flow with forward-reference BCI. Stack assumes straight
+        control flow. */
+    public void opc_goto(Label l) {
+        short instrBCI = getLength();
+        emitByte(opc_goto);
+        l.add(this, instrBCI, getLength(), getStack());
+        emitShort((short) -1); // Must be patched later
+    }
+
+    public void opc_ifnull(short bciOffset) {
+        emitByte(opc_ifnull);
+        emitShort(bciOffset);
+        decStack();
+    }
+
+    /** Control flow with forward-reference BCI. Stack assumes straight
+        control flow. */
+    public void opc_ifnull(Label l) {
+        short instrBCI = getLength();
+        emitByte(opc_ifnull);
+        l.add(this, instrBCI, getLength(), getStack() - 1);
+        emitShort((short) -1); // Must be patched later
+        decStack();
+    }
+
+    public void opc_ifnonnull(short bciOffset) {
+        emitByte(opc_ifnonnull);
+        emitShort(bciOffset);
+        decStack();
+    }
+
+    /** Control flow with forward-reference BCI. Stack assumes straight
+        control flow. */
+    public void opc_ifnonnull(Label l) {
+        short instrBCI = getLength();
+        emitByte(opc_ifnonnull);
+        l.add(this, instrBCI, getLength(), getStack() - 1);
+        emitShort((short) -1); // Must be patched later
+        decStack();
+    }
+
+    /////////////////////////
+    // Return instructions //
+    /////////////////////////
+
+    public void opc_ireturn() {
+        emitByte(opc_ireturn);
+        setStack(0);
+    }
+
+    public void opc_lreturn() {
+        emitByte(opc_lreturn);
+        setStack(0);
+    }
+
+    public void opc_freturn() {
+        emitByte(opc_freturn);
+        setStack(0);
+    }
+
+    public void opc_dreturn() {
+        emitByte(opc_dreturn);
+        setStack(0);
+    }
+
+    public void opc_areturn() {
+        emitByte(opc_areturn);
+        setStack(0);
+    }
+
+    public void opc_return() {
+        emitByte(opc_return);
+        setStack(0);
+    }
+
+    //////////////////////
+    // Field operations //
+    //////////////////////
+
+    public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) {
+        emitByte(opc_getstatic);
+        emitShort(fieldIndex);
+        setStack(getStack() + fieldSizeInStackSlots);
+    }
+
+    public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) {
+        emitByte(opc_putstatic);
+        emitShort(fieldIndex);
+        setStack(getStack() - fieldSizeInStackSlots);
+    }
+
+    public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {
+        emitByte(opc_getfield);
+        emitShort(fieldIndex);
+        setStack(getStack() + fieldSizeInStackSlots - 1);
+    }
+
+    public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) {
+        emitByte(opc_putfield);
+        emitShort(fieldIndex);
+        setStack(getStack() - fieldSizeInStackSlots - 1);
+    }
+
+    ////////////////////////
+    // Method invocations //
+    ////////////////////////
+
+    /** Long and double arguments and return types count as 2 arguments;
+        other values count as 1. */
+    public void opc_invokevirtual(short methodIndex,
+                                  int numArgs,
+                                  int numReturnValues)
+    {
+        emitByte(opc_invokevirtual);
+        emitShort(methodIndex);
+        setStack(getStack() - numArgs - 1 + numReturnValues);
+    }
+
+    /** Long and double arguments and return types count as 2 arguments;
+        other values count as 1. */
+    public void opc_invokespecial(short methodIndex,
+                                  int numArgs,
+                                  int numReturnValues)
+    {
+        emitByte(opc_invokespecial);
+        emitShort(methodIndex);
+        setStack(getStack() - numArgs - 1 + numReturnValues);
+    }
+
+    /** Long and double arguments and return types count as 2 arguments;
+        other values count as 1. */
+    public void opc_invokestatic(short methodIndex,
+                                 int numArgs,
+                                 int numReturnValues)
+    {
+        emitByte(opc_invokestatic);
+        emitShort(methodIndex);
+        setStack(getStack() - numArgs + numReturnValues);
+    }
+
+    /** Long and double arguments and return types count as 2 arguments;
+        other values count as 1. */
+    public void opc_invokeinterface(short methodIndex,
+                                    int numArgs,
+                                    byte count,
+                                    int numReturnValues)
+    {
+        emitByte(opc_invokeinterface);
+        emitShort(methodIndex);
+        emitByte(count);
+        emitByte((byte) 0);
+        setStack(getStack() - numArgs - 1 + numReturnValues);
+    }
+
+    //////////////////
+    // Array length //
+    //////////////////
+
+    public void opc_arraylength() {
+        emitByte(opc_arraylength);
+    }
+
+    /////////
+    // New //
+    /////////
+
+    public void opc_new(short classIndex) {
+        emitByte(opc_new);
+        emitShort(classIndex);
+        incStack();
+    }
+
+    ////////////
+    // Athrow //
+    ////////////
+
+    public void opc_athrow() {
+        emitByte(opc_athrow);
+        setStack(1);
+    }
+
+    //////////////////////////////
+    // Checkcast and instanceof //
+    //////////////////////////////
+
+    /** Assumes the checkcast succeeds */
+    public void opc_checkcast(short classIndex) {
+        emitByte(opc_checkcast);
+        emitShort(classIndex);
+    }
+
+    public void opc_instanceof(short classIndex) {
+        emitByte(opc_instanceof);
+        emitShort(classIndex);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ClassFileConstants.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+/** Minimal set of class file constants for assembly of field and
+    method accessors. */
+
+interface ClassFileConstants {
+    // Constants
+    public static final byte opc_aconst_null   = (byte) 0x1;
+    public static final byte opc_sipush        = (byte) 0x11;
+    public static final byte opc_ldc           = (byte) 0x12;
+
+    // Local variable loads and stores
+    public static final byte opc_iload_0       = (byte) 0x1a;
+    public static final byte opc_iload_1       = (byte) 0x1b;
+    public static final byte opc_iload_2       = (byte) 0x1c;
+    public static final byte opc_iload_3       = (byte) 0x1d;
+    public static final byte opc_lload_0       = (byte) 0x1e;
+    public static final byte opc_lload_1       = (byte) 0x1f;
+    public static final byte opc_lload_2       = (byte) 0x20;
+    public static final byte opc_lload_3       = (byte) 0x21;
+    public static final byte opc_fload_0       = (byte) 0x22;
+    public static final byte opc_fload_1       = (byte) 0x23;
+    public static final byte opc_fload_2       = (byte) 0x24;
+    public static final byte opc_fload_3       = (byte) 0x25;
+    public static final byte opc_dload_0       = (byte) 0x26;
+    public static final byte opc_dload_1       = (byte) 0x27;
+    public static final byte opc_dload_2       = (byte) 0x28;
+    public static final byte opc_dload_3       = (byte) 0x29;
+    public static final byte opc_aload_0       = (byte) 0x2a;
+    public static final byte opc_aload_1       = (byte) 0x2b;
+    public static final byte opc_aload_2       = (byte) 0x2c;
+    public static final byte opc_aload_3       = (byte) 0x2d;
+    public static final byte opc_aaload        = (byte) 0x32;
+    public static final byte opc_astore_0      = (byte) 0x4b;
+    public static final byte opc_astore_1      = (byte) 0x4c;
+    public static final byte opc_astore_2      = (byte) 0x4d;
+    public static final byte opc_astore_3      = (byte) 0x4e;
+
+    // Stack manipulation
+    public static final byte opc_pop           = (byte) 0x57;
+    public static final byte opc_dup           = (byte) 0x59;
+    public static final byte opc_dup_x1        = (byte) 0x5a;
+    public static final byte opc_swap          = (byte) 0x5f;
+
+    // Conversions
+    public static final byte opc_i2l           = (byte) 0x85;
+    public static final byte opc_i2f           = (byte) 0x86;
+    public static final byte opc_i2d           = (byte) 0x87;
+    public static final byte opc_l2i           = (byte) 0x88;
+    public static final byte opc_l2f           = (byte) 0x89;
+    public static final byte opc_l2d           = (byte) 0x8a;
+    public static final byte opc_f2i           = (byte) 0x8b;
+    public static final byte opc_f2l           = (byte) 0x8c;
+    public static final byte opc_f2d           = (byte) 0x8d;
+    public static final byte opc_d2i           = (byte) 0x8e;
+    public static final byte opc_d2l           = (byte) 0x8f;
+    public static final byte opc_d2f           = (byte) 0x90;
+    public static final byte opc_i2b           = (byte) 0x91;
+    public static final byte opc_i2c           = (byte) 0x92;
+    public static final byte opc_i2s           = (byte) 0x93;
+
+    // Control flow
+    public static final byte opc_ifeq          = (byte) 0x99;
+    public static final byte opc_if_icmpeq     = (byte) 0x9f;
+    public static final byte opc_goto          = (byte) 0xa7;
+
+    // Return instructions
+    public static final byte opc_ireturn       = (byte) 0xac;
+    public static final byte opc_lreturn       = (byte) 0xad;
+    public static final byte opc_freturn       = (byte) 0xae;
+    public static final byte opc_dreturn       = (byte) 0xaf;
+    public static final byte opc_areturn       = (byte) 0xb0;
+    public static final byte opc_return        = (byte) 0xb1;
+
+    // Field operations
+    public static final byte opc_getstatic     = (byte) 0xb2;
+    public static final byte opc_putstatic     = (byte) 0xb3;
+    public static final byte opc_getfield      = (byte) 0xb4;
+    public static final byte opc_putfield      = (byte) 0xb5;
+
+    // Method invocations
+    public static final byte opc_invokevirtual   = (byte) 0xb6;
+    public static final byte opc_invokespecial   = (byte) 0xb7;
+    public static final byte opc_invokestatic    = (byte) 0xb8;
+    public static final byte opc_invokeinterface = (byte) 0xb9;
+
+    // Array length
+    public static final byte opc_arraylength     = (byte) 0xbe;
+
+    // New
+    public static final byte opc_new           = (byte) 0xbb;
+
+    // Athrow
+    public static final byte opc_athrow        = (byte) 0xbf;
+
+    // Checkcast and instanceof
+    public static final byte opc_checkcast     = (byte) 0xc0;
+    public static final byte opc_instanceof    = (byte) 0xc1;
+
+    // Ifnull and ifnonnull
+    public static final byte opc_ifnull        = (byte) 0xc6;
+    public static final byte opc_ifnonnull     = (byte) 0xc7;
+
+    // Constant pool tags
+    public static final byte CONSTANT_Class              = (byte) 7;
+    public static final byte CONSTANT_Fieldref           = (byte) 9;
+    public static final byte CONSTANT_Methodref          = (byte) 10;
+    public static final byte CONSTANT_InterfaceMethodref = (byte) 11;
+    public static final byte CONSTANT_NameAndType        = (byte) 12;
+    public static final byte CONSTANT_String             = (byte) 8;
+    public static final byte CONSTANT_Utf8               = (byte) 1;
+
+    // Access flags
+    public static final short ACC_PUBLIC = (short) 0x0001;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ConstantPool.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2003, 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.reflect;
+
+import java.lang.reflect.*;
+
+/** Provides reflective access to the constant pools of classes.
+    Currently this is needed to provide reflective access to annotations
+    but may be used by other internal subsystems in the future. */
+
+public class ConstantPool {
+  // Number of entries in this constant pool (= maximum valid constant pool index)
+  public int      getSize()                      { return getSize0            (constantPoolOop);        }
+  public Class<?> getClassAt         (int index) { return getClassAt0         (constantPoolOop, index); }
+  public Class<?> getClassAtIfLoaded (int index) { return getClassAtIfLoaded0 (constantPoolOop, index); }
+  // Returns a class reference index for a method or a field.
+  public int getClassRefIndexAt(int index) {
+      return getClassRefIndexAt0(constantPoolOop, index);
+  }
+  // Returns either a Method or Constructor.
+  // Static initializers are returned as Method objects.
+  public Member   getMethodAt        (int index) { return getMethodAt0        (constantPoolOop, index); }
+  public Member   getMethodAtIfLoaded(int index) { return getMethodAtIfLoaded0(constantPoolOop, index); }
+  public Field    getFieldAt         (int index) { return getFieldAt0         (constantPoolOop, index); }
+  public Field    getFieldAtIfLoaded (int index) { return getFieldAtIfLoaded0 (constantPoolOop, index); }
+  // Fetches the class name, member (field, method or interface
+  // method) name, and type descriptor as an array of three Strings
+  public String[] getMemberRefInfoAt (int index) { return getMemberRefInfoAt0 (constantPoolOop, index); }
+  // Returns a name and type reference index for a method, a field or an invokedynamic.
+  public int getNameAndTypeRefIndexAt(int index) {
+      return getNameAndTypeRefIndexAt0(constantPoolOop, index);
+  }
+  // Fetches the name and type from name_and_type index as an array of two Strings
+  public String[] getNameAndTypeRefInfoAt(int index) {
+      return getNameAndTypeRefInfoAt0(constantPoolOop, index);
+  }
+  public int      getIntAt           (int index) { return getIntAt0           (constantPoolOop, index); }
+  public long     getLongAt          (int index) { return getLongAt0          (constantPoolOop, index); }
+  public float    getFloatAt         (int index) { return getFloatAt0         (constantPoolOop, index); }
+  public double   getDoubleAt        (int index) { return getDoubleAt0        (constantPoolOop, index); }
+  public String   getStringAt        (int index) { return getStringAt0        (constantPoolOop, index); }
+  public String   getUTF8At          (int index) { return getUTF8At0          (constantPoolOop, index); }
+  public Tag getTagAt(int index) {
+      return Tag.valueOf(getTagAt0(constantPoolOop, index));
+  }
+
+  public static enum Tag {
+      UTF8(1),
+      INTEGER(3),
+      FLOAT(4),
+      LONG(5),
+      DOUBLE(6),
+      CLASS(7),
+      STRING(8),
+      FIELDREF(9),
+      METHODREF(10),
+      INTERFACEMETHODREF(11),
+      NAMEANDTYPE(12),
+      METHODHANDLE(15),
+      METHODTYPE(16),
+      INVOKEDYNAMIC(18),
+      INVALID(0);
+
+      private final int tagCode;
+
+      private Tag(int tagCode) {
+          this.tagCode = tagCode;
+      }
+
+      private static Tag valueOf(byte v) {
+          for (Tag tag : Tag.values()) {
+              if (tag.tagCode == v) {
+                  return tag;
+              }
+          }
+          throw new IllegalArgumentException("Unknown constant pool tag code " + v);
+      }
+   }
+  //---------------------------------------------------------------------------
+  // Internals only below this point
+  //
+
+  static {
+      Reflection.registerFieldsToFilter(ConstantPool.class, new String[] { "constantPoolOop" });
+  }
+
+  // HotSpot-internal constant pool object (set by the VM, name known to the VM)
+  private Object constantPoolOop;
+
+  private native int      getSize0            (Object constantPoolOop);
+  private native Class<?> getClassAt0         (Object constantPoolOop, int index);
+  private native Class<?> getClassAtIfLoaded0 (Object constantPoolOop, int index);
+  private native int      getClassRefIndexAt0 (Object constantPoolOop, int index);
+  private native Member   getMethodAt0        (Object constantPoolOop, int index);
+  private native Member   getMethodAtIfLoaded0(Object constantPoolOop, int index);
+  private native Field    getFieldAt0         (Object constantPoolOop, int index);
+  private native Field    getFieldAtIfLoaded0 (Object constantPoolOop, int index);
+  private native String[] getMemberRefInfoAt0 (Object constantPoolOop, int index);
+  private native int      getNameAndTypeRefIndexAt0(Object constantPoolOop, int index);
+  private native String[] getNameAndTypeRefInfoAt0(Object constantPoolOop, int index);
+  private native int      getIntAt0           (Object constantPoolOop, int index);
+  private native long     getLongAt0          (Object constantPoolOop, int index);
+  private native float    getFloatAt0         (Object constantPoolOop, int index);
+  private native double   getDoubleAt0        (Object constantPoolOop, int index);
+  private native String   getStringAt0        (Object constantPoolOop, int index);
+  private native String   getUTF8At0          (Object constantPoolOop, int index);
+  private native byte     getTagAt0           (Object constantPoolOop, int index);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ConstructorAccessor.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+
+/** This interface provides the declaration for
+    java.lang.reflect.Constructor.invoke(). Each Constructor object is
+    configured with a (possibly dynamically-generated) class which
+    implements this interface. */
+
+public interface ConstructorAccessor {
+    /** Matches specification in {@link java.lang.reflect.Constructor} */
+    public Object newInstance(Object[] args)
+        throws InstantiationException,
+               IllegalArgumentException,
+               InvocationTargetException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/ConstructorAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+
+/** Package-private implementation of the ConstructorAccessor
+    interface which has access to all classes and all fields,
+    regardless of language restrictions. See MagicAccessorImpl. */
+
+abstract class ConstructorAccessorImpl extends MagicAccessorImpl
+    implements ConstructorAccessor {
+    /** Matches specification in {@link java.lang.reflect.Constructor} */
+    public abstract Object newInstance(Object[] args)
+        throws InstantiationException,
+               IllegalArgumentException,
+               InvocationTargetException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/DelegatingConstructorAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+
+/** Delegates its invocation to another ConstructorAccessorImpl and can
+    change its delegate at run time. */
+
+class DelegatingConstructorAccessorImpl extends ConstructorAccessorImpl {
+    private ConstructorAccessorImpl delegate;
+
+    DelegatingConstructorAccessorImpl(ConstructorAccessorImpl delegate) {
+        setDelegate(delegate);
+    }
+
+    public Object newInstance(Object[] args)
+      throws InstantiationException,
+             IllegalArgumentException,
+             InvocationTargetException
+    {
+        return delegate.newInstance(args);
+    }
+
+    void setDelegate(ConstructorAccessorImpl delegate) {
+        this.delegate = delegate;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/DelegatingMethodAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+
+/** Delegates its invocation to another MethodAccessorImpl and can
+    change its delegate at run time. */
+
+class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
+    private MethodAccessorImpl delegate;
+
+    DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {
+        setDelegate(delegate);
+    }
+
+    public Object invoke(Object obj, Object[] args)
+        throws IllegalArgumentException, InvocationTargetException
+    {
+        return delegate.invoke(obj, args);
+    }
+
+    void setDelegate(MethodAccessorImpl delegate) {
+        this.delegate = delegate;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/FieldAccessor.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+/** This interface provides the declarations for the accessor methods
+    of java.lang.reflect.Field. Each Field object is configured with a
+    (possibly dynamically-generated) class which implements this
+    interface. */
+
+public interface FieldAccessor {
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public Object get(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public boolean getBoolean(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public byte getByte(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public char getChar(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public short getShort(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public int getInt(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public long getLong(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public float getFloat(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public double getDouble(Object obj) throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void set(Object obj, Object value)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setBoolean(Object obj, boolean z)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setByte(Object obj, byte b)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setChar(Object obj, char c)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setShort(Object obj, short s)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setInt(Object obj, int i)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setLong(Object obj, long l)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setFloat(Object obj, float f)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public void setDouble(Object obj, double d)
+        throws IllegalArgumentException, IllegalAccessException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/FieldAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+/** Package-private implementation of the FieldAccessor interface
+    which has access to all classes and all fields, regardless of
+    language restrictions. See MagicAccessorImpl. */
+
+abstract class FieldAccessorImpl extends MagicAccessorImpl
+    implements FieldAccessor {
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract Object get(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract boolean getBoolean(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract byte getByte(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract char getChar(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract short getShort(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract int getInt(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract long getLong(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract float getFloat(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract double getDouble(Object obj)
+        throws IllegalArgumentException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void set(Object obj, Object value)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setBoolean(Object obj, boolean z)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setByte(Object obj, byte b)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setChar(Object obj, char c)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setShort(Object obj, short s)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setInt(Object obj, int i)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setLong(Object obj, long l)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setFloat(Object obj, float f)
+        throws IllegalArgumentException, IllegalAccessException;
+
+    /** Matches specification in {@link java.lang.reflect.Field} */
+    public abstract void setDouble(Object obj, double d)
+        throws IllegalArgumentException, IllegalAccessException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/InstantiationExceptionConstructorAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/** Throws an InstantiationException with given error message upon
+    newInstance() call */
+
+class InstantiationExceptionConstructorAccessorImpl
+    extends ConstructorAccessorImpl {
+    private final String message;
+
+    InstantiationExceptionConstructorAccessorImpl(String message) {
+        this.message = message;
+    }
+
+    public Object newInstance(Object[] args)
+        throws InstantiationException,
+               IllegalArgumentException,
+               InvocationTargetException
+    {
+        if (message == null) {
+            throw new InstantiationException();
+        }
+        throw new InstantiationException(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/Label.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2001, 2011, 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.reflect;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/** Allows forward references in bytecode streams emitted by
+    ClassFileAssembler. Assumes that the start of the method body is
+    the first byte in the assembler's buffer. May be used at more than
+    one branch site. */
+
+class Label {
+    static class PatchInfo {
+        PatchInfo(ClassFileAssembler asm,
+                  short instrBCI,
+                  short patchBCI,
+                  int stackDepth)
+        {
+            this.asm = asm;
+            this.instrBCI   = instrBCI;
+            this.patchBCI   = patchBCI;
+            this.stackDepth = stackDepth;
+        }
+        // This won't work for more than one assembler anyway, so this is
+        // unnecessary
+        final ClassFileAssembler asm;
+        final short instrBCI;
+        final short patchBCI;
+        final int   stackDepth;
+    }
+    private final List<PatchInfo> patches = new ArrayList<>();
+
+    public Label() {
+    }
+
+    void add(ClassFileAssembler asm,
+             short instrBCI,
+             short patchBCI,
+             int stackDepth)
+    {
+        patches.add(new PatchInfo(asm, instrBCI, patchBCI, stackDepth));
+    }
+
+    public void bind() {
+        for (PatchInfo patch : patches){
+            short curBCI = patch.asm.getLength();
+            short offset = (short) (curBCI - patch.instrBCI);
+            patch.asm.emitShort(patch.patchBCI, offset);
+            patch.asm.setStack(patch.stackDepth);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/LangReflectAccess.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2001, 2013, 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.reflect;
+
+import java.lang.reflect.*;
+
+/** An interface which gives privileged packages Java-level access to
+    internals of java.lang.reflect. */
+
+public interface LangReflectAccess {
+    /** Creates a new java.lang.reflect.Field. Access checks as per
+        java.lang.reflect.AccessibleObject are not overridden. */
+    public Field newField(Class<?> declaringClass,
+                          String name,
+                          Class<?> type,
+                          int modifiers,
+                          int slot,
+                          String signature,
+                          byte[] annotations);
+
+    /** Creates a new java.lang.reflect.Method. Access checks as per
+      java.lang.reflect.AccessibleObject are not overridden. */
+    public Method newMethod(Class<?> declaringClass,
+                            String name,
+                            Class<?>[] parameterTypes,
+                            Class<?> returnType,
+                            Class<?>[] checkedExceptions,
+                            int modifiers,
+                            int slot,
+                            String signature,
+                            byte[] annotations,
+                            byte[] parameterAnnotations,
+                            byte[] annotationDefault);
+
+    /** Creates a new java.lang.reflect.Constructor. Access checks as
+      per java.lang.reflect.AccessibleObject are not overridden. */
+    public <T> Constructor<T> newConstructor(Class<T> declaringClass,
+                                             Class<?>[] parameterTypes,
+                                             Class<?>[] checkedExceptions,
+                                             int modifiers,
+                                             int slot,
+                                             String signature,
+                                             byte[] annotations,
+                                             byte[] parameterAnnotations);
+
+    /** Gets the MethodAccessor object for a java.lang.reflect.Method */
+    public MethodAccessor getMethodAccessor(Method m);
+
+    /** Sets the MethodAccessor object for a java.lang.reflect.Method */
+    public void setMethodAccessor(Method m, MethodAccessor accessor);
+
+    /** Gets the ConstructorAccessor object for a
+        java.lang.reflect.Constructor */
+    public ConstructorAccessor getConstructorAccessor(Constructor<?> c);
+
+    /** Sets the ConstructorAccessor object for a
+        java.lang.reflect.Constructor */
+    public void setConstructorAccessor(Constructor<?> c,
+                                       ConstructorAccessor accessor);
+
+    /** Gets the byte[] that encodes TypeAnnotations on an Executable. */
+    public byte[] getExecutableTypeAnnotationBytes(Executable ex);
+
+    /** Gets the "slot" field from a Constructor (used for serialization) */
+    public int getConstructorSlot(Constructor<?> c);
+
+    /** Gets the "signature" field from a Constructor (used for serialization) */
+    public String getConstructorSignature(Constructor<?> c);
+
+    /** Gets the "annotations" field from a Constructor (used for serialization) */
+    public byte[] getConstructorAnnotations(Constructor<?> c);
+
+    /** Gets the "parameterAnnotations" field from a Constructor (used for serialization) */
+    public byte[] getConstructorParameterAnnotations(Constructor<?> c);
+
+    //
+    // Copying routines, needed to quickly fabricate new Field,
+    // Method, and Constructor objects from templates
+    //
+
+    /** Makes a "child" copy of a Method */
+    public Method      copyMethod(Method arg);
+
+    /** Makes a copy of this non-root a Method */
+    public Method      leafCopyMethod(Method arg);
+
+    /** Makes a "child" copy of a Field */
+    public Field       copyField(Field arg);
+
+    /** Makes a "child" copy of a Constructor */
+    public <T> Constructor<T> copyConstructor(Constructor<T> arg);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/MagicAccessorImpl.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+/** <P> MagicAccessorImpl (named for parity with FieldAccessorImpl and
+    others, not because it actually implements an interface) is a
+    marker class in the hierarchy. All subclasses of this class are
+    "magically" granted access by the VM to otherwise inaccessible
+    fields and methods of other classes. It is used to hold the code
+    for dynamically-generated FieldAccessorImpl and MethodAccessorImpl
+    subclasses. (Use of the word "unsafe" was avoided in this class's
+    name to avoid confusion with {@link jdk.internal.misc.Unsafe}.) </P>
+
+    <P> The bug fix for 4486457 also necessitated disabling
+    verification for this class and all subclasses, as opposed to just
+    SerializationConstructorAccessorImpl and subclasses, to avoid
+    having to indicate to the VM which of these dynamically-generated
+    stub classes were known to be able to pass the verifier. </P>
+
+    <P> Do not change the name of this class without also changing the
+    VM's code. </P> */
+
+class MagicAccessorImpl {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/MethodAccessor.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2001, 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.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+
+/** This interface provides the declaration for
+    java.lang.reflect.Method.invoke(). Each Method object is
+    configured with a (possibly dynamically-generated) class which
+    implements this interface.
+*/
+
+public interface MethodAccessor {
+    /** Matches specification in {@link java.lang.reflect.Method} */
+    public Object invoke(Object obj, Object[] args)
+        throws IllegalArgumentException, InvocationTargetException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java	Mon Apr 18 15:39:47 2016 -0700
@@ -0,0 +1,780 @@
+/*
+ * Copyright (c) 2001, 2013, 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.reflect;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/** Generator for sun.reflect.MethodAccessor and
+    sun.reflect.ConstructorAccessor objects using bytecodes to
+    implement reflection. A java.lang.reflect.Method or
+    java.lang.reflect.Constructor object can delegate its invoke or
+    newInstance method to an accessor using native code or to one
+    generated by this class. (Methods and Constructors were merged
+    together in this class to ensure maximum code sharing.) */
+
+class MethodAccessorGenerator extends AccessorGenerator {
+
+    private static final short NUM_BASE_CPOOL_ENTRIES   = (short) 12;
+    // One for invoke() plus one for constructor
+    private static final short NUM_METHODS              = (short) 2;
+    // Only used if forSerialization is true
+    private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
+
+    private static volatile int methodSymnum;
+    private static volatile int constructorSymnum;
+    private static volatile int serializationConstructorSymnum;
+
+    private Class<?>   declaringClass;
+    private Class<?>[] parameterTypes;
+    private Class<?>   returnType;
+    private boolean    isConstructor;
+    private boolean    forSerialization;
+
+    private short targetMethodRef;
+    private short invokeIdx;
+    private short invokeDescriptorIdx;
+    // Constant pool index of CONSTANT_Class_info for first
+    // non-primitive parameter type. Should be incremented by 2.
+    private short nonPrimitiveParametersBaseIdx;
+
+    MethodAccessorGenerator() {
+    }
+
+    /** This routine is not thread-safe */
+    public MethodAccessor generateMethod(Class<?> declaringClass,
+                                         String   name,
+                                         Class<?>[] parameterTypes,
+                                         Class<?>   returnType,
+                                         Class<?>[] checkedExceptions,
+                                         int modifiers)
+    {
+        return (MethodAccessor) generate(declaringClass,
+                                         name,
+                                         parameterTypes,
+                                         returnType,
+                                         checkedExceptions,
+                                         modifiers,
+                                         false,
+                                         false,
+                                         null);
+    }
+
+    /** This routine is not thread-safe */
+    public ConstructorAccessor generateConstructor(Class<?> declaringClass,
+                                                   Class<?>[] parameterTypes,
+                                                   Class<?>[] checkedExceptions,
+                                                   int modifiers)
+    {
+        return (ConstructorAccessor) generate(declaringClass,
+                                              "<init>",
+                                              parameterTypes,
+                                              Void.TYPE,
+                                              checkedExceptions,
+                                              modifiers,
+                                              true,
+                                              false,
+                                              null);
+    }
+
+    /** This routine is not thread-safe */
+    public SerializationConstructorAccessorImpl
+    generateSerializationConstructor(Class<?> declaringClass,
+                                     Class<?>[] parameterTypes,
+                                     Class<?>[] checkedExceptions,
+                                     int modifiers,
+                                     Class<?> targetConstructorClass)
+    {
+        return (SerializationConstructorAccessorImpl)
+            generate(declaringClass,
+                     "<init>",
+                     parameterTypes,
+                     Void.TYPE,
+                     checkedExceptions,
+                     modifiers,
+                     true,
+                     true,
+                     targetConstructorClass);
+    }
+
+    /** This routine is not thread-safe */
+    private MagicAccessorImpl generate(final Class<?> declaringClass,
+                                       String name,
+                                       Class<?>[] parameterTypes,
+                                       Class<?>   returnType,
+                                       Class<?>[] checkedExceptions,
+                                       int modifiers,
+                                       boolean isConstructor,
+                                       boolean forSerialization,
+                                       Class<?> serializationTargetClass)
+    {
+        ByteVector vec = ByteVectorFactory.create();
+        asm = new ClassFileAssembler(vec);
+        this.declaringClass = declaringClass;
+        this.parameterTypes = parameterTypes;
+        this.returnType = returnType;
+        this.modifiers = modifiers;
+        this.isConstructor = isConstructor;
+        this.forSerialization = forSerialization;
+
+        asm.emitMagicAndVersion();
+
+        // Constant pool entries:
+        // ( * = Boxing information: optional)
+        // (+  = Shared entries provided by AccessorGenerator)
+        // (^  = Only present if generating SerializationConstructorAccessor)
+        //     [UTF-8] [This class's name]
+        //     [CONSTANT_Class_info] for above
+        //     [UTF-8] "jdk/internal/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
+        //     [CONSTANT_Class_info] for above
+        //     [UTF-8] [Target class's name]
+        //     [CONSTANT_Class_info] for above
+        // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
+        // ^   [CONSTANT_Class_info] for above
+        //     [UTF-8] target method or constructor name
+        //     [UTF-8] target method or constructor signature
+        //     [CONSTANT_NameAndType_info] for above
+        //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
+        //     [UTF-8] "invoke" or "newInstance"
+        //     [UTF-8] invoke or newInstance descriptor
+        //     [UTF-8] descriptor for type of non-primitive parameter 1
+        //     [CONSTANT_Class_info] for type of non-primitive parameter 1
+        //     ...
+        //     [UTF-8] descriptor for type of non-primitive parameter n
+        //     [CONSTANT_Class_info] for type of non-primitive parameter n
+        // +   [UTF-8] "java/lang/Exception"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/ClassCastException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/NullPointerException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/IllegalArgumentException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "java/lang/InvocationTargetException"
+        // +   [CONSTANT_Class_info] for above
+        // +   [UTF-8] "<init>"
+        // +   [UTF-8] "()V"
+        // +   [CONSTANT_NameAndType_info] for above
+        // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
+        // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
+        // +   [UTF-8] "(Ljava/lang/String;)V"
+        // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
+        // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String</