Merge
authorduke
Wed, 05 Jul 2017 19:37:28 +0200
changeset 23952 85efd9f8ba79
parent 23951 8e30fd90c1db (current diff)
parent 23945 9c47c48f448e (diff)
child 23957 98ce82c2e8aa
Merge
jdk/src/macosx/lib/content-types.properties
jdk/src/share/demo/nio/zipfs/Demo.java
jdk/src/share/demo/nio/zipfs/README.txt
jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/JarFileSystemProvider.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipCoder.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipDirectoryStream.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributes.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipInfo.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java
jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java
jdk/src/solaris/lib/content-types.properties
jdk/src/windows/lib/content-types.properties
jdk/test/demo/zipfs/Basic.java
jdk/test/demo/zipfs/PathOps.java
jdk/test/demo/zipfs/ZFSTests.java
jdk/test/demo/zipfs/ZipFSTester.java
jdk/test/demo/zipfs/basic.sh
--- a/.hgtags-top-repo	Thu Apr 17 15:22:07 2014 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 19:37:28 2017 +0200
@@ -251,3 +251,4 @@
 d0b525cd31b87abeb6d5b7e3516953eeb13b323c jdk9-b06
 0ea015c298b201c07fa33990f2445b6d0ef3566d jdk9-b07
 db045d8faa0924b7378102d24a1a0d850c1e3834 jdk9-b08
+4a21dc7d57d1069a01f68e7182c074cb37349dfb jdk9-b09
--- a/common/src/fixpath.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/common/src/fixpath.c	Wed Jul 05 19:37:28 2017 +0200
@@ -109,7 +109,7 @@
 
 void append(char **b, size_t *bl, size_t *u, char *add, size_t addlen)
 {
-  while ( (addlen+*u+1) > *bl) {
+  while ((addlen+*u+1) > *bl) {
     *bl *= 2;
     *b = (char*) realloc(*b, *bl);
   }
@@ -118,7 +118,7 @@
 }
 
 /*
- * Creates a new string from in where the first occurance of sub is
+ * Creates a new string from in where the first occurrence of sub is
  * replaced by rep.
  */
 char *replace_substring(char *in, char *sub, char *rep)
@@ -246,7 +246,7 @@
   }
 
   buffer = (char*) malloc(buflen);
-  while((blocklen = fread(block,1,sizeof(block),atin)) > 0) {
+  while ((blocklen = fread(block, 1, sizeof(block), atin)) > 0) {
     append(&buffer, &buflen, &used, block, blocklen);
   }
   buffer[used] = 0;
@@ -280,16 +280,21 @@
   char *current = quoted;
   int pass;
 
-  if(strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) {
+  if (strlen(in_arg) == 0) {
+     // empty string? explicitly quote it.
+     return _strdup("\"\"");
+  }
+
+  if (strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) {
      return _strdup(in_arg);
   }
 
   // process the arg twice. Once to calculate the size and then to copy it.
-  for(pass=1; pass<=2; pass++) {
+  for (pass=1; pass<=2; pass++) {
     char const *arg = in_arg;
 
     // initial "
-    if(pass == 2) {
+    if (pass == 2) {
       *current = '\"';
     }
     current++;
@@ -328,7 +333,7 @@
         *current = *arg;
       }
       current++;
-    } while( *arg++ != '\0');
+    } while (*arg++ != '\0');
 
     // allocate the buffer
     if (pass == 1) {
@@ -362,7 +367,7 @@
 
     if (getenv("DEBUG_FIXPATH") != NULL) {
       char const * cmdline = GetCommandLine();
-      fprintf(stderr, "fixpath input line >%s<\n", strstr( cmdline , argv[1]));
+      fprintf(stderr, "fixpath input line >%s<\n", strstr(cmdline, argv[1]));
     }
 
     if (argv[1][1] == 'c' && argv[1][2] == '\0') {
@@ -399,7 +404,7 @@
         }
 
         rc = SetEnvironmentVariable(var, val);
-        if(!rc) {
+        if (!rc) {
           // Could not set var for some reason.  Try to report why.
           const int msg_len = 80 + var_len + strlen(val);
           char * msg = (char *) alloca(msg_len);
@@ -422,7 +427,7 @@
     // handle command and it's args.
     while (i < argc) {
       char const *replaced = replace_cygdrive(argv[i]);
-      if(replaced[0] == '@') {
+      if (replaced[0] == '@') {
         // Found at-file! Fix it!
         replaced = fix_at_file(replaced);
       }
@@ -433,7 +438,7 @@
     // determine the length of the line
     line = NULL;
     // args
-    for(i = cmd; i < argc; i++) {
+    for (i = cmd; i < argc; i++) {
       line += (ptrdiff_t) strlen(argv[i]);
     }
     // spaces and null
@@ -443,7 +448,7 @@
 
     // copy in args.
     current = line;
-    for(i = cmd; i < argc; i++) {
+    for (i = cmd; i < argc; i++) {
       ptrdiff_t len = strlen(argv[i]);
       if (i != cmd) {
         *current++ = ' ';
@@ -457,16 +462,16 @@
       fprintf(stderr, "fixpath converted line >%s<\n", line);
     }
 
-    if(cmd == argc) {
+    if (cmd == argc) {
        if (getenv("DEBUG_FIXPATH") != NULL) {
          fprintf(stderr, "fixpath no command provided!\n");
        }
        exit(0);
     }
 
-    ZeroMemory(&si,sizeof(si));
+    ZeroMemory(&si, sizeof(si));
     si.cb=sizeof(si);
-    ZeroMemory(&pi,sizeof(pi));
+    ZeroMemory(&pi, sizeof(pi));
 
     fflush(stderr);
     fflush(stdout);
@@ -481,14 +486,14 @@
                        NULL,
                        &si,
                        &pi);
-    if(!rc) {
+    if (!rc) {
       // Could not start process for some reason.  Try to report why:
       report_error("Could not start process!");
       exit(126);
     }
 
-    WaitForSingleObject(pi.hProcess,INFINITE);
-    GetExitCodeProcess(pi.hProcess,&exitCode);
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    GetExitCodeProcess(pi.hProcess, &exitCode);
 
     if (getenv("DEBUG_FIXPATH") != NULL) {
       for (i=0; i<num_files_to_delete; ++i) {
--- a/corba/.hgtags	Thu Apr 17 15:22:07 2014 -0700
+++ b/corba/.hgtags	Wed Jul 05 19:37:28 2017 +0200
@@ -251,3 +251,4 @@
 a4bf701ac316946c2e5e83138ad8e687da6a4b30 jdk9-b06
 6c8563600a71394c949405189ddd66267a88d8cd jdk9-b07
 2da7fead826bc27f193c7d63048c2cf100a8809c jdk9-b08
+1a3a4f48515dbf1cff37279691b2fb74f228298d jdk9-b09
--- a/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -52,6 +52,7 @@
 import java.io.DataOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InvalidClassException;
+import java.io.Externalizable;
 import java.io.Serializable;
 
 import java.util.Arrays;
@@ -80,15 +81,15 @@
     public static final long kDefaultUID = -1;
 
     private static Object noArgsList[] = {};
-    private static Class noTypesList[] = {};
+    private static Class<?> noTypesList[] = {};
 
     /** true if represents enum type */
     private boolean isEnum;
 
     private static final Bridge bridge =
-        (Bridge)AccessController.doPrivileged(
-            new PrivilegedAction() {
-                public Object run() {
+        AccessController.doPrivileged(
+            new PrivilegedAction<Bridge>() {
+                public Bridge run() {
                     return Bridge.get() ;
                 }
             }
@@ -98,7 +99,7 @@
      * is returned if the specified class does not implement
      * java.io.Serializable or java.io.Externalizable.
      */
-    static final ObjectStreamClass lookup(Class cl)
+    static final ObjectStreamClass lookup(Class<?> cl)
     {
         ObjectStreamClass desc = lookupInternal(cl);
         if (desc.isSerializable() || desc.isExternalizable())
@@ -110,7 +111,7 @@
      * Find the class descriptor for the specified class.
      * Package access only so it can be called from ObjectIn/OutStream.
      */
-    static ObjectStreamClass lookupInternal(Class cl)
+    static ObjectStreamClass lookupInternal(Class<?> cl)
     {
         /* Synchronize on the hashtable so no two threads will do
          * this at the same time.
@@ -121,14 +122,14 @@
             desc = findDescriptorFor(cl);
             if (desc == null) {
                 /* Check if it's serializable */
-                boolean serializable = classSerializable.isAssignableFrom(cl);
+                boolean serializable = Serializable.class.isAssignableFrom(cl);
 
                 /* If the class is only Serializable,
                  * lookup the descriptor for the superclass.
                  */
                 ObjectStreamClass superdesc = null;
                 if (serializable) {
-                    Class superclass = cl.getSuperclass();
+                    Class<?> superclass = cl.getSuperclass();
                     if (superclass != null)
                         superdesc = lookup(superclass);
                 }
@@ -141,7 +142,7 @@
                 if (serializable) {
                     externalizable =
                         ((superdesc != null) && superdesc.isExternalizable()) ||
-                        classExternalizable.isAssignableFrom(cl);
+                        Externalizable.class.isAssignableFrom(cl);
                     if (externalizable) {
                         serializable = false;
                     }
@@ -185,7 +186,7 @@
      * that have evolved from a common root class and agree to be serialized
      * and deserialized using a common format.
      */
-    public static final long getSerialVersionUID( java.lang.Class clazz) {
+    public static final long getSerialVersionUID( java.lang.Class<?> clazz) {
         ObjectStreamClass theosc = ObjectStreamClass.lookup( clazz );
         if( theosc != null )
         {
@@ -219,7 +220,7 @@
     /**
      * Return the actual (computed) serialVersionUID for this class.
      */
-    public static final long getActualSerialVersionUID( java.lang.Class clazz )
+    public static final long getActualSerialVersionUID( java.lang.Class<?> clazz )
     {
         ObjectStreamClass theosc = ObjectStreamClass.lookup( clazz );
         if( theosc != null )
@@ -249,7 +250,7 @@
      * Return the class in the local VM that this version is mapped to.
      * Null is returned if there is no corresponding local class.
      */
-    public final Class forClass() {
+    public final Class<?> forClass() {
         return ofClass;
     }
 
@@ -349,7 +350,7 @@
      * Create a new ObjectStreamClass from a loaded class.
      * Don't call this directly, call lookup instead.
      */
-    private ObjectStreamClass(java.lang.Class cl, ObjectStreamClass superdesc,
+    private ObjectStreamClass(java.lang.Class<?> cl, ObjectStreamClass superdesc,
                               boolean serial, boolean extern)
     {
         ofClass = cl;           /* created from this class */
@@ -433,7 +434,7 @@
         if (initialized)
             return;
 
-        final Class cl = ofClass;
+        final Class<?> cl = ofClass;
 
         if (!serializable ||
             externalizable ||
@@ -561,9 +562,9 @@
                      * will call it as necessary.
                      */
                     writeObjectMethod = getPrivateMethod( cl, "writeObject",
-                        new Class[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ;
+                        new Class<?>[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ;
                     readObjectMethod = getPrivateMethod( cl, "readObject",
-                        new Class[] { java.io.ObjectInputStream.class }, Void.TYPE ) ;
+                        new Class<?>[] { java.io.ObjectInputStream.class }, Void.TYPE ) ;
                 }
                 return null;
             }
@@ -589,9 +590,9 @@
      * class, or null if none found.  Access checks are disabled on the
      * returned method (if any).
      */
-    private static Method getPrivateMethod(Class cl, String name,
-                                           Class[] argTypes,
-                                           Class returnType)
+    private static Method getPrivateMethod(Class<?> cl, String name,
+                                           Class<?>[] argTypes,
+                                           Class<?> returnType)
     {
         try {
             Method meth = cl.getDeclaredMethod(name, argTypes);
@@ -653,7 +654,7 @@
      * Fill in the reflected Fields that will be used
      * for reading.
      */
-    final void setClass(Class cl) throws InvalidClassException {
+    final void setClass(Class<?> cl) throws InvalidClassException {
 
         if (cl == null) {
             localClassDesc = null;
@@ -920,9 +921,9 @@
      * Access checks are disabled on the returned constructor (if any), since
      * the defining class may still be non-public.
      */
-    private static Constructor getExternalizableConstructor(Class cl) {
+    private static Constructor getExternalizableConstructor(Class<?> cl) {
         try {
-            Constructor cons = cl.getDeclaredConstructor(new Class[0]);
+            Constructor cons = cl.getDeclaredConstructor(new Class<?>[0]);
             cons.setAccessible(true);
             return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
                 cons : null;
@@ -936,15 +937,15 @@
      * superclass, or null if none found.  Access checks are disabled on the
      * returned constructor (if any).
      */
-    private static Constructor getSerializableConstructor(Class cl) {
-        Class initCl = cl;
+    private static Constructor getSerializableConstructor(Class<?> cl) {
+        Class<?> initCl = cl;
         while (Serializable.class.isAssignableFrom(initCl)) {
             if ((initCl = initCl.getSuperclass()) == null) {
                 return null;
             }
         }
         try {
-            Constructor cons = initCl.getDeclaredConstructor(new Class[0]);
+            Constructor cons = initCl.getDeclaredConstructor(new Class<?>[0]);
             int mods = cons.getModifiers();
             if ((mods & Modifier.PRIVATE) != 0 ||
                 ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
@@ -1049,7 +1050,7 @@
      * items to the hash accumulating in the digest stream.
      * Fold the hash into a long.  Use the SHA secure hash function.
      */
-    private static long _computeSerialVersionUID(Class cl) {
+    private static long _computeSerialVersionUID(Class<?> cl) {
         if (DEBUG_SVUID)
             msg( "Computing SerialVersionUID for " + cl ) ;
         ByteArrayOutputStream devnull = new ByteArrayOutputStream(512);
@@ -1103,7 +1104,7 @@
                  * them from its computation.
                  */
 
-                Class interfaces[] = cl.getInterfaces();
+                Class<?> interfaces[] = cl.getInterfaces();
                 Arrays.sort(interfaces, compareClassByName);
 
                 for (int i = 0; i < interfaces.length; i++) {
@@ -1233,7 +1234,7 @@
         return h;
     }
 
-    private static long computeStructuralUID(com.sun.corba.se.impl.io.ObjectStreamClass osc, Class cl) {
+    private static long computeStructuralUID(com.sun.corba.se.impl.io.ObjectStreamClass osc, Class<?> cl) {
         ByteArrayOutputStream devnull = new ByteArrayOutputStream(512);
 
         long h = 0;
@@ -1253,7 +1254,7 @@
             DataOutputStream data = new DataOutputStream(mdo);
 
             // Get SUID of parent
-            Class parent = cl.getSuperclass();
+            Class<?> parent = cl.getSuperclass();
             if ((parent != null))
             // SerialBug 1; acc. to spec the one for
             // java.lang.object
@@ -1309,10 +1310,10 @@
     /**
      * Compute the JVM signature for the class.
      */
-    static String getSignature(Class clazz) {
+    static String getSignature(Class<?> clazz) {
         String type = null;
         if (clazz.isArray()) {
-            Class cl = clazz;
+            Class<?> cl = clazz;
             int dimensions = 0;
             while (cl.isArray()) {
                 dimensions++;
@@ -1358,7 +1359,7 @@
 
         sb.append("(");
 
-        Class[] params = meth.getParameterTypes(); // avoid clone
+        Class<?>[] params = meth.getParameterTypes(); // avoid clone
         for (int j = 0; j < params.length; j++) {
             sb.append(getSignature(params[j]));
         }
@@ -1375,7 +1376,7 @@
 
         sb.append("(");
 
-        Class[] params = cons.getParameterTypes(); // avoid clone
+        Class<?>[] params = cons.getParameterTypes(); // avoid clone
         for (int j = 0; j < params.length; j++) {
             sb.append(getSignature(params[j]));
         }
@@ -1395,7 +1396,7 @@
      * The entries are extended from java.lang.ref.SoftReference so the
      * gc will be able to free them if needed.
      */
-    private static ObjectStreamClass findDescriptorFor(Class cl) {
+    private static ObjectStreamClass findDescriptorFor(Class<?> cl) {
 
         int hash = cl.hashCode();
         int index = (hash & 0x7FFFFFFF) % descriptorFor.length;
@@ -1442,7 +1443,7 @@
         descriptorFor[index] = e;
     }
 
-    private static Field[] getDeclaredFields(final Class clz) {
+    private static Field[] getDeclaredFields(final Class<?> clz) {
         return (Field[]) AccessController.doPrivileged(new PrivilegedAction() {
             public Object run() {
                 return clz.getDeclaredFields();
@@ -1476,7 +1477,7 @@
     /*
      * Class that is a descriptor for in this virtual machine.
      */
-    private Class ofClass;
+    private Class<?> ofClass;
 
     /*
      * True if descriptor for a proxy class.
@@ -1548,30 +1549,17 @@
      * Returns true if the given class defines a static initializer method,
      * false otherwise.
      */
-    private static boolean hasStaticInitializer(Class cl) {
+    private static boolean hasStaticInitializer(Class<?> cl) {
         if (hasStaticInitializerMethod == null) {
-            Class classWithThisMethod = null;
+            Class<?> classWithThisMethod = null;
 
             try {
-                try {
-                    // When using rip-int with Merlin or when this is a Merlin
-                    // workspace, the method we want is in sun.misc.ClassReflector
-                    // and absent from java.io.ObjectStreamClass.
-                    //
-                    // When compiling rip-int with JDK 1.3.x, we have to get it
-                    // from java.io.ObjectStreamClass.
-                    classWithThisMethod = Class.forName("sun.misc.ClassReflector");
-                } catch (ClassNotFoundException cnfe) {
-                    // Do nothing.  This is either not a Merlin workspace,
-                    // or rip-int is being compiled with something other than
-                    // Merlin, probably JDK 1.3.  Fall back on java.io.ObjectStreaClass.
-                }
                 if (classWithThisMethod == null)
                     classWithThisMethod = java.io.ObjectStreamClass.class;
 
                 hasStaticInitializerMethod =
                     classWithThisMethod.getDeclaredMethod("hasStaticInitializer",
-                                                          new Class[] { Class.class });
+                                                          new Class<?>[] { Class.class });
             } catch (NoSuchMethodException ex) {
             }
 
@@ -1596,22 +1584,6 @@
     }
 
 
-    /* The Class Object for java.io.Serializable */
-    private static Class classSerializable = null;
-    private static Class classExternalizable = null;
-
-    /*
-     * Resolve java.io.Serializable at load time.
-     */
-    static {
-        try {
-            classSerializable = Class.forName("java.io.Serializable");
-            classExternalizable = Class.forName("java.io.Externalizable");
-        } catch (Throwable e) {
-            System.err.println("Could not load java.io.Serializable or java.io.Externalizable.");
-        }
-    }
-
     /** use serialVersionUID from JDK 1.1. for interoperability */
     private static final long serialVersionUID = -6120832682080437368L;
 
@@ -1649,8 +1621,8 @@
 
     private static class CompareClassByName implements Comparator {
         public int compare(Object o1, Object o2) {
-            Class c1 = (Class)o1;
-            Class c2 = (Class)o2;
+            Class<?> c1 = (Class)o1;
+            Class<?> c2 = (Class)o2;
             return (c1.getName()).compareTo(c2.getName());
         }
     }
@@ -1764,12 +1736,12 @@
      *
      * Copied from the Merlin java.io.ObjectStreamClass.
      */
-    private static Method getInheritableMethod(Class cl, String name,
-                                               Class[] argTypes,
-                                               Class returnType)
+    private static Method getInheritableMethod(Class<?> cl, String name,
+                                               Class<?>[] argTypes,
+                                               Class<?> returnType)
     {
         Method meth = null;
-        Class defCl = cl;
+        Class<?> defCl = cl;
         while (defCl != null) {
             try {
                 meth = defCl.getDeclaredMethod(name, argTypes);
@@ -1801,7 +1773,7 @@
      *
      * Copied from the Merlin java.io.ObjectStreamClass.
      */
-    private static boolean packageEquals(Class cl1, Class cl2) {
+    private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
         Package pkg1 = cl1.getPackage(), pkg2 = cl2.getPackage();
         return ((pkg1 == pkg2) || ((pkg1 != null) && (pkg1.equals(pkg2))));
     }
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClassUtil_1_3.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClassUtil_1_3.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -94,7 +94,7 @@
         });
     }
 
-    public static long computeStructuralUID(boolean hasWriteObject, Class cl) {
+    public static long computeStructuralUID(boolean hasWriteObject, Class<?> cl) {
         ByteArrayOutputStream devnull = new ByteArrayOutputStream(512);
 
         long h = 0;
@@ -119,7 +119,7 @@
             // Object method in there
 
             // Get SUID of parent
-            Class parent = cl.getSuperclass();
+            Class<?> parent = cl.getSuperclass();
             if ((parent != null) && (parent != java.lang.Object.class)) {
                 boolean hasWriteObjectFlag = false;
                 Class [] args = {java.io.ObjectOutputStream.class};
@@ -503,19 +503,6 @@
             Class classWithThisMethod = null;
 
             try {
-                try {
-                    // When using rip-int with Merlin or when this is a Merlin
-                    // workspace, the method we want is in sun.misc.ClassReflector
-                    // and absent from java.io.ObjectStreamClass.
-                    //
-                    // When compiling rip-int with JDK 1.3.x, we have to get it
-                    // from java.io.ObjectStreamClass.
-                    classWithThisMethod = Class.forName("sun.misc.ClassReflector");
-                } catch (ClassNotFoundException cnfe) {
-                    // Do nothing.  This is either not a Merlin workspace,
-                    // or rip-int is being compiled with something other than
-                    // Merlin, probably JDK 1.3.  Fall back on java.io.ObjectStreaClass.
-                }
                 if (classWithThisMethod == null)
                     classWithThisMethod = java.io.ObjectStreamClass.class;
 
--- a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -53,6 +53,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.InvalidClassException;
 import java.io.Serializable;
+import java.io.Externalizable;
 
 import java.util.Arrays;
 import java.util.Comparator;
@@ -88,7 +89,7 @@
     public static final long kDefaultUID = -1;
 
     private static Object noArgsList[] = {};
-    private static Class noTypesList[] = {};
+    private static Class<?> noTypesList[] = {};
 
     private static Hashtable translatedFields;
 
@@ -96,7 +97,7 @@
      * is returned if the specified class does not implement
      * java.io.Serializable or java.io.Externalizable.
      */
-    static final ObjectStreamClass_1_3_1 lookup(Class cl)
+    static final ObjectStreamClass_1_3_1 lookup(Class<?> cl)
     {
         ObjectStreamClass_1_3_1 desc = lookupInternal(cl);
         if (desc.isSerializable() || desc.isExternalizable())
@@ -108,7 +109,7 @@
      * Find the class descriptor for the specified class.
      * Package access only so it can be called from ObjectIn/OutStream.
      */
-    static ObjectStreamClass_1_3_1 lookupInternal(Class cl)
+    static ObjectStreamClass_1_3_1 lookupInternal(Class<?> cl)
     {
         /* Synchronize on the hashtable so no two threads will do
          * this at the same time.
@@ -122,13 +123,13 @@
             }
 
                 /* Check if it's serializable */
-                boolean serializable = classSerializable.isAssignableFrom(cl);
+                boolean serializable = Serializable.class.isAssignableFrom(cl);
                 /* If the class is only Serializable,
                  * lookup the descriptor for the superclass.
                  */
                 ObjectStreamClass_1_3_1 superdesc = null;
                 if (serializable) {
-                    Class superclass = cl.getSuperclass();
+                    Class<?> superclass = cl.getSuperclass();
                     if (superclass != null)
                         superdesc = lookup(superclass);
                 }
@@ -141,7 +142,7 @@
                 if (serializable) {
                     externalizable =
                         ((superdesc != null) && superdesc.isExternalizable()) ||
-                        classExternalizable.isAssignableFrom(cl);
+                        Externalizable.class.isAssignableFrom(cl);
                     if (externalizable) {
                         serializable = false;
                     }
@@ -170,7 +171,7 @@
      * that have evolved from a common root class and agree to be serialized
      * and deserialized using a common format.
      */
-    public static final long getSerialVersionUID( java.lang.Class clazz) {
+    public static final long getSerialVersionUID( java.lang.Class<?> clazz) {
         ObjectStreamClass_1_3_1 theosc = ObjectStreamClass_1_3_1.lookup( clazz );
         if( theosc != null )
         {
@@ -204,7 +205,7 @@
     /**
      * Return the actual (computed) serialVersionUID for this class.
      */
-    public static final long getActualSerialVersionUID( java.lang.Class clazz )
+    public static final long getActualSerialVersionUID( java.lang.Class<?> clazz )
     {
         ObjectStreamClass_1_3_1 theosc = ObjectStreamClass_1_3_1.lookup( clazz );
         if( theosc != null )
@@ -234,7 +235,7 @@
      * Return the class in the local VM that this version is mapped to.
      * Null is returned if there is no corresponding local class.
      */
-    public final Class forClass() {
+    public final Class<?> forClass() {
         return ofClass;
     }
 
@@ -333,7 +334,7 @@
      * Create a new ObjectStreamClass_1_3_1 from a loaded class.
      * Don't call this directly, call lookup instead.
      */
-    private ObjectStreamClass_1_3_1(java.lang.Class cl, ObjectStreamClass_1_3_1 superdesc,
+    private ObjectStreamClass_1_3_1(java.lang.Class<?> cl, ObjectStreamClass_1_3_1 superdesc,
                               boolean serial, boolean extern)
     {
         ofClass = cl;           /* created from this class */
@@ -376,7 +377,7 @@
     private void init() {
       synchronized (lock) {
 
-        final Class cl = ofClass;
+        final Class<?> cl = ofClass;
 
         if (fields != null) // already initialized
                 return;
@@ -558,7 +559,7 @@
                      * will call it as necessary.
                      */
                     try {
-                      Class[] args = {java.io.ObjectOutputStream.class};
+                      Class<?>[] args = {java.io.ObjectOutputStream.class};
                       writeObjectMethod = cl.getDeclaredMethod("writeObject", args);
                       hasWriteObjectMethod = true;
                       int mods = writeObjectMethod.getModifiers();
@@ -578,7 +579,7 @@
                      * ObjectInputStream so it can all the method directly.
                      */
                     try {
-                      Class[] args = {java.io.ObjectInputStream.class};
+                      Class<?>[] args = {java.io.ObjectInputStream.class};
                       readObjectMethod = cl.getDeclaredMethod("readObject", args);
                       int mods = readObjectMethod.getModifiers();
 
@@ -629,11 +630,11 @@
             if (translation != null)
                 return translation;
             else {
-                Class osfClass = com.sun.corba.se.impl.orbutil.ObjectStreamField.class;
+                Class<?> osfClass = com.sun.corba.se.impl.orbutil.ObjectStreamField.class;
 
                 translation = (Object[])java.lang.reflect.Array.newInstance(osfClass, objs.length);
                 Object arg[] = new Object[2];
-                Class types[] = {String.class, Class.class};
+                Class<?> types[] = {String.class, Class.class};
                 Constructor constructor = osfClass.getDeclaredConstructor(types);
                 for (int i = fields.length -1; i >= 0; i--){
                     arg[0] = fields[i].getName();
@@ -804,7 +805,7 @@
         }
     }
 
-    private static long computeStructuralUID(ObjectStreamClass_1_3_1 osc, Class cl) {
+    private static long computeStructuralUID(ObjectStreamClass_1_3_1 osc, Class<?> cl) {
         ByteArrayOutputStream devnull = new ByteArrayOutputStream(512);
 
         long h = 0;
@@ -824,7 +825,7 @@
             DataOutputStream data = new DataOutputStream(mdo);
 
             // Get SUID of parent
-            Class parent = cl.getSuperclass();
+            Class<?> parent = cl.getSuperclass();
             if ((parent != null))
             // SerialBug 1; acc. to spec the one for
             // java.lang.object
@@ -910,10 +911,10 @@
     /**
      * Compute the JVM signature for the class.
      */
-    static String getSignature(Class clazz) {
+    static String getSignature(Class<?> clazz) {
         String type = null;
         if (clazz.isArray()) {
-            Class cl = clazz;
+            Class<?> cl = clazz;
             int dimensions = 0;
             while (cl.isArray()) {
                 dimensions++;
@@ -959,7 +960,7 @@
 
         sb.append("(");
 
-        Class[] params = meth.getParameterTypes(); // avoid clone
+        Class<?>[] params = meth.getParameterTypes(); // avoid clone
         for (int j = 0; j < params.length; j++) {
             sb.append(getSignature(params[j]));
         }
@@ -976,7 +977,7 @@
 
         sb.append("(");
 
-        Class[] params = cons.getParameterTypes(); // avoid clone
+        Class<?>[] params = cons.getParameterTypes(); // avoid clone
         for (int j = 0; j < params.length; j++) {
             sb.append(getSignature(params[j]));
         }
@@ -996,7 +997,7 @@
      * The entries are extended from java.lang.ref.SoftReference so the
      * gc will be able to free them if needed.
      */
-    private static ObjectStreamClass_1_3_1 findDescriptorFor(Class cl) {
+    private static ObjectStreamClass_1_3_1 findDescriptorFor(Class<?> cl) {
 
         int hash = cl.hashCode();
         int index = (hash & 0x7FFFFFFF) % descriptorFor.length;
@@ -1077,7 +1078,7 @@
     /*
      * Class that is a descriptor for in this virtual machine.
      */
-    private Class ofClass;
+    private Class<?> ofClass;
 
     /*
      * True if descriptor for a proxy class.
@@ -1130,22 +1131,6 @@
     /* Get the private static final field for serial version UID */
     // private static native long getSerialVersionUIDField(Class cl);
 
-    /* The Class Object for java.io.Serializable */
-    private static Class classSerializable = null;
-    private static Class classExternalizable = null;
-
-    /*
-     * Resolve java.io.Serializable at load time.
-     */
-    static {
-        try {
-            classSerializable = Class.forName("java.io.Serializable");
-            classExternalizable = Class.forName("java.io.Externalizable");
-        } catch (Throwable e) {
-            System.err.println("Could not load java.io.Serializable or java.io.Externalizable.");
-        }
-    }
-
     /** use serialVersionUID from JDK 1.1. for interoperability */
     private static final long serialVersionUID = -6120832682080437368L;
 
@@ -1183,8 +1168,8 @@
 
     private static class CompareClassByName implements Comparator {
         public int compare(Object o1, Object o2) {
-            Class c1 = (Class)o1;
-            Class c2 = (Class)o2;
+            Class<?> c1 = (Class)o1;
+            Class<?> c2 = (Class)o2;
             return (c1.getName()).compareTo(c2.getName());
         }
     }
--- a/corba/src/share/classes/org/omg/CORBA/ORB.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/corba/src/share/classes/org/omg/CORBA/ORB.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -36,6 +36,8 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
+import sun.reflect.misc.ReflectUtil;
+
 /**
  * A class providing APIs for the CORBA Object Request Broker
  * features.  The <code>ORB</code> class also provides
@@ -161,6 +163,20 @@
  * <P>
  * An application or applet can be initialized in one or more ORBs.
  * ORB initialization is a bootstrap call into the CORBA world.
+ *
+ *
+ * @implNote
+ * As described above it is possible to specify, at runtime, an alternative ORBSingleton class and
+ * an alternative ORB implementation class, via the system properties {@code org.omg.CORBA.ORBSingletonClass}
+ * and {@code org.omg.CORBA.ORBClass} respectively.
+ * The class loading strategy is organized, such that, in the case of the ORBSingleton
+ * the system class loader is used to load the alternative singleton ORB.
+ * Thus, it is necessary that an application's CLASSPATH
+ * includes the classes for this alternative ORBSingleton, when specified.
+ *
+ * In the case of specifying an alternative ORB implementation class, the loading
+ * strategy will use the thread context class loader, as appropriate.
+ *
  * @since   JDK1.2
  */
 abstract public class ORB {
@@ -289,20 +305,38 @@
                     (className.equals("com.sun.corba.se.impl.orb.ORBSingleton"))) {
                 singleton = new com.sun.corba.se.impl.orb.ORBSingleton();
             } else {
-                singleton = create_impl(className);
+                singleton = create_impl_with_systemclassloader(className);
             }
         }
         return singleton;
     }
 
+   private static ORB create_impl_with_systemclassloader(String className) {
+
+        try {
+            ReflectUtil.checkPackageAccess(className);
+            ClassLoader cl = ClassLoader.getSystemClassLoader();
+            Class<org.omg.CORBA.ORB> orbBaseClass = org.omg.CORBA.ORB.class;
+            Class<?> singletonOrbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass);
+            return (ORB)singletonOrbClass.newInstance();
+        } catch (Throwable ex) {
+            SystemException systemException = new INITIALIZE(
+                "can't instantiate default ORB implementation " + className);
+            systemException.initCause(ex);
+            throw systemException;
+        }
+    }
+
     private static ORB create_impl(String className) {
-
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         if (cl == null)
             cl = ClassLoader.getSystemClassLoader();
 
         try {
-            return (ORB) Class.forName(className, true, cl).newInstance();
+            ReflectUtil.checkPackageAccess(className);
+            Class<org.omg.CORBA.ORB> orbBaseClass = org.omg.CORBA.ORB.class;
+            Class<?> orbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass);
+            return (ORB)orbClass.newInstance();
         } catch (Throwable ex) {
             SystemException systemException = new INITIALIZE(
                "can't instantiate default ORB implementation " + className);
@@ -346,7 +380,6 @@
         } else {
             orb = create_impl(className);
         }
-
         orb.set_parameters(args, props);
         return orb;
     }
@@ -377,7 +410,6 @@
         } else {
             orb = create_impl(className);
         }
-
         orb.set_parameters(app, props);
         return orb;
     }
@@ -573,7 +605,7 @@
         try {
             // First try to load the OperationDef class
             String opDefClassName = "org.omg.CORBA.OperationDef";
-            Class opDefClass = null;
+            Class<?> opDefClass = null;
 
             ClassLoader cl = Thread.currentThread().getContextClassLoader();
             if ( cl == null )
@@ -583,7 +615,7 @@
 
             // OK, we loaded OperationDef. Now try to get the
             // create_operation_list(OperationDef oper) method.
-            Class[] argc = { opDefClass };
+            Class<?>[] argc = { opDefClass };
             java.lang.reflect.Method meth =
                 this.getClass().getMethod("create_operation_list", argc);
 
--- a/hotspot/.hgtags	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 19:37:28 2017 +0200
@@ -411,3 +411,4 @@
 52377a30a3f87b62d6135706997b8c7a47366e37 jdk9-b06
 52f7edf2589d9f9d35db3008bc5377f279de9c18 jdk9-b07
 4dedef5e51ed3a36677a8ba82949fc517ad64162 jdk9-b08
+05e8f5242c26ba45d4fa947e4f4f54c058c9b522 jdk9-b09
--- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -958,7 +958,7 @@
 
   // reset handle block
   __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), G3_scratch);
-  __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes());
+  __ st(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes());
 
 
   // handle exceptions (exception handling will handle unlocking!)
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -2687,7 +2687,7 @@
   if (!is_critical_native) {
     // reset handle block
     __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), L5);
-    __ st_ptr(G0, L5, JNIHandleBlock::top_offset_in_bytes());
+    __ st(G0, L5, JNIHandleBlock::top_offset_in_bytes());
 
     __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), G3_scratch);
     check_forward_pending_exception(masm, G3_scratch);
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1147,7 +1147,7 @@
 
   // reset handle block
   __ ld_ptr(G2_thread, JavaThread::active_handles_offset(), G3_scratch);
-  __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes());
+  __ st(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes());
 
   // If we have an oop result store it where it will be safe for any further gc
   // until we return now that we've released the handle it might be protected by
--- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1358,7 +1358,7 @@
 
   // reset handle block
   __ movptr(t, Address(thread, JavaThread::active_handles_offset()));
-  __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD);
+  __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD);
 
   // If result was an oop then unbox and save it in the frame
   { Label L;
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -162,7 +162,7 @@
           "Number of milliseconds to wait before start calculating aborts " \
           "for RTM locking")                                                \
                                                                             \
-  experimental(bool, UseRTMXendForLockBusy, false,                          \
+  experimental(bool, UseRTMXendForLockBusy, true,                           \
           "Use RTM Xend instead of Xabort when lock busy")                  \
                                                                             \
   /* assembler */                                                           \
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1488,11 +1488,10 @@
     movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort
     bind(L_rtm_retry);
   }
-  if (!UseRTMXendForLockBusy) {
-    movptr(tmpReg, Address(objReg, 0));
-    testptr(tmpReg, markOopDesc::monitor_value);  // inflated vs stack-locked|neutral|biased
-    jcc(Assembler::notZero, IsInflated);
-  }
+  movptr(tmpReg, Address(objReg, 0));
+  testptr(tmpReg, markOopDesc::monitor_value);  // inflated vs stack-locked|neutral|biased
+  jcc(Assembler::notZero, IsInflated);
+
   if (PrintPreciseRTMLockingStatistics || profile_rtm) {
     Label L_noincrement;
     if (RTMTotalCountIncrRate > 1) {
@@ -1512,10 +1511,7 @@
   Register abort_status_Reg = tmpReg; // status of abort is stored in RAX
   if (UseRTMXendForLockBusy) {
     xend();
-    movptr(tmpReg, Address(objReg, 0));
-    testptr(tmpReg, markOopDesc::monitor_value);  // inflated vs stack-locked|neutral|biased
-    jcc(Assembler::notZero, IsInflated);
-    movptr(abort_status_Reg, 0x1);                // Set the abort status to 1 (as xabort does)
+    movptr(abort_status_Reg, 0x2);   // Set the abort status to 2 (so we can retry)
     jmp(L_decrement_retry);
   }
   else {
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -2266,7 +2266,7 @@
   if (!is_critical_native) {
     // reset handle block
     __ movptr(rcx, Address(thread, JavaThread::active_handles_offset()));
-    __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD);
+    __ movl(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD);
 
     // Any exception pending?
     __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD);
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -2509,7 +2509,7 @@
   if (!is_critical_native) {
     // reset handle block
     __ movptr(rcx, Address(r15_thread, JavaThread::active_handles_offset()));
-    __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD);
+    __ movl(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD);
   }
 
   // pop our frame
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1287,7 +1287,7 @@
 
   // reset handle block
   __ movptr(t, Address(thread, JavaThread::active_handles_offset()));
-  __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD);
+  __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD);
 
   // If result was an oop then unbox and save it in the frame
   { Label L;
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1259,7 +1259,7 @@
 
   // reset handle block
   __ movptr(t, Address(r15_thread, JavaThread::active_handles_offset()));
-  __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD);
+  __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD);
 
   // If result is an oop unbox and store it in frame where gc will see it
   // and result handler will pick it up
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -2811,18 +2811,13 @@
 
 os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN; }
 
-void os::yield_all(int attempts) {
+void os::yield_all() {
   // Yields to all threads, including threads with lower priorities
   // Threads on Linux are all with same priority. The Solaris style
   // os::yield_all() with nanosleep(1ms) is not necessary.
   sched_yield();
 }
 
-// Called from the tight loops to possibly influence time-sharing heuristics
-void os::loop_breaker(int attempts) {
-  os::yield_all(attempts);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // thread priority support
 
@@ -3079,7 +3074,7 @@
 
   for (int n = 0; !osthread->sr.is_suspended(); n++) {
     for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) {
-      os::yield_all(i);
+      os::yield_all();
     }
 
     // timeout, try to cancel the request
@@ -3113,7 +3108,7 @@
     if (sr_notify(osthread) == 0) {
       for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) {
         for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) {
-          os::yield_all(i);
+          os::yield_all();
         }
       }
     } else {
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -917,9 +917,20 @@
 //////////////////////////////////////////////////////////////////////////////
 // thread local storage
 
+// Restore the thread pointer if the destructor is called. This is in case
+// someone from JNI code sets up a destructor with pthread_key_create to run
+// detachCurrentThread on thread death. Unless we restore the thread pointer we
+// will hang or crash. When detachCurrentThread is called the key will be set
+// to null and we will not be called again. If detachCurrentThread is never
+// called we could loop forever depending on the pthread implementation.
+static void restore_thread_pointer(void* p) {
+  Thread* thread = (Thread*) p;
+  os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
+}
+
 int os::allocate_thread_local_storage() {
   pthread_key_t key;
-  int rslt = pthread_key_create(&key, NULL);
+  int rslt = pthread_key_create(&key, restore_thread_pointer);
   assert(rslt == 0, "cannot allocate thread local storage");
   return (int)key;
 }
@@ -2551,18 +2562,13 @@
 
 os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;}
 
-void os::yield_all(int attempts) {
+void os::yield_all() {
   // Yields to all threads, including threads with lower priorities
   // Threads on Bsd are all with same priority. The Solaris style
   // os::yield_all() with nanosleep(1ms) is not necessary.
   sched_yield();
 }
 
-// Called from the tight loops to possibly influence time-sharing heuristics
-void os::loop_breaker(int attempts) {
-  os::yield_all(attempts);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // thread priority support
 
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1032,9 +1032,20 @@
 //////////////////////////////////////////////////////////////////////////////
 // thread local storage
 
+// Restore the thread pointer if the destructor is called. This is in case
+// someone from JNI code sets up a destructor with pthread_key_create to run
+// detachCurrentThread on thread death. Unless we restore the thread pointer we
+// will hang or crash. When detachCurrentThread is called the key will be set
+// to null and we will not be called again. If detachCurrentThread is never
+// called we could loop forever depending on the pthread implementation.
+static void restore_thread_pointer(void* p) {
+  Thread* thread = (Thread*) p;
+  os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
+}
+
 int os::allocate_thread_local_storage() {
   pthread_key_t key;
-  int rslt = pthread_key_create(&key, NULL);
+  int rslt = pthread_key_create(&key, restore_thread_pointer);
   assert(rslt == 0, "cannot allocate thread local storage");
   return (int)key;
 }
@@ -3781,18 +3792,13 @@
 
 os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;}
 
-void os::yield_all(int attempts) {
+void os::yield_all() {
   // Yields to all threads, including threads with lower priorities
   // Threads on Linux are all with same priority. The Solaris style
   // os::yield_all() with nanosleep(1ms) is not necessary.
   sched_yield();
 }
 
-// Called from the tight loops to possibly influence time-sharing heuristics
-void os::loop_breaker(int attempts) {
-  os::yield_all(attempts);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // thread priority support
 
--- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -29,6 +29,7 @@
 #include "services/dtraceAttacher.hpp"
 
 #include <door.h>
+#include <limits.h>
 #include <string.h>
 #include <signal.h>
 #include <sys/types.h>
@@ -668,11 +669,13 @@
     out->print_cr("No probe specified");
     return JNI_ERR;
   } else {
-    int probe_typess = atoi(probe);
-    if (errno) {
+    char *end;
+    long val = strtol(probe, &end, 10);
+    if (end == probe || val < 0 || val > INT_MAX) {
       out->print_cr("invalid probe type");
       return JNI_ERR;
     } else {
+      int probe_typess = (int) val;
       DTrace::enable_dprobes(probe_typess);
       return JNI_OK;
     }
@@ -703,8 +706,9 @@
   bool flag = true;
   const char* arg1;
   if ((arg1 = op->arg(1)) != NULL) {
-    flag = (atoi(arg1) != 0);
-    if (errno) {
+    char *end;
+    flag = (strtol(arg1, &end, 10) != 0);
+    if (arg1 == end) {
       out->print_cr("flag value has to be an integer");
       return JNI_ERR;
     }
--- a/hotspot/src/os/solaris/vm/osThread_solaris.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/solaris/vm/osThread_solaris.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -49,16 +49,6 @@
 
 // copied from synchronizer.cpp
 
-void OSThread::handle_spinlock_contention(int tries) {
-  if (NoYieldsInMicrolock) return;
-
-  if (tries > 10) {
-    os::yield_all(tries); // Yield to threads of any priority
-  } else if (tries > 5) {
-    os::yield();          // Yield to threads of same or higher priority
-  }
-}
-
 void OSThread::SR_handler(Thread* thread, ucontext_t* uc) {
   os::Solaris::SR_handler(thread, uc);
 }
--- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -82,8 +82,6 @@
   void set_ucontext(ucontext_t* ptr) { _ucontext = ptr; }
   static void SR_handler(Thread* thread, ucontext_t* uc);
 
-  static void       handle_spinlock_contention(int tries);                      // Used for thread local eden locking
-
   // ***************************************************************
   // Platform dependent initialization and cleanup
   // ***************************************************************
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -969,9 +969,6 @@
   return true;
 }
 
-// _T2_libthread is true if we believe we are running with the newer
-// SunSoft lwp/libthread.so (2.8 patch, 2.9 default)
-bool os::Solaris::_T2_libthread = false;
 
 bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
   // Allocate the OSThread object
@@ -1056,71 +1053,10 @@
   thread->set_osthread(osthread);
 
   // Create the Solaris thread
-  // explicit THR_BOUND for T2_libthread case in case
-  // that assumption is not accurate, but our alternate signal stack
-  // handling is based on it which must have bound threads
   thread_t tid = 0;
-  long     flags = (UseDetachedThreads ? THR_DETACHED : 0) | THR_SUSPENDED
-                   | ((UseBoundThreads || os::Solaris::T2_libthread() ||
-                       (thr_type == vm_thread) ||
-                       (thr_type == cgc_thread) ||
-                       (thr_type == pgc_thread) ||
-                       (thr_type == compiler_thread && BackgroundCompilation)) ?
-                      THR_BOUND : 0);
+  long     flags = (UseDetachedThreads ? THR_DETACHED : 0) | THR_SUSPENDED;
   int      status;
 
-  // 4376845 -- libthread/kernel don't provide enough LWPs to utilize all CPUs.
-  //
-  // On multiprocessors systems, libthread sometimes under-provisions our
-  // process with LWPs.  On a 30-way systems, for instance, we could have
-  // 50 user-level threads in ready state and only 2 or 3 LWPs assigned
-  // to our process.  This can result in under utilization of PEs.
-  // I suspect the problem is related to libthread's LWP
-  // pool management and to the kernel's SIGBLOCKING "last LWP parked"
-  // upcall policy.
-  //
-  // The following code is palliative -- it attempts to ensure that our
-  // process has sufficient LWPs to take advantage of multiple PEs.
-  // Proper long-term cures include using user-level threads bound to LWPs
-  // (THR_BOUND) or using LWP-based synchronization.  Note that there is a
-  // slight timing window with respect to sampling _os_thread_count, but
-  // the race is benign.  Also, we should periodically recompute
-  // _processors_online as the min of SC_NPROCESSORS_ONLN and the
-  // the number of PEs in our partition.  You might be tempted to use
-  // THR_NEW_LWP here, but I'd recommend against it as that could
-  // result in undesirable growth of the libthread's LWP pool.
-  // The fix below isn't sufficient; for instance, it doesn't take into count
-  // LWPs parked on IO.  It does, however, help certain CPU-bound benchmarks.
-  //
-  // Some pathologies this scheme doesn't handle:
-  // *  Threads can block, releasing the LWPs.  The LWPs can age out.
-  //    When a large number of threads become ready again there aren't
-  //    enough LWPs available to service them.  This can occur when the
-  //    number of ready threads oscillates.
-  // *  LWPs/Threads park on IO, thus taking the LWP out of circulation.
-  //
-  // Finally, we should call thr_setconcurrency() periodically to refresh
-  // the LWP pool and thwart the LWP age-out mechanism.
-  // The "+3" term provides a little slop -- we want to slightly overprovision.
-
-  if (AdjustConcurrency && os::Solaris::_os_thread_count < (_processors_online+3)) {
-    if (!(flags & THR_BOUND)) {
-      thr_setconcurrency (os::Solaris::_os_thread_count);       // avoid starvation
-    }
-  }
-  // Although this doesn't hurt, we should warn of undefined behavior
-  // when using unbound T1 threads with schedctl().  This should never
-  // happen, as the compiler and VM threads are always created bound
-  DEBUG_ONLY(
-      if ((VMThreadHintNoPreempt || CompilerThreadHintNoPreempt) &&
-          (!os::Solaris::T2_libthread() && (!(flags & THR_BOUND))) &&
-          ((thr_type == vm_thread) || (thr_type == cgc_thread) ||
-           (thr_type == pgc_thread) || (thr_type == compiler_thread && BackgroundCompilation))) {
-         warning("schedctl behavior undefined when Compiler/VM/GC Threads are Unbound");
-      }
-  );
-
-
   // Mark that we don't have an lwp or thread id yet.
   // In case we attempt to set the priority before the thread starts.
   osthread->set_lwp_id(-1);
@@ -1145,13 +1081,6 @@
   // Remember that we created this thread so we can set priority on it
   osthread->set_vm_created();
 
-  // Set the default thread priority.  If using bound threads, setting
-  // lwp priority will be delayed until thread start.
-  set_native_priority(thread,
-                      DefaultThreadPriority == -1 ?
-                        java_to_os_priority[NormPriority] :
-                        DefaultThreadPriority);
-
   // Initial thread state is INITIALIZED, not SUSPENDED
   osthread->set_state(INITIALIZED);
 
@@ -1333,39 +1262,8 @@
     jt->set_stack_size(stack_size);
   }
 
-   // 5/22/01: Right now alternate signal stacks do not handle
-   // throwing stack overflow exceptions, see bug 4463178
-   // Until a fix is found for this, T2 will NOT imply alternate signal
-   // stacks.
-   // If using T2 libthread threads, install an alternate signal stack.
-   // Because alternate stacks associate with LWPs on Solaris,
-   // see sigaltstack(2), if using UNBOUND threads, or if UseBoundThreads
-   // we prefer to explicitly stack bang.
-   // If not using T2 libthread, but using UseBoundThreads any threads
-   // (primordial thread, jni_attachCurrentThread) we do not create,
-   // probably are not bound, therefore they can not have an alternate
-   // signal stack. Since our stack banging code is generated and
-   // is shared across threads, all threads must be bound to allow
-   // using alternate signal stacks.  The alternative is to interpose
-   // on _lwp_create to associate an alt sig stack with each LWP,
-   // and this could be a problem when the JVM is embedded.
-   // We would prefer to use alternate signal stacks with T2
-   // Since there is currently no accurate way to detect T2
-   // we do not. Assuming T2 when running T1 causes sig 11s or assertions
-   // on installing alternate signal stacks
-
-
-   // 05/09/03: removed alternate signal stack support for Solaris
-   // The alternate signal stack mechanism is no longer needed to
-   // handle stack overflow. This is now handled by allocating
-   // guard pages (red zone) and stackbanging.
-   // Initially the alternate signal stack mechanism was removed because
-   // it did not work with T1 llibthread. Alternate
-   // signal stacks MUST have all threads bound to lwps. Applications
-   // can create their own threads and attach them without their being
-   // bound under T1. This is frequently the case for the primordial thread.
-   // If we were ever to reenable this mechanism we would need to
-   // use the dynamic check for T2 libthread.
+  // With the T2 libthread (T1 is no longer supported) threads are always bound
+  // and we use stackbanging in all cases.
 
   os::Solaris::init_thread_fpu_state();
   std::set_terminate(_handle_uncaught_cxx_exception);
@@ -2092,12 +1990,7 @@
 }
 
 void os::Solaris::print_libversion_info(outputStream* st) {
-  if (os::Solaris::T2_libthread()) {
-    st->print("  (T2 libthread)");
-  }
-  else {
-    st->print("  (T1 libthread)");
-  }
+  st->print("  (T2 libthread)");
   st->cr();
 }
 
@@ -3323,41 +3216,10 @@
 
 os::YieldResult os::NakedYield() { thr_yield(); return os::YIELD_UNKNOWN; }
 
-
-// On Solaris we found that yield_all doesn't always yield to all other threads.
-// There have been cases where there is a thread ready to execute but it doesn't
-// get an lwp as the VM thread continues to spin with sleeps of 1 millisecond.
-// The 1 millisecond wait doesn't seem long enough for the kernel to issue a
-// SIGWAITING signal which will cause a new lwp to be created. So we count the
-// number of times yield_all is called in the one loop and increase the sleep
-// time after 8 attempts. If this fails too we increase the concurrency level
-// so that the starving thread would get an lwp
-
-void os::yield_all(int attempts) {
+void os::yield_all() {
   // Yields to all threads, including threads with lower priorities
-  if (attempts == 0) {
-    os::sleep(Thread::current(), 1, false);
-  } else {
-    int iterations = attempts % 30;
-    if (iterations == 0 && !os::Solaris::T2_libthread()) {
-      // thr_setconcurrency and _getconcurrency make sense only under T1.
-      int noofLWPS = thr_getconcurrency();
-      if (noofLWPS < (Threads::number_of_threads() + 2)) {
-        thr_setconcurrency(thr_getconcurrency() + 1);
-      }
-    } else if (iterations < 25) {
-      os::sleep(Thread::current(), 1, false);
-    } else {
-      os::sleep(Thread::current(), 10, false);
-    }
-  }
-}
-
-// Called from the tight loops to possibly influence time-sharing heuristics
-void os::loop_breaker(int attempts) {
-  os::yield_all(attempts);
-}
-
+  os::sleep(Thread::current(), 1, false);
+}
 
 // Interface for setting lwp priorities.  If we are using T2 libthread,
 // which forces the use of BoundThreads or we manually set UseBoundThreads,
@@ -3365,6 +3227,9 @@
 // function is meaningless in this mode so we must adjust the real lwp's priority
 // The routines below implement the getting and setting of lwp priorities.
 //
+// Note: T2 is now the only supported libthread. UseBoundThreads flag is
+//       being deprecated and all threads are now BoundThreads
+//
 // Note: There are three priority scales used on Solaris.  Java priotities
 //       which range from 1 to 10, libthread "thr_setprio" scale which range
 //       from 0 to 127, and the current scheduling class of the process we
@@ -3437,29 +3302,19 @@
 
   if (!UseThreadPriorities) return 0;
 
-  // We are using Bound threads, we need to determine our priority ranges
-  if (os::Solaris::T2_libthread() || UseBoundThreads) {
-    // If ThreadPriorityPolicy is 1, switch tables
-    if (ThreadPriorityPolicy == 1) {
-      for (i = 0 ; i < CriticalPriority+1; i++)
-        os::java_to_os_priority[i] = prio_policy1[i];
-    }
-    if (UseCriticalJavaThreadPriority) {
-      // MaxPriority always maps to the FX scheduling class and criticalPrio.
-      // See set_native_priority() and set_lwp_class_and_priority().
-      // Save original MaxPriority mapping in case attempt to
-      // use critical priority fails.
-      java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority];
-      // Set negative to distinguish from other priorities
-      os::java_to_os_priority[MaxPriority] = -criticalPrio;
-    }
-  }
-  // Not using Bound Threads, set to ThreadPolicy 1
-  else {
-    for ( i = 0 ; i < CriticalPriority+1; i++ ) {
+  // If ThreadPriorityPolicy is 1, switch tables
+  if (ThreadPriorityPolicy == 1) {
+    for (i = 0 ; i < CriticalPriority+1; i++)
       os::java_to_os_priority[i] = prio_policy1[i];
-    }
-    return 0;
+  }
+  if (UseCriticalJavaThreadPriority) {
+    // MaxPriority always maps to the FX scheduling class and criticalPrio.
+    // See set_native_priority() and set_lwp_class_and_priority().
+    // Save original MaxPriority mapping in case attempt to
+    // use critical priority fails.
+    java_MaxPriority_to_os_priority = os::java_to_os_priority[MaxPriority];
+    // Set negative to distinguish from other priorities
+    os::java_to_os_priority[MaxPriority] = -criticalPrio;
   }
 
   // Get IDs for a set of well-known scheduling classes.
@@ -3583,10 +3438,6 @@
 
 
 // set_lwp_class_and_priority
-//
-// Set the class and priority of the lwp.  This call should only
-// be made when using bound threads (T2 threads are bound by default).
-//
 int set_lwp_class_and_priority(int ThreadID, int lwpid,
                                int newPrio, int new_class, bool scale) {
   int rslt;
@@ -3812,23 +3663,20 @@
     status = thr_setprio(thread->osthread()->thread_id(), newpri);
   }
 
-  if (os::Solaris::T2_libthread() ||
-      (UseBoundThreads && osthread->is_vm_created())) {
-    int lwp_status =
-      set_lwp_class_and_priority(osthread->thread_id(),
-                                 osthread->lwp_id(),
-                                 newpri,
-                                 fxcritical ? fxLimits.schedPolicy : myClass,
-                                 !fxcritical);
-    if (lwp_status != 0 && fxcritical) {
-      // Try again, this time without changing the scheduling class
-      newpri = java_MaxPriority_to_os_priority;
-      lwp_status = set_lwp_class_and_priority(osthread->thread_id(),
-                                              osthread->lwp_id(),
-                                              newpri, myClass, false);
-    }
-    status |= lwp_status;
-  }
+  int lwp_status =
+          set_lwp_class_and_priority(osthread->thread_id(),
+          osthread->lwp_id(),
+          newpri,
+          fxcritical ? fxLimits.schedPolicy : myClass,
+          !fxcritical);
+  if (lwp_status != 0 && fxcritical) {
+    // Try again, this time without changing the scheduling class
+    newpri = java_MaxPriority_to_os_priority;
+    lwp_status = set_lwp_class_and_priority(osthread->thread_id(),
+            osthread->lwp_id(),
+            newpri, myClass, false);
+  }
+  status |= lwp_status;
   return (status == 0) ? OS_OK : OS_ERR;
 }
 
@@ -4495,13 +4343,6 @@
   }
 }
 
-// (Static) wrappers for the new libthread API
-int_fnP_thread_t_iP_uP_stack_tP_gregset_t os::Solaris::_thr_getstate;
-int_fnP_thread_t_i_gregset_t os::Solaris::_thr_setstate;
-int_fnP_thread_t_i os::Solaris::_thr_setmutator;
-int_fnP_thread_t os::Solaris::_thr_suspend_mutator;
-int_fnP_thread_t os::Solaris::_thr_continue_mutator;
-
 // (Static) wrapper for getisax(2) call.
 os::Solaris::getisax_func_t os::Solaris::_getisax = 0;
 
@@ -4536,78 +4377,9 @@
   return addr;
 }
 
-
-
-// isT2_libthread()
-//
-// Routine to determine if we are currently using the new T2 libthread.
-//
-// We determine if we are using T2 by reading /proc/self/lstatus and
-// looking for a thread with the ASLWP bit set.  If we find this status
-// bit set, we must assume that we are NOT using T2.  The T2 team
-// has approved this algorithm.
-//
-// We need to determine if we are running with the new T2 libthread
-// since setting native thread priorities is handled differently
-// when using this library.  All threads created using T2 are bound
-// threads. Calling thr_setprio is meaningless in this case.
-//
-bool isT2_libthread() {
-  static prheader_t * lwpArray = NULL;
-  static int lwpSize = 0;
-  static int lwpFile = -1;
-  lwpstatus_t * that;
-  char lwpName [128];
-  bool isT2 = false;
-
-#define ADR(x)  ((uintptr_t)(x))
-#define LWPINDEX(ary,ix)   ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1))))
-
-  lwpFile = ::open("/proc/self/lstatus", O_RDONLY, 0);
-  if (lwpFile < 0) {
-      if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n");
-      return false;
-  }
-  lwpSize = 16*1024;
-  for (;;) {
-    ::lseek64 (lwpFile, 0, SEEK_SET);
-    lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize, mtInternal);
-    if (::read(lwpFile, lwpArray, lwpSize) < 0) {
-      if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n");
-      break;
-    }
-    if ((lwpArray->pr_nent * lwpArray->pr_entsize) <= lwpSize) {
-       // We got a good snapshot - now iterate over the list.
-      int aslwpcount = 0;
-      for (int i = 0; i < lwpArray->pr_nent; i++ ) {
-        that = LWPINDEX(lwpArray,i);
-        if (that->pr_flags & PR_ASLWP) {
-          aslwpcount++;
-        }
-      }
-      if (aslwpcount == 0) isT2 = true;
-      break;
-    }
-    lwpSize = lwpArray->pr_nent * lwpArray->pr_entsize;
-    FREE_C_HEAP_ARRAY(char, lwpArray, mtInternal);  // retry.
-  }
-
-  FREE_C_HEAP_ARRAY(char, lwpArray, mtInternal);
-  ::close (lwpFile);
-  if (ThreadPriorityVerbose) {
-    if (isT2) tty->print_cr("We are running with a T2 libthread\n");
-    else tty->print_cr("We are not running with a T2 libthread\n");
-  }
-  return isT2;
-}
-
-
 void os::Solaris::libthread_init() {
   address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators");
 
-  // Determine if we are running with the new T2 libthread
-  os::Solaris::set_T2_libthread(isT2_libthread());
-
   lwp_priocntl_init();
 
   // RTLD_DEFAULT was not defined on some early versions of 5.5.1
@@ -4618,22 +4390,6 @@
     guarantee(func != NULL, "libthread.so is too old.");
   }
 
-  // Initialize the new libthread getstate API wrappers
-  func = resolve_symbol("thr_getstate");
-  os::Solaris::set_thr_getstate(CAST_TO_FN_PTR(int_fnP_thread_t_iP_uP_stack_tP_gregset_t, func));
-
-  func = resolve_symbol("thr_setstate");
-  os::Solaris::set_thr_setstate(CAST_TO_FN_PTR(int_fnP_thread_t_i_gregset_t, func));
-
-  func = resolve_symbol("thr_setmutator");
-  os::Solaris::set_thr_setmutator(CAST_TO_FN_PTR(int_fnP_thread_t_i, func));
-
-  func = resolve_symbol("thr_suspend_mutator");
-  os::Solaris::set_thr_suspend_mutator(CAST_TO_FN_PTR(int_fnP_thread_t, func));
-
-  func = resolve_symbol("thr_continue_mutator");
-  os::Solaris::set_thr_continue_mutator(CAST_TO_FN_PTR(int_fnP_thread_t, func));
-
   int size;
   void (*handler_info_func)(address *, int *);
   handler_info_func = CAST_TO_FN_PTR(void (*)(address *, int *), resolve_symbol("thr_sighndlrinfo"));
@@ -5536,11 +5292,7 @@
 }
 
 bool os::is_thread_cpu_time_supported() {
-  if ( os::Solaris::T2_libthread() || UseBoundThreads ) {
-    return true;
-  } else {
-    return false;
-  }
+  return true;
 }
 
 // System loadavg support.  Returns -1 if load average cannot be obtained.
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -41,19 +41,6 @@
   #define TRS_LWPID       2
   #define TRS_INVALID     3
 
-  // _T2_libthread is true if we believe we are running with the newer
-  // SunSoft lib/lwp/libthread: default Solaris 9, available Solaris 8
-  // which is a lightweight libthread that also supports all T1
-  static bool _T2_libthread;
-  // These refer to new libthread interface functions
-  // They get intialized if we dynamically detect new libthread
-  static int_fnP_thread_t_iP_uP_stack_tP_gregset_t _thr_getstate;
-  static int_fnP_thread_t_i_gregset_t _thr_setstate;
-  static int_fnP_thread_t_i _thr_setmutator;
-  static int_fnP_thread_t _thr_suspend_mutator;
-  static int_fnP_thread_t _thr_continue_mutator;
-  // libthread_init sets the above, if the new functionality is detected
-
   // initialized to libthread or lwp synchronization primitives depending on UseLWPSychronization
   static int_fnP_mutex_tP _mutex_lock;
   static int_fnP_mutex_tP _mutex_trylock;
@@ -214,29 +201,6 @@
   static struct sigaction *get_chained_signal_action(int sig);
   static bool chained_handler(int sig, siginfo_t *siginfo, void *context);
 
-  // The following allow us to link against both the old and new libthread (2.8)
-  // and exploit the new libthread functionality if available.
-
-  static bool T2_libthread()                                { return _T2_libthread; }
-  static void set_T2_libthread(bool T2_libthread) { _T2_libthread = T2_libthread; }
-
-  static int thr_getstate(thread_t tid, int *flag, unsigned *lwp, stack_t *ss, gregset_t rs)
-    { return _thr_getstate(tid, flag, lwp, ss, rs); }
-  static void set_thr_getstate(int_fnP_thread_t_iP_uP_stack_tP_gregset_t func)
-    { _thr_getstate = func; }
-
-  static int thr_setstate(thread_t tid, int flag, gregset_t rs)   { return _thr_setstate(tid, flag, rs); }
-  static void set_thr_setstate(int_fnP_thread_t_i_gregset_t func) { _thr_setstate = func; }
-
-  static int thr_setmutator(thread_t tid, int enabled)    { return _thr_setmutator(tid, enabled); }
-  static void set_thr_setmutator(int_fnP_thread_t_i func) { _thr_setmutator = func; }
-
-  static int  thr_suspend_mutator(thread_t tid)              { return _thr_suspend_mutator(tid); }
-  static void set_thr_suspend_mutator(int_fnP_thread_t func) { _thr_suspend_mutator = func; }
-
-  static int  thr_continue_mutator(thread_t tid)              { return _thr_continue_mutator(tid); }
-  static void set_thr_continue_mutator(int_fnP_thread_t func) { _thr_continue_mutator = func; }
-
   // Allows us to switch between lwp and thread -based synchronization
   static int mutex_lock(mutex_t *mx)    { return _mutex_lock(mx); }
   static int mutex_trylock(mutex_t *mx) { return _mutex_trylock(mx); }
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -3518,7 +3518,7 @@
 
 void os::yield() {  os::NakedYield(); }
 
-void os::yield_all(int attempts) {
+void os::yield_all() {
   // Yields to all threads, including threads with lower priorities
   Sleep(1);
 }
@@ -3864,12 +3864,6 @@
   win32::setmode_streams();
   init_page_sizes((size_t) win32::vm_page_size());
 
-  // For better scalability on MP systems (must be called after initialize_system_info)
-#ifndef PRODUCT
-  if (is_MP()) {
-    NoYieldsInMicrolock = true;
-  }
-#endif
   // This may be overridden later when argument processing is done.
   FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation,
     os::win32::is_windows_2003());
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -52,9 +52,6 @@
   return (void*)::GetProcAddress((HMODULE)lib, name);
 }
 
-// Used to improve time-sharing on some systems
-inline void os::loop_breaker(int attempts) {}
-
 inline bool os::obsolete_option(const JavaVMOption *option) {
   return false;
 }
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -270,31 +270,6 @@
   }
 }
 
-static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) {
-  char lwpstatusfile[PROCFILE_LENGTH];
-  int lwpfd, err;
-
-  if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs))
-    return (err);
-  if (*flags == TRS_LWPID) {
-    sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
-            *lwp);
-    if ((lwpfd = ::open(lwpstatusfile, O_RDONLY)) < 0) {
-      perror("thr_mutator_status: open lwpstatus");
-      return (EINVAL);
-    }
-    if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
-        sizeof (lwpstatus_t)) {
-      perror("thr_mutator_status: read lwpstatus");
-      (void) ::close(lwpfd);
-      return (EINVAL);
-    }
-    (void) ::close(lwpfd);
-  }
-  return (0);
-}
-
-
 bool os::is_allocatable(size_t bytes) {
 #ifdef _LP64
    return true;
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -256,30 +256,6 @@
   }
 }
 
-static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) {
-  char lwpstatusfile[PROCFILE_LENGTH];
-  int lwpfd, err;
-
-  if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs))
-    return (err);
-  if (*flags == TRS_LWPID) {
-    sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
-            *lwp);
-    if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) {
-      perror("thr_mutator_status: open lwpstatus");
-      return (EINVAL);
-    }
-    if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
-        sizeof (lwpstatus_t)) {
-      perror("thr_mutator_status: read lwpstatus");
-      (void) close(lwpfd);
-      return (EINVAL);
-    }
-    (void) close(lwpfd);
-  }
-  return (0);
-}
-
 #ifndef AMD64
 
 // Detecting SSE support by OS
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -2777,6 +2777,11 @@
                      "Short length on BootstrapMethods in class file %s",
                      CHECK);
 
+  guarantee_property(attribute_byte_length > sizeof(u2),
+                     "Invalid BootstrapMethods attribute length %u in class file %s",
+                     attribute_byte_length,
+                     CHECK);
+
   // The attribute contains a counted array of counted tuples of shorts,
   // represending bootstrap specifiers:
   //    length*{bootstrap_method_index, argument_count*{argument_index}}
@@ -4180,8 +4185,12 @@
 
   clear_class_metadata();
 
-  // deallocate the klass if already created.
-  MetadataFactory::free_metadata(_loader_data, _klass);
+  // deallocate the klass if already created.  Don't directly deallocate, but add
+  // to the deallocate list so that the klass is removed from the CLD::_klasses list
+  // at a safepoint.
+  if (_klass != NULL) {
+    _loader_data->add_to_deallocate_list(_klass);
+  }
   _klass = NULL;
 }
 
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -464,25 +464,26 @@
 void java_lang_String::print(oop java_string, outputStream* st) {
   assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
-  int          length = java_lang_String::length(java_string);
-
-  int end = MIN2(length, 100);
+
   if (value == NULL) {
     // This can happen if, e.g., printing a String
     // object before its initializer has been called
-    st->print_cr("NULL");
-  } else {
-    st->print("\"");
-    for (int index = 0; index < length; index++) {
-      st->print("%c", value->char_at(index + offset));
-    }
-    st->print("\"");
+    st->print("NULL");
+    return;
   }
-}
-
-static void initialize_static_field(fieldDescriptor* fd, TRAPS) {
-  Handle mirror (THREAD, fd->field_holder()->java_mirror());
+
+  int offset = java_lang_String::offset(java_string);
+  int length = java_lang_String::length(java_string);
+
+  st->print("\"");
+  for (int index = 0; index < length; index++) {
+    st->print("%c", value->char_at(index + offset));
+  }
+  st->print("\"");
+}
+
+
+static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) {
   assert(mirror.not_null() && fd->is_static(), "just checking");
   if (fd->has_initial_value()) {
     BasicType t = fd->field_type();
@@ -549,21 +550,45 @@
   create_mirror(k, Handle(NULL), CHECK);
 }
 
-oop java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) {
+void java_lang_Class::initialize_mirror_fields(KlassHandle k,
+                                               Handle mirror,
+                                               Handle protection_domain,
+                                               TRAPS) {
+  // Allocate a simple java object for a lock.
+  // This needs to be a java object because during class initialization
+  // it can be held across a java call.
+  typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK);
+  set_init_lock(mirror(), r);
+
+  // Set protection domain also
+  set_protection_domain(mirror(), protection_domain());
+
+  // Initialize static fields
+  InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, mirror, CHECK);
+}
+
+void java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) {
   assert(k->java_mirror() == NULL, "should only assign mirror once");
   // Use this moment of initialization to cache modifier_flags also,
   // to support Class.getModifiers().  Instance classes recalculate
   // the cached flags after the class file is parsed, but before the
   // class is put into the system dictionary.
-  int computed_modifiers = k->compute_modifier_flags(CHECK_0);
+  int computed_modifiers = k->compute_modifier_flags(CHECK);
   k->set_modifier_flags(computed_modifiers);
   // Class_klass has to be loaded because it is used to allocate
   // the mirror.
   if (SystemDictionary::Class_klass_loaded()) {
     // Allocate mirror (java.lang.Class instance)
-    Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0);
+    Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK);
+
+    // Setup indirection from mirror->klass
+    if (!k.is_null()) {
+      java_lang_Class::set_klass(mirror(), k());
+    }
 
     InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass());
+    assert(oop_size(mirror()) == mk->instance_size(k), "should have been set");
+
     java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror()));
 
     // It might also have a component mirror.  This mirror must already exist.
@@ -576,29 +601,32 @@
         assert(k->oop_is_objArray(), "Must be");
         Klass* element_klass = ObjArrayKlass::cast(k())->element_klass();
         assert(element_klass != NULL, "Must have an element klass");
-          comp_mirror = element_klass->java_mirror();
+        comp_mirror = element_klass->java_mirror();
       }
       assert(comp_mirror.not_null(), "must have a mirror");
 
-        // Two-way link between the array klass and its component mirror:
+      // Two-way link between the array klass and its component mirror:
       ArrayKlass::cast(k())->set_component_mirror(comp_mirror());
       set_array_klass(comp_mirror(), k());
     } else {
       assert(k->oop_is_instance(), "Must be");
 
-      // Allocate a simple java object for a lock.
-      // This needs to be a java object because during class initialization
-      // it can be held across a java call.
-      typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_NULL);
-      set_init_lock(mirror(), r);
-
-      // Set protection domain also
-      set_protection_domain(mirror(), protection_domain());
-
-      // Initialize static fields
-      InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, CHECK_NULL);
+      initialize_mirror_fields(k, mirror, protection_domain, THREAD);
+      if (HAS_PENDING_EXCEPTION) {
+        // If any of the fields throws an exception like OOM remove the klass field
+        // from the mirror so GC doesn't follow it after the klass has been deallocated.
+        // This mirror looks like a primitive type, which logically it is because it
+        // it represents no class.
+        java_lang_Class::set_klass(mirror(), NULL);
+        return;
+      }
     }
-    return mirror();
+
+    // Setup indirection from klass->mirror last
+    // after any exceptions can happen during allocations.
+    if (!k.is_null()) {
+      k->set_java_mirror(mirror());
+    }
   } else {
     if (fixup_mirror_list() == NULL) {
       GrowableArray<Klass*>* list =
@@ -606,12 +634,10 @@
       set_fixup_mirror_list(list);
     }
     fixup_mirror_list()->push(k());
-    return NULL;
   }
 }
 
 
-
 int  java_lang_Class::oop_size(oop java_class) {
   assert(_oop_size_offset != 0, "must be set");
   return java_class->int_field(_oop_size_offset);
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -246,11 +246,12 @@
 
   static void set_init_lock(oop java_class, oop init_lock);
   static void set_protection_domain(oop java_class, oop protection_domain);
+  static void initialize_mirror_fields(KlassHandle k, Handle mirror, Handle protection_domain, TRAPS);
  public:
   static void compute_offsets();
 
   // Instance creation
-  static oop  create_mirror(KlassHandle k, Handle protection_domain, TRAPS);
+  static void create_mirror(KlassHandle k, Handle protection_domain, TRAPS);
   static void fixup_mirror(KlassHandle k, TRAPS);
   static oop  create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
   // Conversion
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -810,11 +810,11 @@
   const int limit = the_table()->table_size();
 
   assert(0 <= start_idx && start_idx <= limit,
-         err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx));
+         err_msg("start_idx (%d) is out of bounds", start_idx));
   assert(0 <= end_idx && end_idx <= limit,
-         err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx));
+         err_msg("end_idx (%d) is out of bounds", end_idx));
   assert(start_idx <= end_idx,
-         err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
+         err_msg("Index ordering: start_idx=%d, end_idx=%d",
                  start_idx, end_idx));
 
   for (int i = start_idx; i < end_idx; i += 1) {
@@ -833,11 +833,11 @@
   const int limit = the_table()->table_size();
 
   assert(0 <= start_idx && start_idx <= limit,
-         err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx));
+         err_msg("start_idx (%d) is out of bounds", start_idx));
   assert(0 <= end_idx && end_idx <= limit,
-         err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx));
+         err_msg("end_idx (%d) is out of bounds", end_idx));
   assert(start_idx <= end_idx,
-         err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
+         err_msg("Index ordering: start_idx=%d, end_idx=%d",
                  start_idx, end_idx));
 
   for (int i = start_idx; i < end_idx; ++i) {
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -826,47 +826,6 @@
       }
     } // load_instance_class loop
 
-    if (HAS_PENDING_EXCEPTION) {
-      // An exception, such as OOM could have happened at various places inside
-      // load_instance_class. We might have partially initialized a shared class
-      // and need to clean it up.
-      if (class_loader.is_null()) {
-        // In some cases k may be null. Let's find the shared class again.
-        instanceKlassHandle ik(THREAD, find_shared_class(name));
-        if (ik.not_null()) {
-          if (ik->class_loader_data() == NULL) {
-            // We didn't go as far as Klass::restore_unshareable_info(),
-            // so nothing to clean up.
-          } else {
-            Klass *kk;
-            {
-              MutexLocker mu(SystemDictionary_lock, THREAD);
-              kk = find_class(d_index, d_hash, name, ik->class_loader_data());
-            }
-            if (kk != NULL) {
-              // No clean up is needed if the shared class has been entered
-              // into system dictionary, as load_shared_class() won't be called
-              // again.
-            } else {
-              // This must be done outside of the SystemDictionary_lock to
-              // avoid deadlock.
-              //
-              // Note that Klass::restore_unshareable_info (called via
-              // load_instance_class above) is also called outside
-              // of SystemDictionary_lock. Other threads are blocked from
-              // loading this class because they are waiting on the
-              // SystemDictionary_lock until this thread removes
-              // the placeholder below.
-              //
-              // This need to be re-thought when parallel-capable non-boot
-              // classloaders are supported by CDS (today they're not).
-              clean_up_shared_class(ik, class_loader, THREAD);
-            }
-          }
-        }
-      }
-    }
-
     if (load_instance_added == true) {
       // clean up placeholder entries for LOAD_INSTANCE success or error
       // This brackets the SystemDictionary updates for both defining
@@ -1272,19 +1231,6 @@
   return ik;
 }
 
-void SystemDictionary::clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS) {
-  // Updating methods must be done under a lock so multiple
-  // threads don't update these in parallel
-  // Shared classes are all currently loaded by the bootstrap
-  // classloader, so this will never cause a deadlock on
-  // a custom class loader lock.
-  {
-    Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
-    check_loader_lock_contention(lockObject, THREAD);
-    ObjectLocker ol(lockObject, THREAD, true);
-    ik->remove_unshareable_info();
-  }
-}
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -617,7 +617,6 @@
                                                Handle class_loader, TRAPS);
   static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
                                                Handle class_loader, TRAPS);
-  static void clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS);
   static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
   static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
   static void check_loader_lock_contention(Handle loader_lock, TRAPS);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -57,10 +57,10 @@
 
   _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC);
 
-  int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
+  uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
 
   ConcurrentG1RefineThread *next = NULL;
-  for (int i = _n_threads - 1; i >= 0; i--) {
+  for (uint i = _n_threads - 1; i != UINT_MAX; i--) {
     ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
     assert(t != NULL, "Conc refine should have been created");
     if (t->osthread() == NULL) {
@@ -87,7 +87,7 @@
 
 void ConcurrentG1Refine::stop() {
   if (_threads != NULL) {
-    for (int i = 0; i < _n_threads; i++) {
+    for (uint i = 0; i < _n_threads; i++) {
       _threads[i]->stop();
     }
   }
@@ -96,7 +96,7 @@
 void ConcurrentG1Refine::reinitialize_threads() {
   reset_threshold_step();
   if (_threads != NULL) {
-    for (int i = 0; i < _n_threads; i++) {
+    for (uint i = 0; i < _n_threads; i++) {
       _threads[i]->initialize();
     }
   }
@@ -104,7 +104,7 @@
 
 ConcurrentG1Refine::~ConcurrentG1Refine() {
   if (_threads != NULL) {
-    for (int i = 0; i < _n_threads; i++) {
+    for (uint i = 0; i < _n_threads; i++) {
       delete _threads[i];
     }
     FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads, mtGC);
@@ -113,7 +113,7 @@
 
 void ConcurrentG1Refine::threads_do(ThreadClosure *tc) {
   if (_threads != NULL) {
-    for (int i = 0; i < _n_threads; i++) {
+    for (uint i = 0; i < _n_threads; i++) {
       tc->do_thread(_threads[i]);
     }
   }
@@ -121,20 +121,20 @@
 
 void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) {
   if (_threads != NULL) {
-    for (int i = 0; i < worker_thread_num(); i++) {
+    for (uint i = 0; i < worker_thread_num(); i++) {
       tc->do_thread(_threads[i]);
     }
   }
 }
 
-int ConcurrentG1Refine::thread_num() {
-  int n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads
+uint ConcurrentG1Refine::thread_num() {
+  uint n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads
                                                 : ParallelGCThreads;
-  return MAX2<int>(n_threads, 1);
+  return MAX2<uint>(n_threads, 1);
 }
 
 void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const {
-  for (int i = 0; i < _n_threads; ++i) {
+  for (uint i = 0; i < _n_threads; ++i) {
     _threads[i]->print_on(st);
     st->cr();
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -39,8 +39,8 @@
 
 class ConcurrentG1Refine: public CHeapObj<mtGC> {
   ConcurrentG1RefineThread** _threads;
-  int _n_threads;
-  int _n_worker_threads;
+  uint _n_threads;
+  uint _n_worker_threads;
  /*
   * The value of the update buffer queue length falls into one of 3 zones:
   * green, yellow, red. If the value is in [0, green) nothing is
@@ -88,7 +88,7 @@
   // The RS sampling thread
   ConcurrentG1RefineThread * sampling_thread() const;
 
-  static int thread_num();
+  static uint thread_num();
 
   void print_worker_threads_on(outputStream* st) const;
 
@@ -100,8 +100,8 @@
   int yellow_zone() const     { return _yellow_zone; }
   int red_zone() const        { return _red_zone;    }
 
-  int total_thread_num() const  { return _n_threads;        }
-  int worker_thread_num() const { return _n_worker_threads; }
+  uint total_thread_num() const  { return _n_threads;        }
+  uint worker_thread_num() const { return _n_worker_threads; }
 
   int thread_threshold_step() const { return _thread_threshold_step; }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -33,7 +33,7 @@
 
 ConcurrentG1RefineThread::
 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
-                         int worker_id_offset, int worker_id) :
+                         uint worker_id_offset, uint worker_id) :
   ConcurrentGCThread(),
   _worker_id_offset(worker_id_offset),
   _worker_id(worker_id),
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -38,8 +38,8 @@
 
   double _vtime_start;  // Initial virtual time.
   double _vtime_accum;  // Initial virtual time.
-  int _worker_id;
-  int _worker_id_offset;
+  uint _worker_id;
+  uint _worker_id_offset;
 
   // The refinement threads collection is linked list. A predecessor can activate a successor
   // when the number of the rset update buffer crosses a certain threshold. A successor
@@ -71,7 +71,7 @@
   virtual void run();
   // Constructor
   ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
-                           int worker_id_offset, int worker_id);
+                           uint worker_id_offset, uint worker_id);
 
   void initialize();
 
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -567,8 +567,8 @@
   _root_regions.init(_g1h, this);
 
   if (ConcGCThreads > ParallelGCThreads) {
-    warning("Can't have more ConcGCThreads (" UINT32_FORMAT ") "
-            "than ParallelGCThreads (" UINT32_FORMAT ").",
+    warning("Can't have more ConcGCThreads (" UINTX_FORMAT ") "
+            "than ParallelGCThreads (" UINTX_FORMAT ").",
             ConcGCThreads, ParallelGCThreads);
     return;
   }
@@ -1804,7 +1804,6 @@
 
 class G1NoteEndOfConcMarkClosure : public HeapRegionClosure {
   G1CollectedHeap* _g1;
-  int _worker_num;
   size_t _max_live_bytes;
   uint _regions_claimed;
   size_t _freed_bytes;
@@ -1817,10 +1816,9 @@
 
 public:
   G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
-                             int worker_num,
                              FreeRegionList* local_cleanup_list,
                              HRRSCleanupTask* hrrs_cleanup_task) :
-    _g1(g1), _worker_num(worker_num),
+    _g1(g1),
     _max_live_bytes(0), _regions_claimed(0),
     _freed_bytes(0),
     _claimed_region_time(0.0), _max_region_time(0.0),
@@ -1893,7 +1891,7 @@
     double start = os::elapsedTime();
     FreeRegionList local_cleanup_list("Local Cleanup List");
     HRRSCleanupTask hrrs_cleanup_task;
-    G1NoteEndOfConcMarkClosure g1_note_end(_g1h, worker_id, &local_cleanup_list,
+    G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
                                            &hrrs_cleanup_task);
     if (G1CollectedHeap::use_parallel_gc_threads()) {
       _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id,
@@ -2145,7 +2143,7 @@
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  _cleanup_list.verify_list();
+  _cleanup_list.verify_optional();
   FreeRegionList tmp_free_list("Tmp Free List");
 
   if (G1ConcRegionFreeingVerbose) {
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -34,12 +34,12 @@
 
 bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl,
                                    bool consume,
-                                   size_t worker_i) {
+                                   uint worker_i) {
   bool res = true;
   if (_buf != NULL) {
     res = apply_closure_to_buffer(cl, _buf, _index, _sz,
                                   consume,
-                                  (int) worker_i);
+                                  worker_i);
     if (res && consume) _index = _sz;
   }
   return res;
@@ -49,7 +49,7 @@
                                              void** buf,
                                              size_t index, size_t sz,
                                              bool consume,
-                                             int worker_i) {
+                                             uint worker_i) {
   if (cl == NULL) return true;
   for (size_t i = index; i < sz; i += oopSize) {
     int ind = byte_index_to_index((int)i);
@@ -79,8 +79,8 @@
 }
 
 // Determines how many mutator threads can process the buffers in parallel.
-size_t DirtyCardQueueSet::num_par_ids() {
-  return os::processor_count();
+uint DirtyCardQueueSet::num_par_ids() {
+  return (uint)os::processor_count();
 }
 
 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
@@ -103,7 +103,7 @@
 }
 
 void DirtyCardQueueSet::iterate_closure_all_threads(bool consume,
-                                                    size_t worker_i) {
+                                                    uint worker_i) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   for(JavaThread* t = Threads::first(); t; t = t->next()) {
     bool b = t->dirty_card_queue().apply_closure(_closure, consume);
@@ -126,11 +126,11 @@
 
   // We get the the number of any par_id that this thread
   // might have already claimed.
-  int worker_i = thread->get_claimed_par_id();
+  uint worker_i = thread->get_claimed_par_id();
 
-  // If worker_i is not -1 then the thread has already claimed
+  // If worker_i is not UINT_MAX then the thread has already claimed
   // a par_id. We make note of it using the already_claimed value
-  if (worker_i != -1) {
+  if (worker_i != UINT_MAX) {
     already_claimed = true;
   } else {
 
@@ -142,7 +142,7 @@
   }
 
   bool b = false;
-  if (worker_i != -1) {
+  if (worker_i != UINT_MAX) {
     b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0,
                                                 _sz, true, worker_i);
     if (b) Atomic::inc(&_processed_buffers_mut);
@@ -154,8 +154,8 @@
       // we release the id
       _free_ids->release_par_id(worker_i);
 
-      // and set the claimed_id in the thread to -1
-      thread->set_claimed_par_id(-1);
+      // and set the claimed_id in the thread to UINT_MAX
+      thread->set_claimed_par_id(UINT_MAX);
     }
   }
   return b;
@@ -186,7 +186,7 @@
 
 bool DirtyCardQueueSet::
 apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
-                                         int worker_i,
+                                         uint worker_i,
                                          BufferNode* nd) {
   if (nd != NULL) {
     void **buf = BufferNode::make_buffer_from_node(nd);
@@ -208,7 +208,7 @@
 }
 
 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
-                                                          int worker_i,
+                                                          uint worker_i,
                                                           int stop_at,
                                                           bool during_pause) {
   assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
@@ -218,7 +218,7 @@
   return res;
 }
 
-bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i,
+bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i,
                                                           int stop_at,
                                                           bool during_pause) {
   return apply_closure_to_completed_buffer(_closure, worker_i,
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -36,7 +36,7 @@
 public:
   // Process the card whose card table entry is "card_ptr".  If returns
   // "false", terminate the iteration early.
-  virtual bool do_card_ptr(jbyte* card_ptr, int worker_i = 0) = 0;
+  virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i = 0) = 0;
 };
 
 // A ptrQueue whose elements are "oops", pointers to object heads.
@@ -53,7 +53,7 @@
   // deletes processed entries from logs.
   bool apply_closure(CardTableEntryClosure* cl,
                      bool consume = true,
-                     size_t worker_i = 0);
+                     uint worker_i = 0);
 
   // Apply the closure to all elements of "buf", down to "index"
   // (inclusive.)  If returns "false", then a closure application returned
@@ -63,7 +63,7 @@
   static bool apply_closure_to_buffer(CardTableEntryClosure* cl,
                                       void** buf, size_t index, size_t sz,
                                       bool consume = true,
-                                      int worker_i = 0);
+                                      uint worker_i = 0);
   void **get_buf() { return _buf;}
   void set_buf(void **buf) {_buf = buf;}
   size_t get_index() { return _index;}
@@ -98,7 +98,7 @@
 
   // The number of parallel ids that can be claimed to allow collector or
   // mutator threads to do card-processing work.
-  static size_t num_par_ids();
+  static uint num_par_ids();
 
   static void handle_zero_index_for_thread(JavaThread* t);
 
@@ -115,7 +115,7 @@
   // change in the future.)  If "consume" is true, processed entries are
   // discarded.
   void iterate_closure_all_threads(bool consume = true,
-                                   size_t worker_i = 0);
+                                   uint worker_i = 0);
 
   // If there exists some completed buffer, pop it, then apply the
   // registered closure to all its elements, nulling out those elements
@@ -124,7 +124,7 @@
   // but is only partially completed before a "yield" happens, the
   // partially completed buffer (with its processed elements set to NULL)
   // is returned to the completed buffer set, and this call returns false.
-  bool apply_closure_to_completed_buffer(int worker_i = 0,
+  bool apply_closure_to_completed_buffer(uint worker_i = 0,
                                          int stop_at = 0,
                                          bool during_pause = false);
 
@@ -136,13 +136,13 @@
   // partially completed buffer (with its processed elements set to NULL)
   // is returned to the completed buffer set, and this call returns false.
   bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
-                                         int worker_i = 0,
+                                         uint worker_i = 0,
                                          int stop_at = 0,
                                          bool during_pause = false);
 
   // Helper routine for the above.
   bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
-                                                int worker_i,
+                                                uint worker_i,
                                                 BufferNode* nd);
 
   BufferNode* get_completed_buffer(int stop_at);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -304,26 +304,26 @@
     if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) {
       guarantee(entry > N_words,
                 err_msg("Should be in logarithmic region - "
-                        "entry: " UINT32_FORMAT ", "
-                        "_array->offset_array(c): " UINT32_FORMAT ", "
-                        "N_words: " UINT32_FORMAT,
-                        entry, _array->offset_array(c), N_words));
+                        "entry: %u, "
+                        "_array->offset_array(c): %u, "
+                        "N_words: %u",
+                        (uint)entry, (uint)_array->offset_array(c), (uint)N_words));
     }
     size_t backskip = BlockOffsetArray::entry_to_cards_back(entry);
     size_t landing_card = c - backskip;
     guarantee(landing_card >= (start_card - 1), "Inv");
     if (landing_card >= start_card) {
       guarantee(_array->offset_array(landing_card) <= entry,
-                err_msg("Monotonicity - landing_card offset: " UINT32_FORMAT ", "
-                        "entry: " UINT32_FORMAT,
-                        _array->offset_array(landing_card), entry));
+                err_msg("Monotonicity - landing_card offset: %u, "
+                        "entry: %u",
+                        (uint)_array->offset_array(landing_card), (uint)entry));
     } else {
       guarantee(landing_card == start_card - 1, "Tautology");
       // Note that N_words is the maximum offset value
       guarantee(_array->offset_array(landing_card) <= N_words,
-                err_msg("landing card offset: " UINT32_FORMAT ", "
-                        "N_words: " UINT32_FORMAT,
-                        _array->offset_array(landing_card), N_words));
+                err_msg("landing card offset: %u, "
+                        "N_words: %u",
+                        (uint)_array->offset_array(landing_card), (uint)N_words));
     }
   }
 }
@@ -554,21 +554,20 @@
           (_array->offset_array(orig_index) > 0 &&
          _array->offset_array(orig_index) <= N_words),
          err_msg("offset array should have been set - "
-                  "orig_index offset: " UINT32_FORMAT ", "
+                  "orig_index offset: %u, "
                   "blk_start: " PTR_FORMAT ", "
                   "boundary: " PTR_FORMAT,
-                  _array->offset_array(orig_index),
+                  (uint)_array->offset_array(orig_index),
                   blk_start, boundary));
   for (size_t j = orig_index + 1; j <= end_index; j++) {
     assert(_array->offset_array(j) > 0 &&
            _array->offset_array(j) <=
              (u_char) (N_words+BlockOffsetArray::N_powers-1),
            err_msg("offset array should have been set - "
-                   UINT32_FORMAT " not > 0 OR "
-                   UINT32_FORMAT " not <= " UINT32_FORMAT,
-                   _array->offset_array(j),
-                   _array->offset_array(j),
-                   (u_char) (N_words+BlockOffsetArray::N_powers-1)));
+                   "%u not > 0 OR %u not <= %u",
+                   (uint) _array->offset_array(j),
+                   (uint) _array->offset_array(j),
+                   (uint) (N_words+BlockOffsetArray::N_powers-1)));
   }
 #endif
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -146,8 +146,8 @@
   void check_offset(size_t offset, const char* msg) const {
     assert(offset <= N_words,
            err_msg("%s - "
-                   "offset: " UINT32_FORMAT", N_words: " UINT32_FORMAT,
-                   msg, offset, N_words));
+                   "offset: " SIZE_FORMAT", N_words: %u",
+                   msg, offset, (uint)N_words));
   }
 
   // Bounds checking accessors:
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -102,7 +102,7 @@
                               ConcurrentG1Refine* cg1r) :
     _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true)
   {}
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
     bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false);
     // This path is executed by the concurrent refine or mutator threads,
     // concurrently, and so we do not care if card_ptr contains references
@@ -131,7 +131,7 @@
   {
     for (int i = 0; i < 256; i++) _histo[i] = 0;
   }
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
     if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
       _calls++;
       unsigned char* ujb = (unsigned char*)card_ptr;
@@ -160,7 +160,7 @@
   RedirtyLoggedCardTableEntryClosure() :
     _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {}
 
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
     if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
       _calls++;
       *card_ptr = 0;
@@ -1288,7 +1288,7 @@
   print_heap_before_gc();
   trace_heap_before_gc(gc_tracer);
 
-  size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes();
+  size_t metadata_prev_used = MetaspaceAux::used_bytes();
 
   verify_region_sets_optional();
 
@@ -2314,7 +2314,7 @@
 void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl,
                                                  DirtyCardQueue* into_cset_dcq,
                                                  bool concurrent,
-                                                 int worker_i) {
+                                                 uint worker_i) {
   // Clean cards in the hot card cache
   G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
   hot_card_cache->drain(worker_i, g1_rem_set(), into_cset_dcq);
@@ -2843,7 +2843,7 @@
 
 // Given the id of a worker, obtain or calculate a suitable
 // starting region for iterating over the current collection set.
-HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) {
+HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) {
   assert(get_gc_time_stamp() > 0, "should have been updated by now");
 
   HeapRegion* result = NULL;
@@ -5103,7 +5103,7 @@
                         OopClosure* scan_non_heap_roots,
                         OopsInHeapRegionClosure* scan_rs,
                         G1KlassScanClosure* scan_klasses,
-                        int worker_i) {
+                        uint worker_i) {
 
   // First scan the strong roots
   double ext_roots_start = os::elapsedTime();
@@ -5207,10 +5207,10 @@
 
   ~G1StringSymbolTableUnlinkTask() {
     guarantee(!_process_strings || !_do_in_parallel || StringTable::parallel_claimed_index() >= _initial_string_table_size,
-              err_msg("claim value "INT32_FORMAT" after unlink less than initial string table size "INT32_FORMAT,
+              err_msg("claim value %d after unlink less than initial string table size %d",
                       StringTable::parallel_claimed_index(), _initial_string_table_size));
     guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
-              err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT,
+              err_msg("claim value %d after unlink less than initial symbol table size %d",
                       SymbolTable::parallel_claimed_index(), _initial_symbol_table_size));
   }
 
@@ -5275,7 +5275,7 @@
 
 class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
 public:
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
     *card_ptr = CardTableModRefBS::dirty_card_val();
     return true;
   }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -845,7 +845,7 @@
                                OopClosure* scan_non_heap_roots,
                                OopsInHeapRegionClosure* scan_rs,
                                G1KlassScanClosure* scan_klasses,
-                               int worker_i);
+                               uint worker_i);
 
   // Notifies all the necessary spaces that the committed space has
   // been updated (either expanded or shrunk). It should be called
@@ -1139,7 +1139,7 @@
 
   void iterate_dirty_card_closure(CardTableEntryClosure* cl,
                                   DirtyCardQueue* into_cset_dcq,
-                                  bool concurrent, int worker_i);
+                                  bool concurrent, uint worker_i);
 
   // The shared block offset table array.
   G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; }
@@ -1370,7 +1370,7 @@
 
   // Given the id of a worker, obtain or calculate a suitable
   // starting region for iterating over the current collection set.
-  HeapRegion* start_cset_region_for_worker(int worker_i);
+  HeapRegion* start_cset_region_for_worker(uint worker_i);
 
   // This is a convenience method that is used by the
   // HeapRegionIterator classes to calculate the starting region for
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1204,7 +1204,7 @@
          (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc;
 
   if (full) {
-    _metaspace_used_bytes_before_gc = MetaspaceAux::allocated_used_bytes();
+    _metaspace_used_bytes_before_gc = MetaspaceAux::used_bytes();
   }
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -147,7 +147,7 @@
 void WorkerDataArray<T>::verify() {
   for (uint i = 0; i < _length; i++) {
     assert(_data[i] != _uninitialized,
-        err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf",
+        err_msg("Invalid data for worker %u, data: %lf, uninitialized: %lf",
             i, (double)_data[i], (double)_uninitialized));
   }
 }
@@ -246,8 +246,8 @@
   LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
 }
 
-void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) {
-  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers);
+void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) {
+  LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %u]", str, value, workers);
 }
 
 double G1GCPhaseTimes::accounted_time_ms() {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -161,7 +161,7 @@
 
   // Helper methods for detailed logging
   void print_stats(int level, const char* str, double value);
-  void print_stats(int level, const char* str, double value, int workers);
+  void print_stats(int level, const char* str, double value, uint workers);
 
  public:
   G1GCPhaseTimes(uint max_gc_threads);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -44,9 +44,9 @@
     _hot_cache_idx = 0;
 
     // For refining the cards in the hot cache in parallel
-    int n_workers = (ParallelGCThreads > 0 ?
+    uint n_workers = (ParallelGCThreads > 0 ?
                         _g1h->workers()->total_workers() : 1);
-    _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / n_workers);
+    _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers);
     _hot_cache_par_claimed_idx = 0;
 
     _card_counts.initialize();
@@ -89,7 +89,7 @@
   return res;
 }
 
-void G1HotCardCache::drain(int worker_i,
+void G1HotCardCache::drain(uint worker_i,
                            G1RemSet* g1rs,
                            DirtyCardQueue* into_cset_dcq) {
   if (!default_use_cache()) {
@@ -122,8 +122,8 @@
             // RSet updating while within an evacuation pause.
             // In this case worker_i should be the id of a GC worker thread
             assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
-            assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads),
-                   err_msg("incorrect worker id: "INT32_FORMAT, worker_i));
+            assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads),
+                   err_msg("incorrect worker id: %u", worker_i));
 
             into_cset_dcq->enqueue(card_ptr);
           }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -99,7 +99,7 @@
 
   // Refine the cards that have delayed as a result of
   // being in the cache.
-  void drain(int worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq);
+  void drain(uint worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq);
 
   // Set up for parallel processing of the cards in the hot cache
   void reset_hot_cache_claimed_index() {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -234,14 +234,14 @@
   HeapRegion* _from;
   OopsInHeapRegionClosure* _push_ref_cl;
   bool _record_refs_into_cset;
-  int _worker_i;
+  uint _worker_i;
 
 public:
   G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
                                 G1RemSet* rs,
                                 OopsInHeapRegionClosure* push_ref_cl,
                                 bool record_refs_into_cset,
-                                int worker_i = 0);
+                                uint worker_i = 0);
 
   void set_from(HeapRegion* from) {
     assert(from != NULL, "from region must be non-NULL");
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -113,14 +113,14 @@
   G1SATBCardTableModRefBS *_ct_bs;
 
   double _strong_code_root_scan_time_sec;
-  int    _worker_i;
+  uint   _worker_i;
   int    _block_size;
   bool   _try_claimed;
 
 public:
   ScanRSClosure(OopsInHeapRegionClosure* oc,
                 CodeBlobToOopClosure* code_root_cl,
-                int worker_i) :
+                uint worker_i) :
     _oc(oc),
     _code_root_cl(code_root_cl),
     _strong_code_root_scan_time_sec(0.0),
@@ -162,7 +162,7 @@
 
   void printCard(HeapRegion* card_region, size_t card_index,
                  HeapWord* card_start) {
-    gclog_or_tty->print_cr("T %d Region [" PTR_FORMAT ", " PTR_FORMAT ") "
+    gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
                            "RS names card %p: "
                            "[" PTR_FORMAT ", " PTR_FORMAT ")",
                            _worker_i,
@@ -241,7 +241,7 @@
 
 void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
                       CodeBlobToOopClosure* code_root_cl,
-                      int worker_i) {
+                      uint worker_i) {
   double rs_time_start = os::elapsedTime();
   HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
 
@@ -274,13 +274,13 @@
                                               DirtyCardQueue* into_cset_dcq) :
     _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq)
   {}
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
     // The only time we care about recording cards that
     // contain references that point into the collection set
     // is during RSet updating within an evacuation pause.
     // In this case worker_i should be the id of a GC worker thread.
     assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
-    assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
+    assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
 
     if (_g1rs->refine_card(card_ptr, worker_i, true)) {
       // 'card_ptr' contains references that point into the collection
@@ -295,7 +295,7 @@
   }
 };
 
-void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
+void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) {
   double start = os::elapsedTime();
   // Apply the given closure to all remaining log entries.
   RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
@@ -320,14 +320,14 @@
 
 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
                                            CodeBlobToOopClosure* code_root_cl,
-                                           int worker_i) {
+                                           uint worker_i) {
 #if CARD_REPEAT_HISTO
   ct_freq_update_histo_and_reset();
 #endif
 
   // We cache the value of 'oc' closure into the appropriate slot in the
   // _cset_rs_update_cl for this worker
-  assert(worker_i < (int)n_workers(), "sanity");
+  assert(worker_i < n_workers(), "sanity");
   _cset_rs_update_cl[worker_i] = oc;
 
   // A DirtyCardQueue that is used to hold cards containing references
@@ -399,7 +399,7 @@
     _g1(g1), _ct_bs(bs)
   { }
 
-  bool do_card_ptr(jbyte* card_ptr, int worker_i) {
+  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
     // Construct the region representing the card.
     HeapWord* start = _ct_bs->addr_for(card_ptr);
     // And find the region containing it.
@@ -543,7 +543,7 @@
                               G1RemSet* rs,
                               OopsInHeapRegionClosure* push_ref_cl,
                               bool record_refs_into_cset,
-                              int worker_i) :
+                              uint worker_i) :
   _g1(g1h), _g1_rem_set(rs), _from(NULL),
   _record_refs_into_cset(record_refs_into_cset),
   _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
@@ -552,7 +552,7 @@
 // into the collection set, if we're checking for such references;
 // false otherwise.
 
-bool G1RemSet::refine_card(jbyte* card_ptr, int worker_i,
+bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
                            bool check_for_refs_into_cset) {
 
   // If the card is no longer dirty, nothing to do.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -97,7 +97,7 @@
   // In the sequential case this param will be ignored.
   void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
                                    CodeBlobToOopClosure* code_root_cl,
-                                   int worker_i);
+                                   uint worker_i);
 
   // Prepare for and cleanup after an oops_into_collection_set_do
   // call.  Must call each of these once before and after (in sequential
@@ -109,9 +109,9 @@
 
   void scanRS(OopsInHeapRegionClosure* oc,
               CodeBlobToOopClosure* code_root_cl,
-              int worker_i);
+              uint worker_i);
 
-  void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
+  void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);
 
   CardTableModRefBS* ct_bs() { return _ct_bs; }
   size_t cardsScanned() { return _total_cards_scanned; }
@@ -138,7 +138,7 @@
   // if the given card contains oops that have references into the
   // current collection set.
   virtual bool refine_card(jbyte* card_ptr,
-                           int worker_i,
+                           uint worker_i,
                            bool check_for_refs_into_cset);
 
   // Print accumulated summary info from the start of the VM.
@@ -171,12 +171,12 @@
 class UpdateRSOopClosure: public ExtendedOopClosure {
   HeapRegion* _from;
   G1RemSet* _rs;
-  int _worker_i;
+  uint _worker_i;
 
   template <class T> void do_oop_work(T* p);
 
 public:
-  UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) :
+  UpdateRSOopClosure(G1RemSet* rs, uint worker_i = 0) :
     _from(NULL), _rs(rs), _worker_i(worker_i)
   {}
 
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -390,7 +390,7 @@
 void FromCardCache::print(outputStream* out) {
   for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
     for (uint j = 0; j < _max_regions; j++) {
-      out->print_cr("_from_card_cache["UINT32_FORMAT"]["UINT32_FORMAT"] = "INT32_FORMAT".",
+      out->print_cr("_from_card_cache[%u][%u] = %d.",
                     i, j, at(i, j));
     }
   }
@@ -430,7 +430,7 @@
   int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift);
 
   if (G1TraceHeapRegionRememberedSet) {
-    gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = "INT32_FORMAT")",
+    gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)",
                   hr()->bottom(), from_card,
                   FromCardCache::at((uint)tid, cur_hrs_ind));
   }
@@ -853,13 +853,13 @@
 // This can be done by either mutator threads together with the
 // concurrent refinement threads or GC threads.
 uint HeapRegionRemSet::num_par_rem_sets() {
-  return (uint)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
+  return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), (uint)ParallelGCThreads);
 }
 
 HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
                                    HeapRegion* hr)
   : _bosa(bosa),
-    _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #"UINT32_FORMAT, hr->hrs_index()), true),
+    _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrs_index()), true),
     _code_roots(), _other_regions(hr, &_m) {
   reset_for_par_iteration();
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -30,7 +30,7 @@
 inline void HeapRegionSetBase::add(HeapRegion* hr) {
   check_mt_safety();
   assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u"));
-  assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked"));
+  assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked"));
 
   _count.increment(1u, hr->capacity());
   hr->set_containing_set(this);
@@ -40,7 +40,7 @@
 inline void HeapRegionSetBase::remove(HeapRegion* hr) {
   check_mt_safety();
   verify_region(hr);
-  assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked"));
+  assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked"));
 
   hr->set_containing_set(NULL);
   assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition"));
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -290,7 +290,7 @@
   shared_satb_queue()->apply_closure_and_empty(_closure);
 }
 
-void SATBMarkQueueSet::par_iterate_closure_all_threads(int worker) {
+void SATBMarkQueueSet::par_iterate_closure_all_threads(uint worker) {
   SharedHeap* sh = SharedHeap::heap();
   int parity = sh->strong_roots_parity();
 
@@ -315,7 +315,7 @@
 }
 
 bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par,
-                                                              int worker) {
+                                                              uint worker) {
   BufferNode* nd = NULL;
   {
     MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -84,7 +84,7 @@
   // Utility function to support sequential and parallel versions.  If
   // "par" is true, then "worker" is the par thread id; if "false", worker
   // is ignored.
-  bool apply_closure_to_completed_buffer_work(bool par, int worker);
+  bool apply_closure_to_completed_buffer_work(bool par, uint worker);
 
 #ifdef ASSERT
   void dump_active_states(bool expected_active);
@@ -124,7 +124,7 @@
   // be called serially and at a safepoint.
   void iterate_closure_all_threads();
   // Parallel version of the above.
-  void par_iterate_closure_all_threads(int worker);
+  void par_iterate_closure_all_threads(uint worker);
 
   // If there exists some completed buffer, pop it, then apply the
   // registered closure to all its elements, and return true.  If no
@@ -133,7 +133,7 @@
     return apply_closure_to_completed_buffer_work(false, 0);
   }
   // Parallel version of the above.
-  bool par_apply_closure_to_completed_buffer(int worker) {
+  bool par_apply_closure_to_completed_buffer(uint worker) {
     return apply_closure_to_completed_buffer_work(true, worker);
   }
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -184,7 +184,7 @@
     size_t prev_used = heap->used();
 
     // Capture metadata size before collection for sizing.
-    size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes();
+    size_t metadata_prev_used = MetaspaceAux::used_bytes();
 
     // For PrintGCDetails
     size_t old_gen_prev_used = old_gen->used_in_bytes();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -928,7 +928,7 @@
     _heap_used      = heap->used();
     _young_gen_used = heap->young_gen()->used_in_bytes();
     _old_gen_used   = heap->old_gen()->used_in_bytes();
-    _metadata_used  = MetaspaceAux::allocated_used_bytes();
+    _metadata_used  = MetaspaceAux::used_bytes();
   };
 
   size_t heap_used() const      { return _heap_used; }
--- a/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -62,16 +62,16 @@
 };
 
 class MetaspaceSizes : public StackObj {
-  size_t _capacity;
+  size_t _committed;
   size_t _used;
   size_t _reserved;
 
  public:
-  MetaspaceSizes() : _capacity(0), _used(0), _reserved(0) {}
-  MetaspaceSizes(size_t capacity, size_t used, size_t reserved) :
-    _capacity(capacity), _used(used), _reserved(reserved) {}
+  MetaspaceSizes() : _committed(0), _used(0), _reserved(0) {}
+  MetaspaceSizes(size_t committed, size_t used, size_t reserved) :
+    _committed(committed), _used(used), _reserved(reserved) {}
 
-  size_t capacity() const { return _capacity; }
+  size_t committed() const { return _committed; }
   size_t used() const { return _used; }
   size_t reserved() const { return _reserved; }
 };
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -258,7 +258,7 @@
 static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) {
   TraceStructMetaspaceSizes meta_sizes;
 
-  meta_sizes.set_capacity(sizes.capacity());
+  meta_sizes.set_committed(sizes.committed());
   meta_sizes.set_used(sizes.used());
   meta_sizes.set_reserved(sizes.reserved());
 
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -85,16 +85,16 @@
 
 MetaspaceSummary CollectedHeap::create_metaspace_summary() {
   const MetaspaceSizes meta_space(
-      MetaspaceAux::allocated_capacity_bytes(),
-      MetaspaceAux::allocated_used_bytes(),
+      MetaspaceAux::committed_bytes(),
+      MetaspaceAux::used_bytes(),
       MetaspaceAux::reserved_bytes());
   const MetaspaceSizes data_space(
-      MetaspaceAux::allocated_capacity_bytes(Metaspace::NonClassType),
-      MetaspaceAux::allocated_used_bytes(Metaspace::NonClassType),
+      MetaspaceAux::committed_bytes(Metaspace::NonClassType),
+      MetaspaceAux::used_bytes(Metaspace::NonClassType),
       MetaspaceAux::reserved_bytes(Metaspace::NonClassType));
   const MetaspaceSizes class_space(
-      MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType),
-      MetaspaceAux::allocated_used_bytes(Metaspace::ClassType),
+      MetaspaceAux::committed_bytes(Metaspace::ClassType),
+      MetaspaceAux::used_bytes(Metaspace::ClassType),
       MetaspaceAux::reserved_bytes(Metaspace::ClassType));
 
   const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary =
@@ -582,36 +582,6 @@
   }
 }
 
-oop CollectedHeap::Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS) {
-  debug_only(check_for_valid_allocation_state());
-  assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
-  assert(size >= 0, "int won't convert to size_t");
-  HeapWord* obj;
-    assert(ScavengeRootsInCode > 0, "must be");
-    obj = common_mem_allocate_init(real_klass, size, CHECK_NULL);
-  post_allocation_setup_common(klass, obj);
-  assert(Universe::is_bootstrapping() ||
-         !((oop)obj)->is_array(), "must not be an array");
-  NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
-  oop mirror = (oop)obj;
-
-  java_lang_Class::set_oop_size(mirror, size);
-
-  // Setup indirections
-  if (!real_klass.is_null()) {
-    java_lang_Class::set_klass(mirror, real_klass());
-    real_klass->set_java_mirror(mirror);
-  }
-
-  InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass());
-  assert(size == mk->instance_size(real_klass), "should have been set");
-
-  // notify jvmti and dtrace
-  post_allocation_notify(klass, (oop)obj);
-
-  return mirror;
-}
-
 /////////////// Unit tests ///////////////
 
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -312,9 +312,6 @@
   // May be overridden to set additional parallelism.
   virtual void set_par_threads(uint t) { _n_par_threads = t; };
 
-  // Allocate and initialize instances of Class
-  static oop Class_obj_allocate(KlassHandle klass, int size, KlassHandle real_klass, TRAPS);
-
   // General obj/array allocation facilities.
   inline static oop obj_allocate(KlassHandle klass, int size, TRAPS);
   inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS);
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -257,6 +257,12 @@
   assert(_min_gen0_size % _gen_alignment == 0, "_min_gen0_size alignment");
   assert(_initial_gen0_size % _gen_alignment == 0, "_initial_gen0_size alignment");
   assert(_max_gen0_size % _gen_alignment == 0, "_max_gen0_size alignment");
+  assert(_min_gen0_size <= bound_minus_alignment(_min_gen0_size, _min_heap_byte_size),
+      "Ergonomics made minimum young generation larger than minimum heap");
+  assert(_initial_gen0_size <=  bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size),
+      "Ergonomics made initial young generation larger than initial heap");
+  assert(_max_gen0_size <= bound_minus_alignment(_max_gen0_size, _max_heap_byte_size),
+      "Ergonomics made maximum young generation lager than maximum heap");
 }
 
 void TwoGenerationCollectorPolicy::assert_size_info() {
@@ -267,6 +273,9 @@
   assert(_max_gen1_size % _gen_alignment == 0, "_max_gen1_size alignment");
   assert(_initial_gen1_size % _gen_alignment == 0, "_initial_gen1_size alignment");
   assert(_max_heap_byte_size <= (_max_gen0_size + _max_gen1_size), "Total maximum heap sizes must be sum of generation maximum sizes");
+  assert(_min_gen0_size + _min_gen1_size <= _min_heap_byte_size, "Minimum generation sizes exceed minimum heap size");
+  assert(_initial_gen0_size + _initial_gen1_size == _initial_heap_byte_size, "Initial generation sizes should match initial heap size");
+  assert(_max_gen0_size + _max_gen1_size == _max_heap_byte_size, "Maximum generation sizes should match maximum heap size");
 }
 #endif // ASSERT
 
@@ -303,20 +312,26 @@
     }
   }
 
+  // Make sure NewSize allows an old generation to fit even if set on the command line
+  if (FLAG_IS_CMDLINE(NewSize) && NewSize >= _initial_heap_byte_size) {
+    warning("NewSize was set larger than initial heap size, will use initial heap size.");
+    NewSize = bound_minus_alignment(NewSize, _initial_heap_byte_size);
+  }
+
   // Now take the actual NewSize into account. We will silently increase NewSize
   // if the user specified a smaller or unaligned value.
-  smallest_new_size = MAX2(smallest_new_size, (uintx)align_size_down(NewSize, _gen_alignment));
-  if (smallest_new_size != NewSize) {
+  uintx bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize);
+  bounded_new_size = MAX2(smallest_new_size, (uintx)align_size_down(bounded_new_size, _gen_alignment));
+  if (bounded_new_size != NewSize) {
     // Do not use FLAG_SET_ERGO to update NewSize here, since this will override
     // if NewSize was set on the command line or not. This information is needed
     // later when setting the initial and minimum young generation size.
-    NewSize = smallest_new_size;
+    NewSize = bounded_new_size;
   }
+  _min_gen0_size = smallest_new_size;
   _initial_gen0_size = NewSize;
 
   if (!FLAG_IS_DEFAULT(MaxNewSize)) {
-    uintx min_new_size = MAX2(_gen_alignment, _min_gen0_size);
-
     if (MaxNewSize >= MaxHeapSize) {
       // Make sure there is room for an old generation
       uintx smaller_max_new_size = MaxHeapSize - _gen_alignment;
@@ -330,8 +345,8 @@
         FLAG_SET_ERGO(uintx, NewSize, MaxNewSize);
         _initial_gen0_size = NewSize;
       }
-    } else if (MaxNewSize < min_new_size) {
-      FLAG_SET_ERGO(uintx, MaxNewSize, min_new_size);
+    } else if (MaxNewSize < _initial_gen0_size) {
+      FLAG_SET_ERGO(uintx, MaxNewSize, _initial_gen0_size);
     } else if (!is_size_aligned(MaxNewSize, _gen_alignment)) {
       FLAG_SET_ERGO(uintx, MaxNewSize, align_size_down(MaxNewSize, _gen_alignment));
     }
@@ -361,7 +376,9 @@
   GenCollectorPolicy::initialize_flags();
 
   if (!is_size_aligned(OldSize, _gen_alignment)) {
-    FLAG_SET_ERGO(uintx, OldSize, align_size_down(OldSize, _gen_alignment));
+    // Setting OldSize directly to preserve information about the possible
+    // setting of OldSize on the command line.
+    OldSize = align_size_down(OldSize, _gen_alignment);
   }
 
   if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) {
@@ -400,6 +417,20 @@
     }
   }
 
+  // Update NewSize, if possible, to avoid sizing gen0 to small when only
+  // OldSize is set on the command line.
+  if (FLAG_IS_CMDLINE(OldSize) && !FLAG_IS_CMDLINE(NewSize)) {
+    if (OldSize < _initial_heap_byte_size) {
+      size_t new_size = _initial_heap_byte_size - OldSize;
+      // Need to compare against the flag value for max since _max_gen0_size
+      // might not have been set yet.
+      if (new_size >= _min_gen0_size && new_size <= MaxNewSize) {
+        FLAG_SET_ERGO(uintx, NewSize, new_size);
+        _initial_gen0_size = NewSize;
+      }
+    }
+  }
+
   always_do_update_barrier = UseConcMarkSweepGC;
 
   DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_flags();)
@@ -441,57 +472,37 @@
   // Given the maximum gen0 size, determine the initial and
   // minimum gen0 sizes.
 
-  if (_max_heap_byte_size == _min_heap_byte_size) {
-    // The maximum and minimum heap sizes are the same so the generations
-    // minimum and initial must be the same as its maximum.
-    _min_gen0_size = max_new_size;
-    _initial_gen0_size = max_new_size;
-    _max_gen0_size = max_new_size;
+  if (_max_heap_byte_size == _initial_heap_byte_size) {
+    // The maxium and initial heap sizes are the same so the generation's
+    // initial size must be the same as it maximum size. Use NewSize as the
+    // size if set on command line.
+    size_t fixed_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : max_new_size;
+
+    _initial_gen0_size = fixed_young_size;
+    _max_gen0_size = fixed_young_size;
+
+    // Also update the minimum size if min == initial == max.
+    if (_max_heap_byte_size == _min_heap_byte_size) {
+      _min_gen0_size = fixed_young_size;
+    }
   } else {
     size_t desired_new_size = 0;
     if (FLAG_IS_CMDLINE(NewSize)) {
-      // If NewSize is set on the command line, we must use it as
-      // the initial size and it also makes sense to use it as the
-      // lower limit.
-      _min_gen0_size = NewSize;
-      desired_new_size = NewSize;
-      max_new_size = MAX2(max_new_size, NewSize);
-    } else if (FLAG_IS_ERGO(NewSize)) {
-      // If NewSize is set ergonomically, we should use it as a lower
-      // limit, but use NewRatio to calculate the initial size.
-      _min_gen0_size = NewSize;
+      // If NewSize is set on the command line, we should use it as
+      // the initial size, but make sure it is within the heap bounds.
       desired_new_size =
-        MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize);
-      max_new_size = MAX2(max_new_size, NewSize);
+        MIN2(max_new_size, bound_minus_alignment(NewSize, _initial_heap_byte_size));
+      _min_gen0_size = bound_minus_alignment(desired_new_size, _min_heap_byte_size);
     } else {
-      // For the case where NewSize is the default, use NewRatio
-      // to size the minimum and initial generation sizes.
-      // Use the default NewSize as the floor for these values.  If
-      // NewRatio is overly large, the resulting sizes can be too small.
-      _min_gen0_size = MAX2(scale_by_NewRatio_aligned(_min_heap_byte_size), NewSize);
+      // For the case where NewSize is not set on the command line, use
+      // NewRatio to size the initial generation size. Use the current
+      // NewSize as the floor, because if NewRatio is overly large, the resulting
+      // size can be too small.
       desired_new_size =
-        MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize);
+        MIN2(max_new_size, MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize));
     }
-
-    assert(_min_gen0_size > 0, "Sanity check");
     _initial_gen0_size = desired_new_size;
     _max_gen0_size = max_new_size;
-
-    // At this point the desirable initial and minimum sizes have been
-    // determined without regard to the maximum sizes.
-
-    // Bound the sizes by the corresponding overall heap sizes.
-    _min_gen0_size = bound_minus_alignment(_min_gen0_size, _min_heap_byte_size);
-    _initial_gen0_size = bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size);
-    _max_gen0_size = bound_minus_alignment(_max_gen0_size, _max_heap_byte_size);
-
-    // At this point all three sizes have been checked against the
-    // maximum sizes but have not been checked for consistency among the three.
-
-    // Final check min <= initial <= max
-    _min_gen0_size = MIN2(_min_gen0_size, _max_gen0_size);
-    _initial_gen0_size = MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size);
-    _min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size);
   }
 
   // Write back to flags if necessary.
@@ -512,33 +523,6 @@
   DEBUG_ONLY(GenCollectorPolicy::assert_size_info();)
 }
 
-// Call this method during the sizing of the gen1 to make
-// adjustments to gen0 because of gen1 sizing policy.  gen0 initially has
-// the most freedom in sizing because it is done before the
-// policy for gen1 is applied.  Once gen1 policies have been applied,
-// there may be conflicts in the shape of the heap and this method
-// is used to make the needed adjustments.  The application of the
-// policies could be more sophisticated (iterative for example) but
-// keeping it simple also seems a worthwhile goal.
-bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
-                                                     size_t* gen1_size_ptr,
-                                                     const size_t heap_size) {
-  bool result = false;
-
-  if ((*gen0_size_ptr + *gen1_size_ptr) > heap_size) {
-    uintx smallest_new_size = young_gen_size_lower_bound();
-    if ((heap_size < (*gen0_size_ptr + _min_gen1_size)) &&
-        (heap_size >= _min_gen1_size + smallest_new_size)) {
-      // Adjust gen0 down to accommodate _min_gen1_size
-      *gen0_size_ptr = align_size_down_bounded(heap_size - _min_gen1_size, _gen_alignment);
-      result = true;
-    } else {
-      *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _gen_alignment);
-    }
-  }
-  return result;
-}
-
 // Minimum sizes of the generations may be different than
 // the initial sizes.  An inconsistency is permitted here
 // in the total size that can be specified explicitly by
@@ -564,57 +548,64 @@
     // with the overall heap size).  In either case make
     // the minimum, maximum and initial sizes consistent
     // with the gen0 sizes and the overall heap sizes.
-    _min_gen1_size = MAX2(_min_heap_byte_size - _min_gen0_size, _gen_alignment);
-    _initial_gen1_size = MAX2(_initial_heap_byte_size - _initial_gen0_size, _gen_alignment);
+    _min_gen1_size = _gen_alignment;
+    _initial_gen1_size = MIN2(_max_gen1_size, MAX2(_initial_heap_byte_size - _initial_gen0_size, _min_gen1_size));
     // _max_gen1_size has already been made consistent above
     FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size);
   } else {
-    // OldSize has been explicitly set on the command line. Use the
-    // OldSize and then determine the consequences.
-    _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size);
-    _initial_gen1_size = OldSize;
-
+    // OldSize has been explicitly set on the command line. Use it
+    // for the initial size but make sure the minimum allow a young
+    // generation to fit as well.
     // If the user has explicitly set an OldSize that is inconsistent
     // with other command line flags, issue a warning.
     // The generation minimums and the overall heap minimum should
     // be within one generation alignment.
-    if ((_min_gen1_size + _min_gen0_size + _gen_alignment) < _min_heap_byte_size) {
-      warning("Inconsistency between minimum heap size and minimum "
-              "generation sizes: using minimum heap = " SIZE_FORMAT,
-              _min_heap_byte_size);
-    }
     if (OldSize > _max_gen1_size) {
       warning("Inconsistency between maximum heap size and maximum "
-              "generation sizes: using maximum heap = " SIZE_FORMAT
-              " -XX:OldSize flag is being ignored",
-              _max_heap_byte_size);
+          "generation sizes: using maximum heap = " SIZE_FORMAT
+          " -XX:OldSize flag is being ignored",
+          _max_heap_byte_size);
+      FLAG_SET_ERGO(uintx, OldSize, _max_gen1_size);
     }
-    // If there is an inconsistency between the OldSize and the minimum and/or
-    // initial size of gen0, since OldSize was explicitly set, OldSize wins.
-    if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, _min_heap_byte_size)) {
-      if (PrintGCDetails && Verbose) {
-        gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
-              SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
-              _min_gen0_size, _initial_gen0_size, _max_gen0_size);
-      }
+
+    _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size);
+    _initial_gen1_size = OldSize;
+  }
+
+  // The initial generation sizes should match the initial heap size,
+  // if not issue a warning and resize the generations. This behavior
+  // differs from JDK8 where the generation sizes have higher priority
+  // than the initial heap size.
+  if ((_initial_gen1_size + _initial_gen0_size) != _initial_heap_byte_size) {
+    warning("Inconsistency between generation sizes and heap size, resizing "
+            "the generations to fit the heap.");
+
+    size_t desired_gen0_size = _initial_heap_byte_size - _initial_gen1_size;
+    if (_initial_heap_byte_size < _initial_gen1_size) {
+      // Old want all memory, use minimum for young and rest for old
+      _initial_gen0_size = _min_gen0_size;
+      _initial_gen1_size = _initial_heap_byte_size - _min_gen0_size;
+    } else if (desired_gen0_size > _max_gen0_size) {
+      // Need to increase both young and old generation
+      _initial_gen0_size = _max_gen0_size;
+      _initial_gen1_size = _initial_heap_byte_size - _max_gen0_size;
+    } else if (desired_gen0_size < _min_gen0_size) {
+      // Need to decrease both young and old generation
+      _initial_gen0_size = _min_gen0_size;
+      _initial_gen1_size = _initial_heap_byte_size - _min_gen0_size;
+    } else {
+      // The young generation boundaries allow us to only update the
+      // young generation.
+      _initial_gen0_size = desired_gen0_size;
     }
-    // The same as above for the old gen initial size.
-    if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
-                          _initial_heap_byte_size)) {
-      if (PrintGCDetails && Verbose) {
-        gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
-          SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
-          _min_gen0_size, _initial_gen0_size, _max_gen0_size);
-      }
+
+    if (PrintGCDetails && Verbose) {
+      gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
+        SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
+        _min_gen0_size, _initial_gen0_size, _max_gen0_size);
     }
   }
 
-  _min_gen1_size = MIN2(_min_gen1_size, _max_gen1_size);
-
-  // Make sure that min gen1 <= initial gen1 <= max gen1.
-  _initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size);
-  _initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size);
-
   // Write back to flags if necessary
   if (NewSize != _initial_gen0_size) {
     FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size);
@@ -994,56 +985,88 @@
 // verify that there are some basic rules for NewSize honored by the policies.
 class TestGenCollectorPolicy {
 public:
-  static void test() {
+  static void test_new_size() {
     size_t flag_value;
 
     save_flags();
 
-    // Set some limits that makes the math simple.
-    FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M);
-    FLAG_SET_ERGO(uintx, InitialHeapSize, 120 * M);
-    Arguments::set_min_heap_size(40 * M);
-
     // If NewSize is set on the command line, it should be used
     // for both min and initial young size if less than min heap.
     flag_value = 20 * M;
+    set_basic_flag_values();
     FLAG_SET_CMDLINE(uintx, NewSize, flag_value);
-    verify_min(flag_value);
-    verify_initial(flag_value);
+    verify_gen0_min(flag_value);
+
+    set_basic_flag_values();
+    FLAG_SET_CMDLINE(uintx, NewSize, flag_value);
+    verify_gen0_initial(flag_value);
 
     // If NewSize is set on command line, but is larger than the min
     // heap size, it should only be used for initial young size.
     flag_value = 80 * M;
+    set_basic_flag_values();
     FLAG_SET_CMDLINE(uintx, NewSize, flag_value);
-    verify_initial(flag_value);
+    verify_gen0_initial(flag_value);
 
     // If NewSize has been ergonomically set, the collector policy
     // should use it for min but calculate the initial young size
     // using NewRatio.
     flag_value = 20 * M;
+    set_basic_flag_values();
     FLAG_SET_ERGO(uintx, NewSize, flag_value);
-    verify_min(flag_value);
-    verify_scaled_initial(InitialHeapSize);
+    verify_gen0_min(flag_value);
+
+    set_basic_flag_values();
+    FLAG_SET_ERGO(uintx, NewSize, flag_value);
+    verify_scaled_gen0_initial(InitialHeapSize);
 
     restore_flags();
+  }
+
+  static void test_old_size() {
+      size_t flag_value;
+
+      save_flags();
+
+      // If OldSize is set on the command line, it should be used
+      // for both min and initial old size if less than min heap.
+      flag_value = 20 * M;
+      set_basic_flag_values();
+      FLAG_SET_CMDLINE(uintx, OldSize, flag_value);
+      verify_gen1_min(flag_value);
+
+      set_basic_flag_values();
+      FLAG_SET_CMDLINE(uintx, OldSize, flag_value);
+      verify_gen1_initial(flag_value);
+
+      // If MaxNewSize is large, the maximum OldSize will be less than
+      // what's requested on the command line and it should be reset
+      // ergonomically.
+      flag_value = 30 * M;
+      set_basic_flag_values();
+      FLAG_SET_CMDLINE(uintx, OldSize, flag_value);
+      FLAG_SET_CMDLINE(uintx, MaxNewSize, 170*M);
+      // Calculate what we expect the flag to be.
+      flag_value = MaxHeapSize - MaxNewSize;
+      verify_gen1_initial(flag_value);
 
   }
 
-  static void verify_min(size_t expected) {
+  static void verify_gen0_min(size_t expected) {
     MarkSweepPolicy msp;
     msp.initialize_all();
 
     assert(msp.min_gen0_size() <= expected, err_msg("%zu  > %zu", msp.min_gen0_size(), expected));
   }
 
-  static void verify_initial(size_t expected) {
+  static void verify_gen0_initial(size_t expected) {
     MarkSweepPolicy msp;
     msp.initialize_all();
 
     assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected));
   }
 
-  static void verify_scaled_initial(size_t initial_heap_size) {
+  static void verify_scaled_gen0_initial(size_t initial_heap_size) {
     MarkSweepPolicy msp;
     msp.initialize_all();
 
@@ -1053,6 +1076,21 @@
         err_msg("NewSize should have been set ergonomically to %zu, but was %zu", expected, NewSize));
   }
 
+  static void verify_gen1_min(size_t expected) {
+    MarkSweepPolicy msp;
+    msp.initialize_all();
+
+    assert(msp.min_gen1_size() <= expected, err_msg("%zu  > %zu", msp.min_gen1_size(), expected));
+  }
+
+  static void verify_gen1_initial(size_t expected) {
+    MarkSweepPolicy msp;
+    msp.initialize_all();
+
+    assert(msp.initial_gen1_size() == expected, err_msg("%zu != %zu", msp.initial_gen1_size(), expected));
+  }
+
+
 private:
   static size_t original_InitialHeapSize;
   static size_t original_MaxHeapSize;
@@ -1061,6 +1099,15 @@
   static size_t original_NewSize;
   static size_t original_OldSize;
 
+  static void set_basic_flag_values() {
+    FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M);
+    FLAG_SET_ERGO(uintx, InitialHeapSize, 100 * M);
+    FLAG_SET_ERGO(uintx, OldSize, 4 * M);
+    FLAG_SET_ERGO(uintx, NewSize, 1 * M);
+    FLAG_SET_ERGO(uintx, MaxNewSize, 80 * M);
+    Arguments::set_min_heap_size(40 * M);
+  }
+
   static void save_flags() {
     original_InitialHeapSize   = InitialHeapSize;
     original_MaxHeapSize       = MaxHeapSize;
@@ -1088,7 +1135,11 @@
 size_t TestGenCollectorPolicy::original_OldSize           = 0;
 
 void TestNewSize_test() {
-  TestGenCollectorPolicy::test();
+  TestGenCollectorPolicy::test_new_size();
+}
+
+void TestOldSize_test() {
+  TestGenCollectorPolicy::test_old_size();
 }
 
 #endif
--- a/hotspot/src/share/vm/memory/collectorPolicy.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -248,13 +248,13 @@
   // Compute max heap alignment.
   size_t compute_max_alignment();
 
- // Scale the base_size by NewRatio according to
- //     result = base_size / (NewRatio + 1)
- // and align by min_alignment()
- size_t scale_by_NewRatio_aligned(size_t base_size);
+  // Scale the base_size by NewRatio according to
+  //     result = base_size / (NewRatio + 1)
+  // and align by min_alignment()
+  size_t scale_by_NewRatio_aligned(size_t base_size);
 
- // Bound the value by the given maximum minus the min_alignment.
- size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
+  // Bound the value by the given maximum minus the min_alignment.
+  size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
 
  public:
   GenCollectorPolicy();
@@ -335,10 +335,6 @@
   virtual CollectorPolicy::Name kind() {
     return CollectorPolicy::TwoGenerationCollectorPolicyKind;
   }
-
-  // Returns true if gen0 sizes were adjusted
-  bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr,
-                         const size_t heap_size);
 };
 
 class MarkSweepPolicy : public TwoGenerationCollectorPolicy {
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -374,7 +374,7 @@
 
   ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());
 
-  const size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes();
+  const size_t metadata_prev_used = MetaspaceAux::used_bytes();
 
   print_heap_before_gc();
 
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1447,7 +1447,7 @@
   uint current_shrink_factor = _shrink_factor;
   _shrink_factor = 0;
 
-  const size_t used_after_gc = MetaspaceAux::allocated_capacity_bytes();
+  const size_t used_after_gc = MetaspaceAux::capacity_bytes();
   const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC();
 
   const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;
@@ -2538,8 +2538,8 @@
 // MetaspaceAux
 
 
-size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0};
-size_t MetaspaceAux::_allocated_used_words[] = {0, 0};
+size_t MetaspaceAux::_capacity_words[] = {0, 0};
+size_t MetaspaceAux::_used_words[] = {0, 0};
 
 size_t MetaspaceAux::free_bytes(Metaspace::MetadataType mdtype) {
   VirtualSpaceList* list = Metaspace::get_space_list(mdtype);
@@ -2552,38 +2552,38 @@
 
 void MetaspaceAux::dec_capacity(Metaspace::MetadataType mdtype, size_t words) {
   assert_lock_strong(SpaceManager::expand_lock());
-  assert(words <= allocated_capacity_words(mdtype),
+  assert(words <= capacity_words(mdtype),
     err_msg("About to decrement below 0: words " SIZE_FORMAT
-            " is greater than _allocated_capacity_words[%u] " SIZE_FORMAT,
-            words, mdtype, allocated_capacity_words(mdtype)));
-  _allocated_capacity_words[mdtype] -= words;
+            " is greater than _capacity_words[%u] " SIZE_FORMAT,
+            words, mdtype, capacity_words(mdtype)));
+  _capacity_words[mdtype] -= words;
 }
 
 void MetaspaceAux::inc_capacity(Metaspace::MetadataType mdtype, size_t words) {
   assert_lock_strong(SpaceManager::expand_lock());
   // Needs to be atomic
-  _allocated_capacity_words[mdtype] += words;
+  _capacity_words[mdtype] += words;
 }
 
 void MetaspaceAux::dec_used(Metaspace::MetadataType mdtype, size_t words) {
-  assert(words <= allocated_used_words(mdtype),
+  assert(words <= used_words(mdtype),
     err_msg("About to decrement below 0: words " SIZE_FORMAT
-            " is greater than _allocated_used_words[%u] " SIZE_FORMAT,
-            words, mdtype, allocated_used_words(mdtype)));
+            " is greater than _used_words[%u] " SIZE_FORMAT,
+            words, mdtype, used_words(mdtype)));
   // For CMS deallocation of the Metaspaces occurs during the
   // sweep which is a concurrent phase.  Protection by the expand_lock()
   // is not enough since allocation is on a per Metaspace basis
   // and protected by the Metaspace lock.
   jlong minus_words = (jlong) - (jlong) words;
-  Atomic::add_ptr(minus_words, &_allocated_used_words[mdtype]);
+  Atomic::add_ptr(minus_words, &_used_words[mdtype]);
 }
 
 void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) {
-  // _allocated_used_words tracks allocations for
+  // _used_words tracks allocations for
   // each piece of metadata.  Those allocations are
   // generally done concurrently by different application
   // threads so must be done atomically.
-  Atomic::add_ptr(words, &_allocated_used_words[mdtype]);
+  Atomic::add_ptr(words, &_used_words[mdtype]);
 }
 
 size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) {
@@ -2630,16 +2630,16 @@
 
 size_t MetaspaceAux::capacity_bytes_slow() {
 #ifdef PRODUCT
-  // Use allocated_capacity_bytes() in PRODUCT instead of this function.
+  // Use capacity_bytes() in PRODUCT instead of this function.
   guarantee(false, "Should not call capacity_bytes_slow() in the PRODUCT");
 #endif
   size_t class_capacity = capacity_bytes_slow(Metaspace::ClassType);
   size_t non_class_capacity = capacity_bytes_slow(Metaspace::NonClassType);
-  assert(allocated_capacity_bytes() == class_capacity + non_class_capacity,
-      err_msg("bad accounting: allocated_capacity_bytes() " SIZE_FORMAT
+  assert(capacity_bytes() == class_capacity + non_class_capacity,
+      err_msg("bad accounting: capacity_bytes() " SIZE_FORMAT
         " class_capacity + non_class_capacity " SIZE_FORMAT
         " class_capacity " SIZE_FORMAT " non_class_capacity " SIZE_FORMAT,
-        allocated_capacity_bytes(), class_capacity + non_class_capacity,
+        capacity_bytes(), class_capacity + non_class_capacity,
         class_capacity, non_class_capacity));
 
   return class_capacity + non_class_capacity;
@@ -2699,14 +2699,14 @@
                         "->" SIZE_FORMAT
                         "("  SIZE_FORMAT ")",
                         prev_metadata_used,
-                        allocated_used_bytes(),
+                        used_bytes(),
                         reserved_bytes());
   } else {
     gclog_or_tty->print(" "  SIZE_FORMAT "K"
                         "->" SIZE_FORMAT "K"
                         "("  SIZE_FORMAT "K)",
                         prev_metadata_used/K,
-                        allocated_used_bytes()/K,
+                        used_bytes()/K,
                         reserved_bytes()/K);
   }
 
@@ -2722,8 +2722,8 @@
                 "capacity "  SIZE_FORMAT "K, "
                 "committed " SIZE_FORMAT "K, "
                 "reserved "  SIZE_FORMAT "K",
-                allocated_used_bytes()/K,
-                allocated_capacity_bytes()/K,
+                used_bytes()/K,
+                capacity_bytes()/K,
                 committed_bytes()/K,
                 reserved_bytes()/K);
 
@@ -2734,8 +2734,8 @@
                   "capacity "  SIZE_FORMAT "K, "
                   "committed " SIZE_FORMAT "K, "
                   "reserved "  SIZE_FORMAT "K",
-                  allocated_used_bytes(ct)/K,
-                  allocated_capacity_bytes(ct)/K,
+                  used_bytes(ct)/K,
+                  capacity_bytes(ct)/K,
                   committed_bytes(ct)/K,
                   reserved_bytes(ct)/K);
   }
@@ -2837,42 +2837,42 @@
 
 void MetaspaceAux::verify_capacity() {
 #ifdef ASSERT
-  size_t running_sum_capacity_bytes = allocated_capacity_bytes();
+  size_t running_sum_capacity_bytes = capacity_bytes();
   // For purposes of the running sum of capacity, verify against capacity
   size_t capacity_in_use_bytes = capacity_bytes_slow();
   assert(running_sum_capacity_bytes == capacity_in_use_bytes,
-    err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT
+    err_msg("capacity_words() * BytesPerWord " SIZE_FORMAT
             " capacity_bytes_slow()" SIZE_FORMAT,
             running_sum_capacity_bytes, capacity_in_use_bytes));
   for (Metaspace::MetadataType i = Metaspace::ClassType;
        i < Metaspace:: MetadataTypeCount;
        i = (Metaspace::MetadataType)(i + 1)) {
     size_t capacity_in_use_bytes = capacity_bytes_slow(i);
-    assert(allocated_capacity_bytes(i) == capacity_in_use_bytes,
-      err_msg("allocated_capacity_bytes(%u) " SIZE_FORMAT
+    assert(capacity_bytes(i) == capacity_in_use_bytes,
+      err_msg("capacity_bytes(%u) " SIZE_FORMAT
               " capacity_bytes_slow(%u)" SIZE_FORMAT,
-              i, allocated_capacity_bytes(i), i, capacity_in_use_bytes));
+              i, capacity_bytes(i), i, capacity_in_use_bytes));
   }
 #endif
 }
 
 void MetaspaceAux::verify_used() {
 #ifdef ASSERT
-  size_t running_sum_used_bytes = allocated_used_bytes();
+  size_t running_sum_used_bytes = used_bytes();
   // For purposes of the running sum of used, verify against used
   size_t used_in_use_bytes = used_bytes_slow();
-  assert(allocated_used_bytes() == used_in_use_bytes,
-    err_msg("allocated_used_bytes() " SIZE_FORMAT
+  assert(used_bytes() == used_in_use_bytes,
+    err_msg("used_bytes() " SIZE_FORMAT
             " used_bytes_slow()" SIZE_FORMAT,
-            allocated_used_bytes(), used_in_use_bytes));
+            used_bytes(), used_in_use_bytes));
   for (Metaspace::MetadataType i = Metaspace::ClassType;
        i < Metaspace:: MetadataTypeCount;
        i = (Metaspace::MetadataType)(i + 1)) {
     size_t used_in_use_bytes = used_bytes_slow(i);
-    assert(allocated_used_bytes(i) == used_in_use_bytes,
-      err_msg("allocated_used_bytes(%u) " SIZE_FORMAT
+    assert(used_bytes(i) == used_in_use_bytes,
+      err_msg("used_bytes(%u) " SIZE_FORMAT
               " used_bytes_slow(%u)" SIZE_FORMAT,
-              i, allocated_used_bytes(i), i, used_in_use_bytes));
+              i, used_bytes(i), i, used_in_use_bytes));
   }
 #endif
 }
--- a/hotspot/src/share/vm/memory/metaspace.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -280,11 +280,11 @@
   // allocated to a Metaspace.  This is used instead of
   // iterating over all the classloaders. One for each
   // type of Metadata
-  static size_t _allocated_capacity_words[Metaspace:: MetadataTypeCount];
-  // Running sum of space in all Metachunks that have
+  static size_t _capacity_words[Metaspace:: MetadataTypeCount];
+  // Running sum of space in all Metachunks that
   // are being used for metadata. One for each
   // type of Metadata.
-  static size_t _allocated_used_words[Metaspace:: MetadataTypeCount];
+  static size_t _used_words[Metaspace:: MetadataTypeCount];
 
  public:
   // Decrement and increment _allocated_capacity_words
@@ -308,32 +308,32 @@
   static size_t free_chunks_total_bytes();
   static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype);
 
-  static size_t allocated_capacity_words(Metaspace::MetadataType mdtype) {
-    return _allocated_capacity_words[mdtype];
+  static size_t capacity_words(Metaspace::MetadataType mdtype) {
+    return _capacity_words[mdtype];
   }
-  static size_t allocated_capacity_words() {
-    return allocated_capacity_words(Metaspace::NonClassType) +
-           allocated_capacity_words(Metaspace::ClassType);
+  static size_t capacity_words() {
+    return capacity_words(Metaspace::NonClassType) +
+           capacity_words(Metaspace::ClassType);
   }
-  static size_t allocated_capacity_bytes(Metaspace::MetadataType mdtype) {
-    return allocated_capacity_words(mdtype) * BytesPerWord;
+  static size_t capacity_bytes(Metaspace::MetadataType mdtype) {
+    return capacity_words(mdtype) * BytesPerWord;
   }
-  static size_t allocated_capacity_bytes() {
-    return allocated_capacity_words() * BytesPerWord;
+  static size_t capacity_bytes() {
+    return capacity_words() * BytesPerWord;
   }
 
-  static size_t allocated_used_words(Metaspace::MetadataType mdtype) {
-    return _allocated_used_words[mdtype];
+  static size_t used_words(Metaspace::MetadataType mdtype) {
+    return _used_words[mdtype];
   }
-  static size_t allocated_used_words() {
-    return allocated_used_words(Metaspace::NonClassType) +
-           allocated_used_words(Metaspace::ClassType);
+  static size_t used_words() {
+    return used_words(Metaspace::NonClassType) +
+           used_words(Metaspace::ClassType);
   }
-  static size_t allocated_used_bytes(Metaspace::MetadataType mdtype) {
-    return allocated_used_words(mdtype) * BytesPerWord;
+  static size_t used_bytes(Metaspace::MetadataType mdtype) {
+    return used_words(mdtype) * BytesPerWord;
   }
-  static size_t allocated_used_bytes() {
-    return allocated_used_words() * BytesPerWord;
+  static size_t used_bytes() {
+    return used_words() * BytesPerWord;
   }
 
   static size_t free_bytes();
--- a/hotspot/src/share/vm/memory/metaspaceCounters.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceCounters.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -66,7 +66,7 @@
 MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL;
 
 size_t MetaspaceCounters::used() {
-  return MetaspaceAux::allocated_used_bytes();
+  return MetaspaceAux::used_bytes();
 }
 
 size_t MetaspaceCounters::capacity() {
@@ -98,7 +98,7 @@
 MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL;
 
 size_t CompressedClassSpaceCounters::used() {
-  return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType);
+  return MetaspaceAux::used_bytes(Metaspace::ClassType);
 }
 
 size_t CompressedClassSpaceCounters::capacity() {
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -144,6 +144,10 @@
 // CDS support. Create a new resolved_references array.
 void ConstantPool::restore_unshareable_info(TRAPS) {
 
+  // Only create the new resolved references array and lock if it hasn't been
+  // attempted before
+  if (resolved_references() != NULL) return;
+
   // restore the C++ vtable from the shared archive
   restore_vtable();
 
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1289,17 +1289,18 @@
 }
 
 
-void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS) {
+void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) {
   instanceKlassHandle h_this(THREAD, this);
-  do_local_static_fields_impl(h_this, f, CHECK);
+  do_local_static_fields_impl(h_this, f, mirror, CHECK);
 }
 
 
-void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
+void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k,
+                             void f(fieldDescriptor* fd, Handle, TRAPS), Handle mirror, TRAPS) {
   for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) {
     if (fs.access_flags().is_static()) {
       fieldDescriptor& fd = fs.field_descriptor();
-      f(&fd, CHECK);
+      f(&fd, mirror, CHECK);
     }
   }
 }
@@ -2240,9 +2241,7 @@
   int num_methods = methods->length();
   for (int index2 = 0; index2 < num_methods; ++index2) {
     methodHandle m(THREAD, methods->at(index2));
-    m()->link_method(m, CHECK);
-    // restore method's vtable by calling a virtual function
-    m->restore_vtable();
+    m->restore_unshareable_info(CHECK);
   }
   if (JvmtiExport::has_redefined_a_class()) {
     // Reinitialize vtable because RedefineClasses may have changed some
@@ -3409,6 +3408,10 @@
               ("purge: %s(%s): prev method @%d in version @%d is alive",
               method->name()->as_C_string(),
               method->signature()->as_C_string(), j, i));
+            if (method->method_data() != NULL) {
+              // Clean out any weak method links
+              method->method_data()->clean_weak_method_links();
+            }
           }
         }
       }
@@ -3418,6 +3421,14 @@
       ("purge: previous version stats: live=%d, deleted=%d", live_count,
       deleted_count));
   }
+
+  Array<Method*>* methods = ik->methods();
+  int num_methods = methods->length();
+  for (int index2 = 0; index2 < num_methods; ++index2) {
+    if (methods->at(index2)->method_data() != NULL) {
+      methods->at(index2)->method_data()->clean_weak_method_links();
+    }
+  }
 }
 
 // External interface for use during class unloading.
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -802,7 +802,7 @@
   // Iterators
   void do_local_static_fields(FieldClosure* cl);
   void do_nonstatic_fields(FieldClosure* cl); // including inherited fields
-  void do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS);
+  void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS);
 
   void methods_do(void f(Method* method));
   void array_klasses_do(void f(Klass* k));
@@ -1010,7 +1010,7 @@
   static void set_initialization_state_and_notify_impl  (instanceKlassHandle this_k, ClassState state, TRAPS);
   static void call_class_initializer_impl               (instanceKlassHandle this_k, TRAPS);
   static Klass* array_klass_impl                        (instanceKlassHandle this_k, bool or_null, int n, TRAPS);
-  static void do_local_static_fields_impl               (instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS);
+  static void do_local_static_fields_impl               (instanceKlassHandle this_k, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS);
   /* jni_id_for_impl for jfieldID only */
   static JNIid* jni_id_for_impl                         (instanceKlassHandle this_k, int offset);
 
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -367,7 +367,12 @@
   // Query before forming handle.
   int size = instance_size(k);
   KlassHandle h_k(THREAD, this);
-  instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL);
+  instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
+
+  // Since mirrors can be variable sized because of the static fields, store
+  // the size in the mirror itself.
+  java_lang_Class::set_oop_size(i, size);
+
   return i;
 }
 
--- a/hotspot/src/share/vm/oops/klass.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/klass.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -475,12 +475,8 @@
 }
 
 void Klass::remove_unshareable_info() {
-  if (!DumpSharedSpaces) {
-    // Clean up after OOM during class loading
-    if (class_loader_data() != NULL) {
-      class_loader_data()->remove_class(this);
-    }
-  }
+  assert (DumpSharedSpaces, "only called for DumpSharedSpaces");
+
   set_subklass(NULL);
   set_next_sibling(NULL);
   // Clear the java mirror
@@ -492,17 +488,26 @@
 }
 
 void Klass::restore_unshareable_info(TRAPS) {
-  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
-  // Restore class_loader_data to the null class loader data
-  set_class_loader_data(loader_data);
+  // If an exception happened during CDS restore, some of these fields may already be
+  // set.  We leave the class on the CLD list, even if incomplete so that we don't
+  // modify the CLD list outside a safepoint.
+  if (class_loader_data() == NULL) {
+    ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+    // Restore class_loader_data to the null class loader data
+    set_class_loader_data(loader_data);
 
-  // Add to null class loader list first before creating the mirror
-  // (same order as class file parsing)
-  loader_data->add_class(this);
+    // Add to null class loader list first before creating the mirror
+    // (same order as class file parsing)
+    loader_data->add_class(this);
+  }
 
   // Recreate the class mirror.  The protection_domain is always null for
   // boot loader, for now.
-  java_lang_Class::create_mirror(this, Handle(NULL), CHECK);
+  // Only recreate it if not present.  A previous attempt to restore may have
+  // gotten an OOM later but keep the mirror if it was created.
+  if (java_mirror() == NULL) {
+    java_lang_Class::create_mirror(this, Handle(NULL), CHECK);
+  }
 }
 
 Klass* Klass::array_klass_or_null(int rank) {
--- a/hotspot/src/share/vm/oops/method.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -903,6 +903,19 @@
   return adapter->get_c2i_entry();
 }
 
+void Method::restore_unshareable_info(TRAPS) {
+  // Since restore_unshareable_info can be called more than once for a method, don't
+  // redo any work.   If this field is restored, there is nothing to do.
+  if (_from_compiled_entry == NULL) {
+    // restore method's vtable by calling a virtual function
+    restore_vtable();
+
+    methodHandle mh(THREAD, this);
+    link_method(mh, CHECK);
+  }
+}
+
+
 // The verified_code_entry() must be called when a invoke is resolved
 // on this method.
 
--- a/hotspot/src/share/vm/oops/method.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -123,6 +123,8 @@
   void restore_vtable() { guarantee(is_method(), "vtable restored by this call"); }
   bool is_method() const volatile { return true; }
 
+  void restore_unshareable_info(TRAPS);
+
   // accessors for instance variables
 
   ConstMethod* constMethod() const             { return _constMethod; }
--- a/hotspot/src/share/vm/oops/methodData.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1531,9 +1531,35 @@
   }
 }
 
-// Remove SpeculativeTrapData entries that reference an unloaded
-// method
-void MethodData::clean_extra_data(BoolObjectClosure* is_alive) {
+class CleanExtraDataClosure : public StackObj {
+public:
+  virtual bool is_live(Method* m) = 0;
+};
+
+// Check for entries that reference an unloaded method
+class CleanExtraDataKlassClosure : public CleanExtraDataClosure {
+private:
+  BoolObjectClosure* _is_alive;
+public:
+  CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {}
+  bool is_live(Method* m) {
+    return m->method_holder()->is_loader_alive(_is_alive);
+  }
+};
+
+// Check for entries that reference a redefined method
+class CleanExtraDataMethodClosure : public CleanExtraDataClosure {
+public:
+  CleanExtraDataMethodClosure() {}
+  bool is_live(Method* m) {
+    return m->on_stack();
+  }
+};
+
+
+// Remove SpeculativeTrapData entries that reference an unloaded or
+// redefined method
+void MethodData::clean_extra_data(CleanExtraDataClosure* cl) {
   DataLayout* dp  = extra_data_base();
   DataLayout* end = extra_data_limit();
 
@@ -1544,7 +1570,7 @@
       SpeculativeTrapData* data = new SpeculativeTrapData(dp);
       Method* m = data->method();
       assert(m != NULL, "should have a method");
-      if (!m->method_holder()->is_loader_alive(is_alive)) {
+      if (!cl->is_live(m)) {
         // "shift" accumulates the number of cells for dead
         // SpeculativeTrapData entries that have been seen so
         // far. Following entries must be shifted left by that many
@@ -1575,9 +1601,9 @@
   }
 }
 
-// Verify there's no unloaded method referenced by a
+// Verify there's no unloaded or redefined method referenced by a
 // SpeculativeTrapData entry
-void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) {
+void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) {
 #ifdef ASSERT
   DataLayout* dp  = extra_data_base();
   DataLayout* end = extra_data_limit();
@@ -1587,7 +1613,7 @@
     case DataLayout::speculative_trap_data_tag: {
       SpeculativeTrapData* data = new SpeculativeTrapData(dp);
       Method* m = data->method();
-      assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist");
+      assert(m != NULL && cl->is_live(m), "Method should exist");
       break;
     }
     case DataLayout::bit_data_tag:
@@ -1613,6 +1639,19 @@
     parameters->clean_weak_klass_links(is_alive);
   }
 
-  clean_extra_data(is_alive);
-  verify_extra_data_clean(is_alive);
+  CleanExtraDataKlassClosure cl(is_alive);
+  clean_extra_data(&cl);
+  verify_extra_data_clean(&cl);
 }
+
+void MethodData::clean_weak_method_links() {
+  for (ProfileData* data = first_data();
+       is_valid(data);
+       data = next_data(data)) {
+    data->clean_weak_method_links();
+  }
+
+  CleanExtraDataMethodClosure cl;
+  clean_extra_data(&cl);
+  verify_extra_data_clean(&cl);
+}
--- a/hotspot/src/share/vm/oops/methodData.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -251,6 +251,9 @@
 
   // GC support
   void clean_weak_klass_links(BoolObjectClosure* cl);
+
+  // Redefinition support
+  void clean_weak_method_links();
 };
 
 
@@ -506,6 +509,9 @@
   // GC support
   virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {}
 
+  // Redefinition support
+  virtual void clean_weak_method_links() {}
+
   // CI translation: ProfileData can represent both MethodDataOop data
   // as well as CIMethodData data. This function is provided for translating
   // an oop in a ProfileData to the ci equivalent. Generally speaking,
@@ -1989,6 +1995,7 @@
 //
 
 CC_INTERP_ONLY(class BytecodeInterpreter;)
+class CleanExtraDataClosure;
 
 class MethodData : public Metadata {
   friend class VMStructs;
@@ -2146,9 +2153,9 @@
   static bool profile_parameters_jsr292_only();
   static bool profile_all_parameters();
 
-  void clean_extra_data(BoolObjectClosure* is_alive);
+  void clean_extra_data(CleanExtraDataClosure* cl);
   void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false);
-  void verify_extra_data_clean(BoolObjectClosure* is_alive);
+  void verify_extra_data_clean(CleanExtraDataClosure* cl);
 
 public:
   static int header_size() {
@@ -2440,6 +2447,8 @@
   static bool profile_return_jsr292_only();
 
   void clean_method_data(BoolObjectClosure* is_alive);
+
+  void clean_weak_method_links();
 };
 
 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -269,7 +269,7 @@
         if (element_is_null ||
             (new_val->klass())->is_subtype_of(bound)) {
           bs->write_ref_field_pre(p, new_val);
-          *p = *from;
+          *p = element;
         } else {
           // We must do a barrier to cover the partial copy.
           const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -70,6 +70,7 @@
 
 JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   Compile* C = Compile::current();
+  C->print_inlining_update(this);
 
   if (is_osr()) {
     // The JVMS for a OSR has a single argument (see its TypeFunc).
@@ -126,6 +127,7 @@
 
 JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
+  kit.C->print_inlining_update(this);
   bool is_static = method()->is_static();
   address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
                              : SharedRuntime::get_resolve_opt_virtual_call_stub();
@@ -178,6 +180,8 @@
   GraphKit kit(jvms);
   Node* receiver = kit.argument(0);
 
+  kit.C->print_inlining_update(this);
+
   if (kit.C->log() != NULL) {
     kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
   }
@@ -271,14 +275,13 @@
   LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
     DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
 
-  virtual bool      is_late_inline() const { return true; }
+  virtual bool is_late_inline() const { return true; }
 
   // Convert the CallStaticJava into an inline
   virtual void do_late_inline();
 
   virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     Compile *C = Compile::current();
-    C->print_inlining_skip(this);
 
     // Record that this call site should be revisited once the main
     // parse is finished.
@@ -296,10 +299,11 @@
   virtual void print_inlining_late(const char* msg) {
     CallNode* call = call_node();
     Compile* C = Compile::current();
-    C->print_inlining_insert(this);
+    C->print_inlining_assert_ready();
     C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg);
+    C->print_inlining_move_to(this);
+    C->print_inlining_update_delayed(this);
   }
-
 };
 
 void LateInlineCallGenerator::do_late_inline() {
@@ -360,6 +364,10 @@
     map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1));
   }
 
+  C->print_inlining_assert_ready();
+
+  C->print_inlining_move_to(this);
+
   // This check is done here because for_method_handle_inline() method
   // needs jvms for inlined state.
   if (!do_late_inline_check(jvms)) {
@@ -367,8 +375,6 @@
     return;
   }
 
-  C->print_inlining_insert(this);
-
   CompileLog* log = C->log();
   if (log != NULL) {
     log->head("late_inline method='%d'", log->identify(method()));
@@ -388,7 +394,7 @@
     C->set_default_node_notes(entry_nn);
   }
 
-  // Now perform the inling using the synthesized JVMState
+  // Now perform the inlining using the synthesized JVMState
   JVMState* new_jvms = _inline_cg->generate(jvms, NULL);
   if (new_jvms == NULL)  return;  // no change
   if (C->failing())      return;
@@ -431,6 +437,7 @@
 
   virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser);
+
     if (_input_not_const) {
       // inlining won't be possible so no need to enqueue right now.
       call_node()->set_generator(this);
@@ -439,17 +446,14 @@
     }
     return new_jvms;
   }
-
-  virtual void print_inlining_late(const char* msg) {
-    if (!_input_not_const) return;
-    LateInlineCallGenerator::print_inlining_late(msg);
-  }
 };
 
 bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) {
 
   CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const);
 
+  Compile::current()->print_inlining_update_delayed(this);
+
   if (!_input_not_const) {
     _attempt++;
   }
@@ -479,8 +483,6 @@
 
   virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     Compile *C = Compile::current();
-    C->print_inlining_skip(this);
-
     C->add_string_late_inline(this);
 
     JVMState* new_jvms =  DirectCallGenerator::generate(jvms, parent_parser);
@@ -502,7 +504,6 @@
 
   virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
     Compile *C = Compile::current();
-    C->print_inlining_skip(this);
 
     C->add_boxing_late_inline(this);
 
@@ -554,6 +555,8 @@
 
 JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   Compile* C = Compile::current();
+  C->print_inlining_update(this);
+
   if (C->log() != NULL) {
     C->log()->elem("warm_call bci='%d'", jvms->bci());
   }
@@ -632,6 +635,7 @@
 
 JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
+  kit.C->print_inlining_update(this);
   PhaseGVN& gvn = kit.gvn();
   // We need an explicit receiver null_check before checking its type.
   // We share a map with the caller, so his JVMS gets adjusted.
@@ -779,6 +783,9 @@
         assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
         if (cg != NULL && cg->is_inline())
           return cg;
+      } else {
+        const char* msg = "receiver not constant";
+        if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);
       }
     }
     break;
@@ -844,11 +851,13 @@
           // provide us with a type
           speculative_receiver_type = receiver_type->speculative_type();
         }
-
         CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true);
         assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
         if (cg != NULL && cg->is_inline())
           return cg;
+      } else {
+        const char* msg = "member_name not constant";
+        if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);
       }
     }
     break;
@@ -904,6 +913,7 @@
   if (kit.failing())
     return NULL;  // might happen because of NodeCountInliningCutoff
 
+  kit.C->print_inlining_update(this);
   SafePointNode* slow_map = NULL;
   JVMState* slow_jvms;
   if (slow_ctl != NULL) {
@@ -1017,6 +1027,7 @@
 
 JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
   GraphKit kit(jvms);
+  kit.C->print_inlining_update(this);
   // Take the trap with arguments pushed on the stack.  (Cf. null_check_receiver).
   int nargs = method()->arg_size();
   kit.inc_sp(nargs);
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -662,6 +662,7 @@
                   _inlining_progress(false),
                   _inlining_incrementally(false),
                   _print_inlining_list(NULL),
+                  _print_inlining_stream(NULL),
                   _print_inlining_idx(0),
                   _preserve_jvm_state(0) {
   C = this;
@@ -723,9 +724,7 @@
   PhaseGVN gvn(node_arena(), estimated_size);
   set_initial_gvn(&gvn);
 
-  if (print_inlining() || print_intrinsics()) {
-    _print_inlining_list = new (comp_arena())GrowableArray<PrintInliningBuffer>(comp_arena(), 1, 1, PrintInliningBuffer());
-  }
+  print_inlining_init();
   { // Scope for timing the parser
     TracePhase t3("parse", &_t_parser, true);
 
@@ -967,6 +966,7 @@
     _inlining_progress(false),
     _inlining_incrementally(false),
     _print_inlining_list(NULL),
+    _print_inlining_stream(NULL),
     _print_inlining_idx(0),
     _preserve_jvm_state(0),
     _allowed_reasons(0) {
@@ -2023,6 +2023,8 @@
   ResourceMark rm;
   int          loop_opts_cnt;
 
+  print_inlining_reinit();
+
   NOT_PRODUCT( verify_graph_edges(); )
 
   print_method(PHASE_AFTER_PARSING);
@@ -3755,30 +3757,114 @@
   }
 }
 
-void Compile::dump_inlining() {
+// The message about the current inlining is accumulated in
+// _print_inlining_stream and transfered into the _print_inlining_list
+// once we know whether inlining succeeds or not. For regular
+// inlining, messages are appended to the buffer pointed by
+// _print_inlining_idx in the _print_inlining_list. For late inlining,
+// a new buffer is added after _print_inlining_idx in the list. This
+// way we can update the inlining message for late inlining call site
+// when the inlining is attempted again.
+void Compile::print_inlining_init() {
+  if (print_inlining() || print_intrinsics()) {
+    _print_inlining_stream = new stringStream();
+    _print_inlining_list = new (comp_arena())GrowableArray<PrintInliningBuffer>(comp_arena(), 1, 1, PrintInliningBuffer());
+  }
+}
+
+void Compile::print_inlining_reinit() {
+  if (print_inlining() || print_intrinsics()) {
+    // Re allocate buffer when we change ResourceMark
+    _print_inlining_stream = new stringStream();
+  }
+}
+
+void Compile::print_inlining_reset() {
+  _print_inlining_stream->reset();
+}
+
+void Compile::print_inlining_commit() {
+  assert(print_inlining() || print_intrinsics(), "PrintInlining off?");
+  // Transfer the message from _print_inlining_stream to the current
+  // _print_inlining_list buffer and clear _print_inlining_stream.
+  _print_inlining_list->at(_print_inlining_idx).ss()->write(_print_inlining_stream->as_string(), _print_inlining_stream->size());
+  print_inlining_reset();
+}
+
+void Compile::print_inlining_push() {
+  // Add new buffer to the _print_inlining_list at current position
+  _print_inlining_idx++;
+  _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer());
+}
+
+Compile::PrintInliningBuffer& Compile::print_inlining_current() {
+  return _print_inlining_list->at(_print_inlining_idx);
+}
+
+void Compile::print_inlining_update(CallGenerator* cg) {
   if (print_inlining() || print_intrinsics()) {
+    if (!cg->is_late_inline()) {
+      if (print_inlining_current().cg() != NULL) {
+        print_inlining_push();
+      }
+      print_inlining_commit();
+    } else {
+      if (print_inlining_current().cg() != cg &&
+          (print_inlining_current().cg() != NULL ||
+           print_inlining_current().ss()->size() != 0)) {
+        print_inlining_push();
+      }
+      print_inlining_commit();
+      print_inlining_current().set_cg(cg);
+    }
+  }
+}
+
+void Compile::print_inlining_move_to(CallGenerator* cg) {
+  // We resume inlining at a late inlining call site. Locate the
+  // corresponding inlining buffer so that we can update it.
+  if (print_inlining()) {
+    for (int i = 0; i < _print_inlining_list->length(); i++) {
+      if (_print_inlining_list->adr_at(i)->cg() == cg) {
+        _print_inlining_idx = i;
+        return;
+      }
+    }
+    ShouldNotReachHere();
+  }
+}
+
+void Compile::print_inlining_update_delayed(CallGenerator* cg) {
+  if (print_inlining()) {
+    assert(_print_inlining_stream->size() > 0, "missing inlining msg");
+    assert(print_inlining_current().cg() == cg, "wrong entry");
+    // replace message with new message
+    _print_inlining_list->at_put(_print_inlining_idx, PrintInliningBuffer());
+    print_inlining_commit();
+    print_inlining_current().set_cg(cg);
+  }
+}
+
+void Compile::print_inlining_assert_ready() {
+  assert(!_print_inlining || _print_inlining_stream->size() == 0, "loosing data");
+}
+
+void Compile::dump_inlining() {
+  bool do_print_inlining = print_inlining() || print_intrinsics();
+  if (do_print_inlining) {
     // Print inlining message for candidates that we couldn't inline
-    // for lack of space or non constant receiver
+    // for lack of space
     for (int i = 0; i < _late_inlines.length(); i++) {
       CallGenerator* cg = _late_inlines.at(i);
-      cg->print_inlining_late("live nodes > LiveNodeCountInliningCutoff");
-    }
-    Unique_Node_List useful;
-    useful.push(root());
-    for (uint next = 0; next < useful.size(); ++next) {
-      Node* n  = useful.at(next);
-      if (n->is_Call() && n->as_Call()->generator() != NULL && n->as_Call()->generator()->call_node() == n) {
-        CallNode* call = n->as_Call();
-        CallGenerator* cg = call->generator();
-        cg->print_inlining_late("receiver not constant");
-      }
-      uint max = n->len();
-      for ( uint i = 0; i < max; ++i ) {
-        Node *m = n->in(i);
-        if ( m == NULL ) continue;
-        useful.push(m);
+      if (!cg->is_mh_late_inline()) {
+        const char* msg = "live nodes > LiveNodeCountInliningCutoff";
+        if (do_print_inlining) {
+          cg->print_inlining_late(msg);
+        }
       }
     }
+  }
+  if (do_print_inlining) {
     for (int i = 0; i < _print_inlining_list->length(); i++) {
       tty->print(_print_inlining_list->adr_at(i)->ss()->as_string());
     }
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -416,6 +416,7 @@
     void set_cg(CallGenerator* cg) { _cg = cg; }
   };
 
+  stringStream* _print_inlining_stream;
   GrowableArray<PrintInliningBuffer>* _print_inlining_list;
   int _print_inlining_idx;
 
@@ -433,33 +434,24 @@
 
   void* _replay_inline_data; // Pointer to data loaded from file
 
+  void print_inlining_init();
+  void print_inlining_reinit();
+  void print_inlining_commit();
+  void print_inlining_push();
+  PrintInliningBuffer& print_inlining_current();
+
  public:
 
   outputStream* print_inlining_stream() const {
-    return _print_inlining_list->adr_at(_print_inlining_idx)->ss();
-  }
-
-  void print_inlining_skip(CallGenerator* cg) {
-    if (_print_inlining) {
-      _print_inlining_list->adr_at(_print_inlining_idx)->set_cg(cg);
-      _print_inlining_idx++;
-      _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer());
-    }
+    assert(print_inlining() || print_intrinsics(), "PrintInlining off?");
+    return _print_inlining_stream;
   }
 
-  void print_inlining_insert(CallGenerator* cg) {
-    if (_print_inlining) {
-      for (int i = 0; i < _print_inlining_list->length(); i++) {
-        if (_print_inlining_list->adr_at(i)->cg() == cg) {
-          _print_inlining_list->insert_before(i+1, PrintInliningBuffer());
-          _print_inlining_idx = i+1;
-          _print_inlining_list->adr_at(i)->set_cg(NULL);
-          return;
-        }
-      }
-      ShouldNotReachHere();
-    }
-  }
+  void print_inlining_update(CallGenerator* cg);
+  void print_inlining_update_delayed(CallGenerator* cg);
+  void print_inlining_move_to(CallGenerator* cg);
+  void print_inlining_assert_ready();
+  void print_inlining_reset();
 
   void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
     stringStream ss;
--- a/hotspot/src/share/vm/opto/doCall.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -294,6 +294,8 @@
   // There was no special inlining tactic, or it bailed out.
   // Use a more generic tactic, like a simple call.
   if (call_does_dispatch) {
+    const char* msg = "virtual call";
+    if (PrintInlining) print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);
     return CallGenerator::for_virtual_call(callee, vtable_index);
   } else {
     // Class Hierarchy Analysis or Type Profile reveals a unique target,
@@ -396,6 +398,8 @@
   // our contribution to it is cleaned up right here.
   kill_dead_locals();
 
+  C->print_inlining_assert_ready();
+
   // Set frequently used booleans
   const bool is_virtual = bc() == Bytecodes::_invokevirtual;
   const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
@@ -531,7 +535,8 @@
     // intrinsic was expecting to optimize. Should always be possible to
     // get a normal java call that may inline in that case
     cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false);
-    if ((new_jvms = cg->generate(jvms, this)) == NULL) {
+    new_jvms = cg->generate(jvms, this);
+    if (new_jvms == NULL) {
       guarantee(failing(), "call failed to generate:  calls should work");
       return;
     }
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -620,6 +620,7 @@
     }
     // Push the result from the inlined method onto the stack.
     kit.push_result();
+    C->print_inlining_update(this);
     return kit.transfer_exceptions_into_jvms();
   }
 
@@ -637,6 +638,7 @@
     }
   }
   C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
+  C->print_inlining_update(this);
   return NULL;
 }
 
--- a/hotspot/src/share/vm/prims/jni.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -3877,6 +3877,7 @@
 void TestMetachunk_test();
 void TestVirtualSpaceNode_test();
 void TestNewSize_test();
+void TestOldSize_test();
 void TestKlass_test();
 void TestBitMap_test();
 #if INCLUDE_ALL_GCS
@@ -3903,6 +3904,7 @@
     run_unit_test(AltHashing::test_alt_hash());
     run_unit_test(test_loggc_filename());
     run_unit_test(TestNewSize_test());
+    run_unit_test(TestOldSize_test());
     run_unit_test(TestKlass_test());
     run_unit_test(TestBitMap_test());
 #if INCLUDE_VM_STRUCTS
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -438,6 +438,30 @@
   return (mh->queued_for_compilation() || nm != NULL);
 WB_END
 
+class VM_WhiteBoxOperation : public VM_Operation {
+ public:
+  VM_WhiteBoxOperation()                         { }
+  VMOp_Type type()                  const        { return VMOp_WhiteBoxOperation; }
+  bool allow_nested_vm_operations() const        { return true; }
+};
+
+class AlwaysFalseClosure : public BoolObjectClosure {
+ public:
+  bool do_object_b(oop p) { return false; }
+};
+
+static AlwaysFalseClosure always_false;
+
+class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation {
+ public:
+  VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { }
+  void doit() {
+    _mdo->clean_method_data(&always_false);
+  }
+ private:
+  MethodData* _mdo;
+};
+
 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION(env);
@@ -453,6 +477,8 @@
     for (int i = 0; i < arg_count; i++) {
       mdo->set_arg_modified(i, 0);
     }
+    VM_WhiteBoxCleanMethodData op(mdo);
+    VMThread::execute(&op);
   }
 
   mh->clear_not_c1_compilable();
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -307,6 +307,9 @@
                            JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },
 #endif // PRODUCT
   { "UseVMInterruptibleIO",          JDK_Version::jdk(8), JDK_Version::jdk(9) },
+  { "UseBoundThreads",               JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "DefaultThreadPriority",         JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "NoYieldsInMicrolock",           JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { NULL, JDK_Version(0), JDK_Version(0) }
 };
 
@@ -2078,17 +2081,6 @@
   // Note: Needs platform-dependent factoring.
   bool status = true;
 
-  // Allow both -XX:-UseStackBanging and -XX:-UseBoundThreads in non-product
-  // builds so the cost of stack banging can be measured.
-#if (defined(PRODUCT) && defined(SOLARIS))
-  if (!UseBoundThreads && !UseStackBanging) {
-    jio_fprintf(defaultStream::error_stream(),
-                "-UseStackBanging conflicts with -UseBoundThreads\n");
-
-     status = false;
-  }
-#endif
-
   if (TLABRefillWasteFraction == 0) {
     jio_fprintf(defaultStream::error_stream(),
                 "TLABRefillWasteFraction should be a denominator, "
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -929,6 +929,10 @@
 }
 
 void os::print_date_and_time(outputStream *st) {
+  const int secs_per_day  = 86400;
+  const int secs_per_hour = 3600;
+  const int secs_per_min  = 60;
+
   time_t tloc;
   (void)time(&tloc);
   st->print("time: %s", ctime(&tloc));  // ctime adds newline.
@@ -937,7 +941,17 @@
   // NOTE: It tends to crash after a SEGV if we want to printf("%f",...) in
   //       Linux. Must be a bug in glibc ? Workaround is to round "t" to int
   //       before printf. We lost some precision, but who cares?
-  st->print_cr("elapsed time: %d seconds", (int)t);
+  int eltime = (int)t;  // elapsed time in seconds
+
+  // print elapsed time in a human-readable format:
+  int eldays = eltime / secs_per_day;
+  int day_secs = eldays * secs_per_day;
+  int elhours = (eltime - day_secs) / secs_per_hour;
+  int hour_secs = elhours * secs_per_hour;
+  int elmins = (eltime - day_secs - hour_secs) / secs_per_min;
+  int minute_secs = elmins * secs_per_min;
+  int elsecs = (eltime - day_secs - hour_secs - minute_secs);
+  st->print_cr("elapsed time: %d seconds (%dd %dh %dm %ds)", eltime, eldays, elhours, elmins, elsecs);
 }
 
 // moved from debug.cpp (used to be find()) but still called from there
--- a/hotspot/src/share/vm/runtime/os.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -450,8 +450,8 @@
     // yield that can be used in lieu of blocking.
   } ;
   static YieldResult NakedYield () ;
-  static void yield_all(int attempts = 0); // Yields to all other threads including lower priority
-  static void loop_breaker(int attempts);  // called from within tight loops to possibly influence time-sharing
+  static void yield_all(); // Yields to all other threads including lower priority
+                           // (for the default scheduling policy)
   static OSReturn set_priority(Thread* thread, ThreadPriority priority);
   static OSReturn get_priority(const Thread* const thread, ThreadPriority& priority);
 
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -319,7 +319,7 @@
       if (steps < DeferThrSuspendLoopCount) {
         os::NakedYield() ;
       } else {
-        os::yield_all(steps) ;
+        os::yield_all() ;
         // Alternately, the VM thread could transiently depress its scheduling priority or
         // transiently increase the priority of the tardy mutator(s).
       }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -924,12 +924,6 @@
 JRT_END
 #endif // !PRODUCT
 
-
-JRT_ENTRY(void, SharedRuntime::yield_all(JavaThread* thread, int attempts))
-  os::yield_all(attempts);
-JRT_END
-
-
 JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
   assert(obj->is_oop(), "must be a valid oop");
   assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
@@ -1268,8 +1262,6 @@
       }
 #endif
       if (is_virtual) {
-        nmethod* nm = callee_nm;
-        if (nm == NULL) CodeCache::find_blob(caller_frame.pc());
         CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc());
         if (inline_cache->is_clean()) {
           inline_cache->set_to_monomorphic(virtual_call_info);
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -253,9 +253,6 @@
   // bytecode tracing is only used by the TraceBytecodes
   static intptr_t trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2) PRODUCT_RETURN0;
 
-  // Used to back off a spin lock that is under heavy contention
-  static void yield_all(JavaThread* thread, int attempts = 0);
-
   static oop retrieve_receiver( Symbol* sig, frame caller );
 
   static void register_finalizer(JavaThread* thread, oopDesc* obj);
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1394,8 +1394,8 @@
 void JavaThread::initialize() {
   // Initialize fields
 
-  // Set the claimed par_id to -1 (ie not claiming any par_ids)
-  set_claimed_par_id(-1);
+  // Set the claimed par_id to UINT_MAX (ie not claiming any par_ids)
+  set_claimed_par_id(UINT_MAX);
 
   set_saved_exception_pc(NULL);
   set_threadObj(NULL);
--- a/hotspot/src/share/vm/runtime/thread.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1778,12 +1778,12 @@
   void set_done_attaching_via_jni() { _jni_attach_state = _attached_via_jni; OrderAccess::fence(); }
 private:
   // This field is used to determine if a thread has claimed
-  // a par_id: it is -1 if the thread has not claimed a par_id;
+  // a par_id: it is UINT_MAX if the thread has not claimed a par_id;
   // otherwise its value is the par_id that has been claimed.
-  int _claimed_par_id;
+  uint _claimed_par_id;
 public:
-  int get_claimed_par_id() { return _claimed_par_id; }
-  void set_claimed_par_id(int id) { _claimed_par_id = id;}
+  uint get_claimed_par_id() { return _claimed_par_id; }
+  void set_claimed_par_id(uint id) { _claimed_par_id = id;}
 };
 
 // Inline implementation of JavaThread::current
--- a/hotspot/src/share/vm/runtime/vframe.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -321,24 +321,38 @@
   }
 }
 
-StackValueCollection*  interpretedVFrame::expressions() const {
-  int length = fr().interpreter_frame_expression_stack_size();
-  if (method()->is_native()) {
-    // If the method is native, there is no expression stack
-    length = 0;
+StackValueCollection* interpretedVFrame::expressions() const {
+
+  InterpreterOopMap oop_mask;
+
+  if (!method()->is_native()) {
+    // Get oopmap describing oops and int for current bci
+    if (TraceDeoptimization && Verbose) {
+      methodHandle m_h(method());
+      OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
+    } else {
+      method()->mask_for(bci(), &oop_mask);
+    }
+  }
+
+  // If the bci is a call instruction, i.e. any of the invoke* instructions,
+  // the InterpreterOopMap does not include expression/operand stack liveness
+  // info in the oop_mask/bit_mask. This can lead to a discrepancy of what
+  // is actually on the expression stack compared to what is given by the
+  // oop_map. We need to use the length reported in the oop_map.
+  int length = oop_mask.expression_stack_size();
+
+  assert(fr().interpreter_frame_expression_stack_size() >= length,
+    "error in expression stack!");
+
+  StackValueCollection* result = new StackValueCollection(length);
+
+  if (0 == length) {
+    return result;
   }
 
   int nof_locals = method()->max_locals();
-  StackValueCollection* result = new StackValueCollection(length);
 
-  InterpreterOopMap oop_mask;
-  // Get oopmap describing oops and int for current bci
-  if (TraceDeoptimization && Verbose) {
-    methodHandle m_h(method());
-    OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
-  } else {
-    method()->mask_for(bci(), &oop_mask);
-  }
   // handle expressions
   for(int i=0; i < length; i++) {
     // Find stack location
--- a/hotspot/src/share/vm/runtime/vmThread.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -305,6 +305,9 @@
     _terminate_lock->notify();
   }
 
+  // Thread destructor usually does this.
+  ThreadLocalStorage::set_thread(NULL);
+
   // Deletion must be done synchronously by the JNI DestroyJavaVM thread
   // so that the VMThread deletion completes before the main thread frees
   // up the CodeHeap.
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Wed Jul 05 19:37:28 2017 +0200
@@ -97,6 +97,7 @@
   template(Exit)                                  \
   template(LinuxDllLoad)                          \
   template(RotateGCLog)                           \
+  template(WhiteBoxOperation)                     \
 
 class VM_Operation: public CHeapObj<mtInternal> {
  public:
--- a/hotspot/src/share/vm/services/memoryPool.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/services/memoryPool.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -268,7 +268,7 @@
 }
 
 size_t MetaspacePool::used_in_bytes() {
-  return MetaspaceAux::allocated_used_bytes();
+  return MetaspaceAux::used_bytes();
 }
 
 size_t MetaspacePool::calculate_max_size() const {
@@ -280,7 +280,7 @@
   MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { }
 
 size_t CompressedKlassSpacePool::used_in_bytes() {
-  return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType);
+  return MetaspaceAux::used_bytes(Metaspace::ClassType);
 }
 
 MemoryUsage CompressedKlassSpacePool::get_memory_usage() {
--- a/hotspot/src/share/vm/trace/trace.xml	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/trace/trace.xml	Wed Jul 05 19:37:28 2017 +0200
@@ -185,7 +185,7 @@
     </event>
 
     <struct id="MetaspaceSizes">
-      <value type="BYTES64" field="capacity" label="Capacity" description="Total available memory to allocate in" />
+      <value type="BYTES64" field="committed" label="Committed" description="Committed memory for this space" />
       <value type="BYTES64" field="used" label="Used" description="Bytes allocated by objects in the space" />
       <value type="BYTES64" field="reserved" label="Reserved" description="Reserved memory for this space" />
     </struct>
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -239,8 +239,8 @@
 
 #ifdef TRACESPINNING
 void ParallelTaskTerminator::print_termination_counts() {
-  gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT
-    " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT,
+  gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %u"
+    " Total spins: %u Total peeks: %u",
     total_yields(),
     total_spins(),
     total_peeks());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+import java.security.*;
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+import java.lang.management.ManagementFactory;
+import com.sun.tools.attach.VirtualMachine;
+
+class A {
+    void m() {
+    }
+}
+
+class B extends A {
+    void m() {
+    }
+}
+
+class C extends A {
+    void m() {
+    }
+}
+
+class Test {
+
+    static public void m() throws Exception {
+        for (int i = 0; i < 20000; i++) {
+            m1(a);
+        }
+        for (int i = 0; i < 4; i++) {
+            m1(b);
+        }
+    }
+
+    static boolean m1(A a) {
+        boolean res =  Agent.m2(a);
+        return res;
+    }
+
+    static public A a = new A();
+    static public B b = new B();
+    static public C c = new C();
+}
+
+public class Agent implements ClassFileTransformer {
+
+
+    static class MemoryChunk {
+        MemoryChunk other;
+        long[] array;
+        MemoryChunk(MemoryChunk other) {
+            other = other;
+            array = new long[1024 * 1024 * 1024];
+        }
+    }
+
+    static public boolean m2(A a) {
+        boolean res = false;
+        if (a.getClass() == B.class) {
+            a.m();
+        } else {
+            res = true;
+        }
+        return res;
+    }
+
+    static public void main(String[] args) throws Exception {
+        // Create speculative trap entries
+        Test.m();
+
+        String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
+        int p = nameOfRunningVM.indexOf('@');
+        String pid = nameOfRunningVM.substring(0, p);
+
+        // Make the nmethod go away
+        for (int i = 0; i < 10; i++) {
+            System.gc();
+        }
+
+        // Redefine class
+        try {
+            VirtualMachine vm = VirtualMachine.attach(pid);
+            vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", "");
+            vm.detach();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        Test.m();
+        // GC will hit dead method pointer
+        for (int i = 0; i < 10; i++) {
+            System.gc();
+        }
+    }
+
+    public synchronized byte[] transform(final ClassLoader classLoader,
+                                         final String className,
+                                         Class<?> classBeingRedefined,
+                                         ProtectionDomain protectionDomain,
+                                         byte[] classfileBuffer) {
+        System.out.println("Transforming class " + className);
+        return classfileBuffer;
+    }
+
+    public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
+
+        try {
+            instrumentation.retransformClasses(to_redefine);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception {
+        Agent transformer = new Agent();
+        instrumentation.addTransformer(transformer, true);
+
+        redefine(agentArgs, instrumentation, Test.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+import java.io.PrintWriter;
+import com.oracle.java.testlibrary.*;
+
+/*
+ * @test
+ * @bug 8038636
+ * @library /testlibrary
+ * @build Agent
+ * @run main ClassFileInstaller Agent
+ * @run main Launcher
+ * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent
+ */
+public class Launcher {
+    public static void main(String[] args) throws Exception  {
+
+      PrintWriter pw = new PrintWriter("MANIFEST.MF");
+      pw.println("Agent-Class: Agent");
+      pw.println("Can-Retransform-Classes: true");
+      pw.close();
+
+      ProcessBuilder pb = new ProcessBuilder();
+      pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"});
+      pb.start().waitFor();
+    }
+}
--- a/hotspot/test/gc/g1/TestStringDeduplicationTools.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTools.java	Wed Jul 05 19:37:28 2017 +0200
@@ -310,7 +310,9 @@
             }
 
             System.gc();
+
             System.out.println("Heap Memory Usage: " + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed());
+            System.out.println("Array Header Size: " + unsafe.ARRAY_CHAR_BASE_OFFSET);
 
             System.out.println("End: MemoryUsageTest");
         }
@@ -482,31 +484,40 @@
     public static void testMemoryUsage() throws Exception {
         // Test that memory usage is reduced after deduplication
         OutputAnalyzer output;
-        final String usagePattern = "Heap Memory Usage: (\\d+)";
+        final String heapMemoryUsagePattern = "Heap Memory Usage: (\\d+)";
+        final String arrayHeaderSizePattern = "Array Header Size: (\\d+)";
 
         // Run without deduplication
         output = MemoryUsageTest.run(false);
         output.shouldHaveExitValue(0);
-        final long memoryUsageWithoutDedup = Long.parseLong(output.firstMatch(usagePattern, 1));
+        final long heapMemoryUsageWithoutDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1));
+        final long arrayHeaderSizeWithoutDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1));
 
         // Run with deduplication
         output = MemoryUsageTest.run(true);
         output.shouldHaveExitValue(0);
-        final long memoryUsageWithDedup = Long.parseLong(output.firstMatch(usagePattern, 1));
+        final long heapMemoryUsageWithDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1));
+        final long arrayHeaderSizeWithDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1));
+
+        // Sanity check to make sure one instance isn't using compressed class pointers and the other not
+        if (arrayHeaderSizeWithoutDedup != arrayHeaderSizeWithDedup) {
+            throw new Exception("Unexpected difference between array header sizes");
+        }
 
         // Calculate expected memory usage with deduplication enabled. This calculation does
         // not take alignment and padding into account, so it's a conservative estimate.
-        final long sizeOfChar = 2; // bytes
-        final long bytesSaved = (LargeNumberOfStrings - 1) * (StringLength * sizeOfChar + unsafe.ARRAY_CHAR_BASE_OFFSET);
-        final long memoryUsageWithDedupExpected = memoryUsageWithoutDedup - bytesSaved;
+        final long sizeOfChar = unsafe.ARRAY_CHAR_INDEX_SCALE;
+        final long sizeOfCharArray = StringLength * sizeOfChar + arrayHeaderSizeWithoutDedup;
+        final long bytesSaved = (LargeNumberOfStrings - 1) * sizeOfCharArray;
+        final long heapMemoryUsageWithDedupExpected = heapMemoryUsageWithoutDedup - bytesSaved;
 
         System.out.println("Memory usage summary:");
-        System.out.println("   memoryUsageWithoutDedup:      " + memoryUsageWithoutDedup);
-        System.out.println("   memoryUsageWithDedup:         " + memoryUsageWithDedup);
-        System.out.println("   memoryUsageWithDedupExpected: " + memoryUsageWithDedupExpected);
+        System.out.println("   heapMemoryUsageWithoutDedup:      " + heapMemoryUsageWithoutDedup);
+        System.out.println("   heapMemoryUsageWithDedup:         " + heapMemoryUsageWithDedup);
+        System.out.println("   heapMemoryUsageWithDedupExpected: " + heapMemoryUsageWithDedupExpected);
 
-        if (memoryUsageWithDedup > memoryUsageWithDedupExpected) {
-            throw new Exception("Unexpected memory usage, memoryUsageWithDedup should less or equal to memoryUsageWithDedupExpected");
+        if (heapMemoryUsageWithDedup > heapMemoryUsageWithDedupExpected) {
+            throw new Exception("Unexpected memory usage, heapMemoryUsageWithDedup should be less or equal to heapMemoryUsageWithDedupExpected");
         }
     }
 }
--- a/hotspot/test/runtime/6626217/Test6626217.sh	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/test/runtime/6626217/Test6626217.sh	Wed Jul 05 19:37:28 2017 +0200
@@ -22,7 +22,6 @@
 # 
 
 
-# @ignore 8028733
 # @test @(#)Test6626217.sh
 # @bug 6626217
 # @summary Loader-constraint table allows arrays instead of only the base-classes
--- a/hotspot/test/runtime/6888954/vmerrors.sh	Thu Apr 17 15:22:07 2014 -0700
+++ b/hotspot/test/runtime/6888954/vmerrors.sh	Wed Jul 05 19:37:28 2017 +0200
@@ -85,7 +85,7 @@
     [ $i -lt 10 ] && i2=0$i
 
     "$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \
-        -XX:-TransmitErrorReport \
+        -XX:-TransmitErrorReport -XX:-CreateMinidumpOnCrash \
         -XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1
 
     # If ErrorHandlerTest is ignored (product build), stop.
--- a/jdk/.hgtags	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/.hgtags	Wed Jul 05 19:37:28 2017 +0200
@@ -251,3 +251,4 @@
 cac7b28b8b1e0e11d7a8e1ac1fe75a03b3749eab jdk9-b06
 f4e624447514f12dd7c51f1e5b0cb97efcd15be2 jdk9-b07
 9e7bd44ea85c72318130379c34b98716b9c7c248 jdk9-b08
+2cef452ba711b17950da275fd15931925799f07c jdk9-b09
--- a/jdk/make/CompileDemos.gmk	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/CompileDemos.gmk	Wed Jul 05 19:37:28 2017 +0200
@@ -176,7 +176,6 @@
 $(eval $(call SetupDemo,JTop,management,,JTop,,,README*))
 $(eval $(call SetupDemo,MemoryMonitor,management,,MemoryMonitor,,,README*))
 $(eval $(call SetupDemo,VerboseGC,management,,VerboseGC,,,README*))
-$(eval $(call SetupDemo,zipfs,nio,,,,,README* *.java,,,,Main-Class: \n))
 
 ifndef OPENJDK
   $(eval $(call SetupDemo,Laffy,jfc,,,,closed/,*))
--- a/jdk/make/CopyFiles.gmk	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/CopyFiles.gmk	Wed Jul 05 19:37:28 2017 +0200
@@ -158,15 +158,6 @@
 
 ##########################################################################################
 
-CONTENT_TYPES_SRC = $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib
-
-$(LIBDIR)/content-types.properties: $(CONTENT_TYPES_SRC)/content-types.properties
-	$(call install-file)
-
-COPY_FILES += $(LIBDIR)/content-types.properties
-
-##########################################################################################
-
 CALENDARS_SRC := $(JDK_TOPDIR)/src/share/lib
 
 $(LIBDIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties
@@ -183,9 +174,9 @@
 
 ##########################################################################################
 
-ifeq ($(OPENJDK_TARGET_OS), windows)
+ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),)
 
-  TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib
+  TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS)/lib
 
   $(LIBDIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings
 	$(call install-file)
--- a/jdk/make/CopyIntoClasses.gmk	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/CopyIntoClasses.gmk	Wed Jul 05 19:37:28 2017 +0200
@@ -26,7 +26,7 @@
 # Copy icu and _dict files used by the text break iterator
 
 COPY_PATTERNS := .icu _dict .dat _options .js aliasmap .spp .wav .css \
-    .png .gif .xml .dtd .txt oqlhelp.html
+    .png .gif .xml .dtd .txt oqlhelp.html content-types.properties
 
 # These directories should not be copied at all
 EXCLUDES += \
--- a/jdk/make/CreateJars.gmk	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/CreateJars.gmk	Wed Jul 05 19:37:28 2017 +0200
@@ -160,11 +160,13 @@
     javax/swing/JWindowBeanInfo.class \
     javax/swing/SwingBeanInfoBase.class \
     javax/swing/text/JTextComponentBeanInfo.class \
+    jdk/nio/zipfs \
     META-INF/services/com.sun.jdi.connect.Connector \
     META-INF/services/com.sun.jdi.connect.spi.TransportService \
     META-INF/services/com.sun.tools.attach.spi.AttachProvider \
     META-INF/services/com.sun.tools.xjc.Plugin \
     META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor \
+    META-INF/services/java.nio.file.spi.FileSystemProvider \
     org/relaxng/datatype \
     sun/awt/HKSCS.class \
     sun/awt/motif/X11GB2312.class \
@@ -356,6 +358,16 @@
 
 ##########################################################################################
 
+$(eval $(call SetupArchive,BUILD_ZIPFS_JAR, , \
+    SRCS := $(JDK_OUTPUTDIR)/classes, \
+    INCLUDES := jdk/nio/zipfs, \
+    EXTRA_FILES := META-INF/services/java.nio.file.spi.FileSystemProvider, \
+    JAR := $(IMAGES_OUTPUTDIR)/lib/ext/zipfs.jar, \
+    SKIP_METAINF := true, \
+    CHECK_COMPRESS_JAR := true))
+
+##########################################################################################
+
 ifndef OPENJDK
   ifeq ($(ENABLE_JFR), true)
     $(eval $(call SetupArchive,BUILD_JFR_JAR, , \
@@ -660,11 +672,6 @@
 
 ##########################################################################################
 
-$(IMAGES_OUTPUTDIR)/lib/ext/zipfs.jar: $(JDK_OUTPUTDIR)/demo/nio/zipfs/zipfs.jar
-	$(install-file)
-
-##########################################################################################
-
 # This file is imported from hotspot in Import.gmk. Copying it into images/lib so that
 # all jars can be found in one place when creating images in Images.gmk. It needs to be
 # done here so that clean targets can be simple and accurate.
--- a/jdk/make/data/jdwp/jdwp.spec	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/data/jdwp/jdwp.spec	Wed Jul 05 19:37:28 2017 +0200
@@ -1079,7 +1079,7 @@
     (Command InvokeMethod=3
         "Invokes a static method. "
         "The method must be member of the class type "
-        "or one of its superclasses, superinterfaces, or implemented interfaces. "
+        "or one of its superclasses. "
         "Access control is not enforced; for example, private "
         "methods can be invoked."
         "<p>"
--- a/jdk/make/mapfiles/libnet/mapfile-vers	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/mapfiles/libnet/mapfile-vers	Wed Jul 05 19:37:28 2017 +0200
@@ -94,6 +94,10 @@
 		Java_sun_net_sdp_SdpSupport_create0;
 		Java_sun_net_spi_DefaultProxySelector_init;
 		Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
+		Java_sun_net_ExtendedOptionsImpl_init;
+		Java_sun_net_ExtendedOptionsImpl_setFlowOption;
+		Java_sun_net_ExtendedOptionsImpl_getFlowOption;
+		Java_sun_net_ExtendedOptionsImpl_flowSupported;
 		NET_AllocSockaddr;
 		NET_SockaddrToInetAddress;
                 NET_SockaddrEqualsInetAddress;
--- a/jdk/make/profile-includes.txt	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/make/profile-includes.txt	Wed Jul 05 19:37:28 2017 +0200
@@ -56,7 +56,6 @@
     $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/Xusage.txt \
     calendars.properties \
     classlist \
-    content-types.properties \
     currency.data \
     ext/localedata.jar \
     ext/meta-index \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/aix/lib/tzmappings	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,586 @@
+#
+#
+# Copyright (c) 1994, 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.
+#
+
+#
+# Portions Copyright (c) 2014 IBM Corporation
+#
+
+# This table describes mappings between AIX time zone IDs and Java time zone
+# IDs. Fields are separated by a single TAB ('\t'). Lines must be in the ascending
+# order in ASCII. (non-ASCII characters can't be used.)
+#                            NOTE
+# This table format is not a public interface of any Java
+# platforms. No applications should depend on this file in any form.
+# This file has been generated using programs. Do not edit this file manually.
+#
+# Solaris		Java
+
+ACST-9:30ACDT	Australia/Adelaide
+AST4	America/Curacao
+AST4ADT	America/Halifax
+AST9	Pacific/Gambier
+AST9ADT	America/Anchorage
+AZOREST1	Atlantic/Cape_Verde
+AZOREST1AZOREDT	Atlantic/Azores
+Africa/Abidjan	Africa/Abidjan
+Africa/Accra	Africa/Accra
+Africa/Addis_Ababa	Africa/Addis_Ababa
+Africa/Algiers	Africa/Algiers
+Africa/Asmera	Africa/Asmera
+Africa/Bamako	GMT
+Africa/Bangui	Africa/Bangui
+Africa/Banjul	Africa/Banjul
+Africa/Bissau	Africa/Bissau
+Africa/Blantyre	Africa/Blantyre
+Africa/Brazzaville	Africa/Luanda
+Africa/Bujumbura	Africa/Bujumbura
+Africa/Cairo	Africa/Cairo
+Africa/Casablanca	Africa/Casablanca
+Africa/Ceuta	Europe/Paris
+Africa/Conakry	Africa/Conakry
+Africa/Dakar	Africa/Dakar
+Africa/Dar_es_Salaam	Africa/Dar_es_Salaam
+Africa/Djibouti	Africa/Djibouti
+Africa/Douala	Africa/Douala
+Africa/El_Aaiun	Africa/Casablanca
+Africa/Freetown	Africa/Freetown
+Africa/Gaborone	Africa/Gaborone
+Africa/Harare	Africa/Harare
+Africa/Johannesburg	Africa/Johannesburg
+Africa/Kampala	Africa/Kampala
+Africa/Khartoum	Africa/Khartoum
+Africa/Kigali	Africa/Kigali
+Africa/Kinshasa	Africa/Kinshasa
+Africa/Lagos	Africa/Lagos
+Africa/Libreville	Africa/Libreville
+Africa/Lome	Africa/Lome
+Africa/Luanda	Africa/Luanda
+Africa/Lubumbashi	Africa/Lubumbashi
+Africa/Lusaka	Africa/Lusaka
+Africa/Malabo	Africa/Malabo
+Africa/Maputo	Africa/Maputo
+Africa/Maseru	Africa/Maseru
+Africa/Mbabane	Africa/Mbabane
+Africa/Mogadishu	Africa/Mogadishu
+Africa/Monrovia	Africa/Monrovia
+Africa/Nairobi	Africa/Nairobi
+Africa/Ndjamena	Africa/Ndjamena
+Africa/Niamey	Africa/Niamey
+Africa/Nouakchott	Africa/Nouakchott
+Africa/Ouagadougou	Africa/Ouagadougou
+Africa/Porto-Novo	Africa/Porto-Novo
+Africa/Sao_Tome	Africa/Sao_Tome
+Africa/Timbuktu	Africa/Timbuktu
+Africa/Tripoli	Africa/Tripoli
+Africa/Tunis	Africa/Tunis
+Africa/Windhoek	Africa/Windhoek
+America/Adak	America/Adak
+America/Anchorage	America/Anchorage
+America/Anguilla	America/Anguilla
+America/Antigua	America/Antigua
+America/Araguaina	America/Sao_Paulo
+America/Argentina/Buenos_Aires	America/Argentina/Buenos_Aires
+America/Argentina/Catamarca	America/Argentina/Catamarca
+America/Argentina/ComodRivadavia	America/Argentina/Catamarca
+America/Argentina/Cordoba	America/Argentina/Cordoba
+America/Argentina/Jujuy	America/Argentina/Jujuy
+America/Argentina/La_Rioja	America/Argentina/La_Rioja
+America/Argentina/Mendoza	America/Argentina/Mendoza
+America/Argentina/Rio_Gallegos	America/Argentina/Rio_Gallegos
+America/Argentina/Salta	America/Argentina/Salta
+America/Argentina/San_Juan	America/Argentina/San_Juan
+America/Argentina/San_Luis	America/Argentina/San_Luis
+America/Argentina/Tucuman	America/Argentina/Tucuman
+America/Argentina/Ushuaia	America/Argentina/Ushuaia
+America/Aruba	America/Aruba
+America/Asuncion	America/Asuncion
+America/Atka	America/Adak
+America/Barbados	America/Barbados
+America/Belize	America/Belize
+America/Bogota	America/Bogota
+America/Boise	America/Denver
+America/Buenos_Aires	America/Argentina/Buenos_Aires
+America/Cancun	America/Chicago
+America/Caracas	America/Caracas
+America/Catamarca	America/Argentina/Catamarca
+America/Cayenne	America/Cayenne
+America/Cayman	America/Cayman
+America/Chicago	America/Chicago
+America/Chihuahua	America/Denver
+America/Coral_Harbour	America/Atikokan
+America/Cordoba	America/Argentina/Cordoba
+America/Costa_Rica	America/Costa_Rica
+America/Cuiaba	America/Cuiaba
+America/Curacao	America/Curacao
+America/Dawson	America/Los_Angeles
+America/Dawson_Creek	America/Dawson_Creek
+America/Denver	America/Denver
+America/Detroit	America/New_York
+America/Dominica	America/Dominica
+America/Edmonton	America/Edmonton
+America/El_Salvador	America/El_Salvador
+America/Ensenada	America/Los_Angeles
+America/Fort_Wayne	America/Indiana/Indianapolis
+America/Fortaleza	America/Fortaleza
+America/Glace_Bay	America/Halifax
+America/Godthab	America/Godthab
+America/Goose_Bay	America/Thule
+America/Grand_Turk	America/Grand_Turk
+America/Grenada	America/Grenada
+America/Guadeloupe	America/Guadeloupe
+America/Guatemala	America/Guatemala
+America/Guayaquil	America/Guayaquil
+America/Guyana	America/Guyana
+America/Halifax	America/Halifax
+America/Havana	America/Havana
+America/Indiana/Indianapolis	America/Indianapolis
+America/Indianapolis	America/Indiana/Indianapolis
+America/Inuvik	America/Denver
+America/Iqaluit	America/New_York
+America/Jamaica	America/Jamaica
+America/Jujuy	America/Argentina/Jujuy
+America/Juneau	America/Anchorage
+America/Knox_IN	America/Indiana/Knox
+America/La_Paz	America/La_Paz
+America/Lima	America/Lima
+America/Los_Angeles	America/Los_Angeles
+America/Louisville	America/Kentucky/Louisville
+America/Managua	America/Managua
+America/Manaus	America/Manaus
+America/Marigot	America/Guadeloupe
+America/Martinique	America/Martinique
+America/Mazatlan	America/Mazatlan
+America/Mendoza	America/Argentina/Mendoza
+America/Menominee	America/Winnipeg
+America/Mexico_City	America/Mexico_City
+America/Miquelon	America/Miquelon
+America/Moncton	America/Moncton
+America/Montevideo	America/Montevideo
+America/Montreal	America/Montreal
+America/Montserrat	America/Montserrat
+America/Nassau	America/Nassau
+America/New_York	America/New_York
+America/Nipigon	America/New_York
+America/Nome	America/Anchorage
+America/Noronha	America/Noronha
+America/Panama	America/Panama
+America/Pangnirtung	America/Thule
+America/Paramaribo	America/Paramaribo
+America/Phoenix	America/Phoenix
+America/Port-au-Prince	America/Port-au-Prince
+America/Port_of_Spain	America/Port_of_Spain
+America/Porto_Acre	America/Rio_Branco
+America/Puerto_Rico	America/Puerto_Rico
+America/Rainy_River	America/Chicago
+America/Rankin_Inlet	America/Chicago
+America/Regina	America/Regina
+America/Rio_Branco	America/Rio_Branco
+America/Rosario	America/Argentina/Cordoba
+America/Santiago	America/Santiago
+America/Santo_Domingo	America/Santo_Domingo
+America/Sao_Paulo	America/Sao_Paulo
+America/Scoresbysund	America/Scoresbysund
+America/Shiprock	America/Denver
+America/St_Barthelemy	America/Guadeloupe
+America/St_Johns	America/St_Johns
+America/St_Kitts	America/St_Kitts
+America/St_Lucia	America/St_Lucia
+America/St_Thomas	America/St_Thomas
+America/St_Vincent	America/St_Vincent
+America/Tegucigalpa	America/Tegucigalpa
+America/Thule	America/Thule
+America/Thunder_Bay	America/New_York
+America/Tijuana	America/Tijuana
+America/Toronto	America/Toronto
+America/Tortola	America/Tortola
+America/Vancouver	America/Vancouver
+America/Virgin	America/St_Thomas
+America/Whitehorse	America/Los_Angeles
+America/Winnipeg	America/Winnipeg
+America/Yakutat	America/Anchorage
+America/Yellowknife	America/Denver
+Antarctica/Casey	Antarctica/Casey
+Antarctica/DumontDUrville	Antarctica/DumontDUrville
+Antarctica/Mawson	Antarctica/Mawson
+Antarctica/McMurdo	Antarctica/McMurdo
+Antarctica/Palmer	Antarctica/Palmer
+Antarctica/South_Pole	Antarctica/McMurdo
+Arctic/Longyearbyen	Europe/Oslo
+Asia/Aden	Asia/Aden
+Asia/Almaty	Asia/Almaty
+Asia/Amman	Asia/Amman
+Asia/Anadyr	Asia/Anadyr
+Asia/Aqtau	Asia/Aqtau
+Asia/Aqtobe	Asia/Aqtobe
+Asia/Ashkhabad	Asia/Ashkhabad
+Asia/Baghdad	Asia/Baghdad
+Asia/Bahrain	Asia/Bahrain
+Asia/Baku	Asia/Baku
+Asia/Bangkok	Asia/Bangkok
+Asia/Beirut	Asia/Beirut
+Asia/Bishkek	Asia/Bishkek
+Asia/Brunei	Asia/Brunei
+Asia/Calcutta	Asia/Calcutta
+Asia/Chungking	Asia/Shanghai
+Asia/Colombo	Asia/Colombo
+Asia/Dacca	Asia/Dacca
+Asia/Damascus	Asia/Damascus
+Asia/Dhaka	Asia/Dhaka
+Asia/Dubai	Asia/Dubai
+Asia/Dushanbe	Asia/Dushanbe
+Asia/Gaza	Asia/Amman
+Asia/Harbin	Asia/Shanghai
+Asia/Hong_Kong	Asia/Hong_Kong
+Asia/Irkutsk	Asia/Irkutsk
+Asia/Istanbul	Europe/Istanbul
+Asia/Jakarta	Asia/Jakarta
+Asia/Jayapura	Asia/Jayapura
+Asia/Jerusalem	Asia/Jerusalem
+Asia/Kabul	Asia/Kabul
+Asia/Kamchatka	Asia/Kamchatka
+Asia/Karachi	Asia/Karachi
+Asia/Kashgar	Asia/Shanghai
+Asia/Katmandu	Asia/Katmandu
+Asia/Kolkata	Asia/Kolkata
+Asia/Krasnoyarsk	Asia/Krasnoyarsk
+Asia/Kuala_Lumpur	Asia/Kuala_Lumpur
+Asia/Kuwait	Asia/Kuwait
+Asia/Macao	Asia/Macao
+Asia/Magadan	Asia/Magadan
+Asia/Manila	Asia/Manila
+Asia/Muscat	Asia/Muscat
+Asia/Nicosia	Asia/Nicosia
+Asia/Novosibirsk	Asia/Novosibirsk
+Asia/Omsk	Asia/Novosibirsk
+Asia/Phnom_Penh	Asia/Phnom_Penh
+Asia/Pyongyang	Asia/Pyongyang
+Asia/Qatar	Asia/Qatar
+Asia/Rangoon	Asia/Rangoon
+Asia/Riyadh	Asia/Riyadh
+Asia/Saigon	Asia/Ho_Chi_Minh
+Asia/Seoul	Asia/Seoul
+Asia/Shanghai	Asia/Shanghai
+Asia/Singapore	Asia/Singapore
+Asia/Taipei	Asia/Taipei
+Asia/Tashkent	Asia/Tashkent
+Asia/Tbilisi	Asia/Tbilisi
+Asia/Tehran	Asia/Tehran
+Asia/Tel_Aviv	Asia/Jerusalem
+Asia/Thimbu	Asia/Thimbu
+Asia/Tokyo	Asia/Tokyo
+Asia/Ujung_Pandang	Asia/Ujung_Pandang
+Asia/Ulan_Bator	Asia/Ulaanbaatar
+Asia/Urumqi	Asia/Shanghai
+Asia/Vientiane	Asia/Vientiane
+Asia/Vladivostok	Asia/Vladivostok
+Asia/Yakutsk	Asia/Yakutsk
+Asia/Yekaterinburg	Asia/Yekaterinburg
+Asia/Yerevan	Asia/Yerevan
+Atlantic/Azores	Atlantic/Azores
+Atlantic/Bermuda	Atlantic/Bermuda
+Atlantic/Canary	Atlantic/Canary
+Atlantic/Cape_Verde	Atlantic/Cape_Verde
+Atlantic/Faeroe	Atlantic/Faeroe
+Atlantic/Jan_Mayen	Atlantic/Jan_Mayen
+Atlantic/Madeira	Europe/London
+Atlantic/Reykjavik	Atlantic/Reykjavik
+Atlantic/South_Georgia	Atlantic/South_Georgia
+Atlantic/St_Helena	Atlantic/St_Helena
+Atlantic/Stanley	Atlantic/Stanley
+Australia/ACT	Australia/Sydney
+Australia/Adelaide	Australia/Adelaide
+Australia/Brisbane	Australia/Brisbane
+Australia/Broken_Hill	Australia/Broken_Hill
+Australia/Canberra	Australia/Sydney
+Australia/Darwin	Australia/Darwin
+Australia/Hobart	Australia/Hobart
+Australia/LHI	Australia/Lord_Howe
+Australia/Lord_Howe	Australia/Lord_Howe
+Australia/Melbourne	Australia/Sydney
+Australia/NSW	Australia/Sydney
+Australia/North	Australia/Darwin
+Australia/Perth	Australia/Perth
+Australia/Queensland	Australia/Brisbane
+Australia/South	Australia/Adelaide
+Australia/Sydney	Australia/Sydney
+Australia/Tasmania	Australia/Hobart
+Australia/Victoria	Australia/Melbourne
+Australia/West	Australia/Perth
+Australia/Yancowinna	Australia/Broken_Hill
+BRT3BRST	America/Sao_Paulo
+BST11	Pacific/Apia
+BST11BDT	Pacific/Apia
+Brazil/Acre	America/Rio_Branco
+Brazil/DeNoronha	America/Noronha
+Brazil/East	America/Sao_Paulo
+Brazil/West	America/Manaus
+CET	Europe/Paris
+CET-1CEST	Europe/Paris
+CET-1CEST-2	Europe/Berlin
+CET-1CET-2	Europe/Paris
+CST6	America/Costa_Rica
+CST6CDT	America/Chicago
+CUT0	UTC
+CUT0GDT	Europe/London
+Canada/Atlantic	America/Halifax
+Canada/Central	America/Winnipeg
+Canada/East-Saskatchewan	America/Regina
+Canada/Eastern	America/Montreal
+Canada/Mountain	America/Edmonton
+Canada/Newfoundland	America/St_Johns
+Canada/Pacific	America/Vancouver
+Canada/Saskatchewan	America/Regina
+Canada/Yukon	America/Whitehorse
+Chile/Continental	America/Santiago
+Chile/EasterIsland	Pacific/Easter
+Cuba	America/Havana
+EET	Europe/Istanbul
+EET-10	Australia/Brisbane
+EET-10EETDT	Australia/Sydney
+EST	America/Indianapolis
+EST5	America/Indianapolis
+EST5EDT	America/New_York
+Egypt	Africa/Cairo
+Eire	Europe/Dublin
+Etc/GMT	GMT
+Etc/GMT0	GMT
+Etc/Greenwich	GMT
+Etc/UCT	UTC
+Etc/UTC	UTC
+Etc/Universal	UTC
+Etc/Zulu	UTC
+Europe/Amsterdam	Europe/Amsterdam
+Europe/Andorra	Europe/Andorra
+Europe/Athens	Europe/Athens
+Europe/Belfast	Europe/London
+Europe/Belgrade	Europe/Belgrade
+Europe/Berlin	Europe/Berlin
+Europe/Bratislava	Europe/Prague
+Europe/Brussels	Europe/Brussels
+Europe/Bucharest	Europe/Bucharest
+Europe/Budapest	Europe/Budapest
+Europe/Chisinau	Europe/Chisinau
+Europe/Copenhagen	Europe/Copenhagen
+Europe/Dublin	Europe/Dublin
+Europe/Gibraltar	Europe/Gibraltar
+Europe/Guernsey	Europe/London
+Europe/Helsinki	Europe/Helsinki
+Europe/Isle_of_Man	Europe/London
+Europe/Istanbul	Europe/Istanbul
+Europe/Jersey	Europe/London
+Europe/Kaliningrad	Europe/Kaliningrad
+Europe/Kiev	Europe/Kiev
+Europe/Lisbon	Europe/Lisbon
+Europe/Ljubljana	Europe/Belgrade
+Europe/London	Europe/London
+Europe/Luxembourg	Europe/Luxembourg
+Europe/Madrid	Europe/Madrid
+Europe/Malta	Europe/Malta
+Europe/Mariehamn	Europe/Helsinki
+Europe/Minsk	Europe/Minsk
+Europe/Monaco	Europe/Monaco
+Europe/Moscow	Europe/Moscow
+Europe/Nicosia	Asia/Nicosia
+Europe/Oslo	Europe/Oslo
+Europe/Paris	Europe/Paris
+Europe/Podgorica	Europe/Belgrade
+Europe/Prague	Europe/Prague
+Europe/Riga	Europe/Riga
+Europe/Rome	Europe/Rome
+Europe/Samara	Europe/Samara
+Europe/San_Marino	Europe/Rome
+Europe/Sarajevo	Europe/Belgrade
+Europe/Simferopol	Europe/Simferopol
+Europe/Skopje	Europe/Belgrade
+Europe/Sofia	Europe/Sofia
+Europe/Stockholm	Europe/Stockholm
+Europe/Tallinn	Europe/Tallinn
+Europe/Tirane	Europe/Tirane
+Europe/Vaduz	Europe/Vaduz
+Europe/Vatican	Europe/Rome
+Europe/Vienna	Europe/Vienna
+Europe/Vilnius	Europe/Vilnius
+Europe/Warsaw	Europe/Warsaw
+Europe/Zagreb	Europe/Belgrade
+Europe/Zurich	Europe/Zurich
+FALKST2	Atlantic/South_Georgia
+FALKST2FALKDT	Atlantic/South_Georgia
+Factory	GMT
+GB	Europe/London
+GB-Eire	Europe/London
+GMT	GMT
+GMT0	GMT
+GMT0BST	Europe/London
+GMT0BST-1	Europe/London
+GMT0WET	Europe/Lisbon
+GRNLNDST3	America/Buenos_Aires
+GRNLNDST3GRNLNDDT	America/Godthab
+Greenwich	GMT
+HST	Pacific/Honolulu
+HST10	Pacific/Honolulu
+HST10HDT	America/Adak
+Hongkong	Asia/Hong_Kong
+Iceland	Atlantic/Reykjavik
+Indian/Antananarivo	Indian/Antananarivo
+Indian/Chagos	Indian/Chagos
+Indian/Christmas	Indian/Christmas
+Indian/Cocos	Indian/Cocos
+Indian/Comoro	Indian/Comoro
+Indian/Kerguelen	Indian/Kerguelen
+Indian/Mahe	Indian/Mahe
+Indian/Maldives	Indian/Maldives
+Indian/Mauritius	Indian/Mauritius
+Indian/Mayotte	Indian/Mayotte
+Indian/Reunion	Indian/Reunion
+Iran	Asia/Tehran
+Israel	Asia/Jerusalem
+JST-9	Asia/Tokyo
+JST-9JSTDT	Asia/Tokyo
+Jamaica	America/Jamaica
+Japan	Asia/Tokyo
+KORST-9	Asia/Seoul
+KORST-9KORDT	Asia/Seoul
+Kwajalein	Pacific/Kwajalein
+Libya	Africa/Tripoli
+MEST-2	Europe/Istanbul
+MEST-2MEDT	Europe/Istanbul
+MEST-3	Asia/Riyadh
+MEST-3MEDT	Europe/Moscow
+MET	Europe/Paris
+MET-11	Pacific/Guadalcanal
+MET-11METDT	Asia/Magadan
+MET-1MEST	Europe/Paris
+MET-1MST-2	Europe/Berlin
+MEZ-1MESZ	Europe/Berlin
+MEZ-1MESZ-2	Europe/Berlin
+MSK-3MSD	Europe/Moscow
+MST	America/Phoenix
+MST7	America/Phoenix
+MST7MDT	America/Denver
+Mexico/BajaNorte	America/Tijuana
+Mexico/BajaSur	America/Mazatlan
+Mexico/General	America/Mexico_City
+Mideast/Riyadh87	Asia/Riyadh87
+Mideast/Riyadh88	Asia/Riyadh88
+Mideast/Riyadh89	Asia/Riyadh89
+NFT-1	Africa/Algiers
+NFT-1DFT	Europe/Paris
+NFT-1DST	Europe/Paris
+NZ	Pacific/Auckland
+NZ-CHAT	Pacific/Chatham
+NZST-12	Pacific/Fiji
+NZST-12NZDT	Pacific/Auckland
+Navajo	America/Denver
+PAKST-5	Asia/Karachi
+PAKST-5PAKDT	Asia/Yekaterinburg
+PRC	Asia/Shanghai
+PST8	Pacific/Pitcairn
+PST8PDT	America/Los_Angeles
+PST8PDT7	America/Tijuana
+Pacific/Apia	Pacific/Apia
+Pacific/Auckland	Pacific/Auckland
+Pacific/Chatham	Pacific/Chatham
+Pacific/Easter	Pacific/Easter
+Pacific/Efate	Pacific/Efate
+Pacific/Enderbury	Pacific/Enderbury
+Pacific/Fakaofo	Pacific/Fakaofo
+Pacific/Fiji	Pacific/Fiji
+Pacific/Funafuti	Pacific/Funafuti
+Pacific/Galapagos	Pacific/Galapagos
+Pacific/Gambier	Pacific/Gambier
+Pacific/Guadalcanal	Pacific/Guadalcanal
+Pacific/Guam	Pacific/Guam
+Pacific/Honolulu	Pacific/Honolulu
+Pacific/Kiritimati	Pacific/Kiritimati
+Pacific/Kosrae	Pacific/Kosrae
+Pacific/Majuro	Pacific/Majuro
+Pacific/Marquesas	Pacific/Marquesas
+Pacific/Nauru	Pacific/Nauru
+Pacific/Niue	Pacific/Niue
+Pacific/Norfolk	Pacific/Norfolk
+Pacific/Noumea	Pacific/Noumea
+Pacific/Pago_Pago	Pacific/Pago_Pago
+Pacific/Palau	Pacific/Palau
+Pacific/Pitcairn	Pacific/Pitcairn
+Pacific/Ponape	Pacific/Ponape
+Pacific/Port_Moresby	Pacific/Port_Moresby
+Pacific/Rarotonga	Pacific/Rarotonga
+Pacific/Saipan	Pacific/Saipan
+Pacific/Samoa	Pacific/Pago_Pago
+Pacific/Tahiti	Pacific/Tahiti
+Pacific/Tarawa	Pacific/Tarawa
+Pacific/Tongatapu	Pacific/Tongatapu
+Pacific/Truk	Pacific/Truk
+Pacific/Wake	Pacific/Wake
+Pacific/Wallis	Pacific/Wallis
+Poland	Europe/Warsaw
+Portugal	Europe/Lisbon
+ROC	Asia/Taipei
+ROK	Asia/Seoul
+SAUST-3	Asia/Riyadh
+SAUST-3SAUDT	Europe/Moscow
+Singapore	Asia/Singapore
+SystemV/AST4ADT	America/Thule
+SystemV/CST6CDT	America/Chicago
+SystemV/EST5EDT	America/New_York
+SystemV/MST7MDT	America/Denver
+SystemV/PST8PDT	America/Los_Angeles
+SystemV/YST9YDT	America/Anchorage
+TAIST-8	Asia/Taipei
+TAIST-8TAIDT	Asia/Irkutsk
+TASHST-6	Asia/Dacca
+TASHST-6TASHDT	Asia/Novosibirsk
+THAIST-7	Asia/Bangkok
+THAIST-7THAIDT	Asia/Krasnoyarsk
+Turkey	Europe/Istanbul
+UCT	UTC
+US/Alaska	America/Anchorage
+US/Aleutian	America/Adak
+US/Arizona	America/Phoenix
+US/Central	America/Chicago
+US/East-Indiana	America/Indiana/Indianapolis
+US/Eastern	America/New_York
+US/Hawaii	Pacific/Honolulu
+US/Indiana-Starke	America/Indiana/Knox
+US/Michigan	America/New_York
+US/Mountain	America/Denver
+US/Pacific	America/Los_Angeles
+US/Pacific-New	America/Los_Angeles
+US/Samoa	Pacific/Pago_Pago
+USAST-2	Africa/Johannesburg
+USAST-2USADT	Europe/Istanbul
+UTC	UTC
+UYT3UYST	America/Montevideo
+Universal	UTC
+W-SU	Europe/Moscow
+WAUST-8	Australia/Perth
+WAUST-8WAUDT	Australia/Perth
+WET	WET
+WET-2	Africa/Johannesburg
+WET-2WET	Europe/Helsinki
+WST-4	Asia/Dubai
+WST-4WDT	Europe/Samara
+Zulu	UTC
--- a/jdk/src/macosx/classes/sun/font/CFontManager.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/classes/sun/font/CFontManager.java	Wed Jul 05 19:37:28 2017 +0200
@@ -27,6 +27,8 @@
 
 import java.awt.*;
 import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -38,6 +40,7 @@
 
 import sun.awt.FontConfiguration;
 import sun.awt.HeadlessToolkit;
+import sun.misc.ThreadGroupUtils;
 import sun.lwawt.macosx.*;
 
 public class CFontManager extends SunFontManager {
@@ -215,24 +218,19 @@
                                 });
                     }
                 };
-                java.security.AccessController.doPrivileged(
-                        new java.security.PrivilegedAction<Object>() {
-                            public Object run() {
-                                /* The thread must be a member of a thread group
-                                 * which will not get GCed before VM exit.
-                                 * Make its parent the top-level thread group.
-                                 */
-                                ThreadGroup tg =
-                                    Thread.currentThread().getThreadGroup();
-                                for (ThreadGroup tgn = tg;
-                                tgn != null;
-                                tg = tgn, tgn = tg.getParent());
-                                fileCloser = new Thread(tg, fileCloserRunnable);
-                                fileCloser.setContextClassLoader(null);
-                                Runtime.getRuntime().addShutdownHook(fileCloser);
-                                return null;
-                            }
-                        });
+                AccessController.doPrivileged(
+                        (PrivilegedAction<Void>) () -> {
+                            /* The thread must be a member of a thread group
+                             * which will not get GCed before VM exit.
+                             * Make its parent the top-level thread group.
+                             */
+                            ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                            fileCloser = new Thread(rootTG, fileCloserRunnable);
+                            fileCloser.setContextClassLoader(null);
+                            Runtime.getRuntime().addShutdownHook(fileCloser);
+                            return null;
+                        }
+                );
                 }
             }
         }
--- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java	Wed Jul 05 19:37:28 2017 +0200
@@ -35,6 +35,7 @@
 
 import sun.awt.*;
 import sun.print.*;
+import sun.misc.ThreadGroupUtils;
 
 import static sun.lwawt.LWWindowPeer.PeerType;
 
@@ -70,30 +71,17 @@
     protected final void init() {
         AWTAutoShutdown.notifyToolkitThreadBusy();
 
-        ThreadGroup mainTG = AccessController.doPrivileged(
-            new PrivilegedAction<ThreadGroup>() {
-                public ThreadGroup run() {
-                    ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
-                    ThreadGroup parentTG = currentTG.getParent();
-                    while (parentTG != null) {
-                        currentTG = parentTG;
-                        parentTG = currentTG.getParent();
-                    }
-                    return currentTG;
-                }
-            }
-        );
+        ThreadGroup rootTG = AccessController.doPrivileged(
+                (PrivilegedAction<ThreadGroup>) ThreadGroupUtils::getRootThreadGroup);
 
         Runtime.getRuntime().addShutdownHook(
-            new Thread(mainTG, new Runnable() {
-                public void run() {
-                    shutdown();
-                    waitForRunState(STATE_CLEANUP);
-                }
+            new Thread(rootTG, () -> {
+                shutdown();
+                waitForRunState(STATE_CLEANUP);
             })
         );
 
-        Thread toolkitThread = new Thread(mainTG, this, "AWT-LW");
+        Thread toolkitThread = new Thread(rootTG, this, "AWT-LW");
         toolkitThread.setDaemon(true);
         toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
         toolkitThread.start();
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CClipboard.java	Wed Jul 05 19:37:28 2017 +0200
@@ -58,7 +58,7 @@
 
     @Override
     protected void setContentsNative(Transferable contents) {
-
+        FlavorTable flavorMap = getDefaultFlavorTable();
         // Don't use delayed Clipboard rendering for the Transferable's data.
         // If we did that, we would call Transferable.getTransferData on
         // the Toolkit thread, which is a security hole.
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Jul 05 19:37:28 2017 +0200
@@ -478,8 +478,12 @@
     private static final String APPKIT_THREAD_NAME = "AppKit Thread";
 
     // Intended to be called from the LWCToolkit.m only.
-    private static void installToolkitThreadNameInJava() {
+    private static void installToolkitThreadInJava() {
         Thread.currentThread().setName(APPKIT_THREAD_NAME);
+        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            Thread.currentThread().setContextClassLoader(null);
+            return null;
+        });
     }
 
     @Override
--- a/jdk/src/macosx/lib/content-types.properties	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-#sun.net.www MIME content-types table
-#
-# Property fields:
-#
-#   <description> ::= 'description' '=' <descriptive string>
-#    <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
-#         <image> ::= 'icon' '=' <filename of icon image>
-#        <action> ::= 'browser' | 'application' | 'save' | 'unknown'
-#   <application> ::= 'application' '=' <command line template>
-#
-
-#
-# The "we don't know anything about this data" type(s).
-# Used internally to mark unrecognized types.
-#
-content/unknown: description=Unknown Content
-unknown/unknown: description=Unknown Data Type
-
-#
-# The template we should use for temporary files when launching an application
-# to view a document of given type.
-#
-temp.file.template: /tmp/%s
-
-#
-# The "real" types.
-#
-application/octet-stream: \
-	description=Generic Binary Stream;\
-	file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz
-
-application/oda: \
-	description=ODA Document;\
-	file_extensions=.oda
-
-application/pdf: \
-	description=Adobe PDF Format;\
-	file_extensions=.pdf
-
-application/postscript: \
-	description=Postscript File;\
-	file_extensions=.eps,.ai,.ps;\
-	icon=ps;\
-	action=application;\
-	application=imagetool %s
-
-application/x-dvi: \
-	description=TeX DVI File;\
-	file_extensions=.dvi;\
-	action=application;\
-	application=xdvi %s
-
-application/x-hdf: \
-	description=Hierarchical Data Format;\
-	file_extensions=.hdf;\
-	action=save
-
-application/x-latex: \
-	description=LaTeX Source;\
-	file_extensions=.latex
-
-application/x-netcdf: \
-	description=Unidata netCDF Data Format;\
-	file_extensions=.nc,.cdf;\
-	action=save
-
-application/x-tex: \
-	description=TeX Source;\
-	file_extensions=.tex
-
-application/x-texinfo: \
-	description=Gnu Texinfo;\
-	file_extensions=.texinfo,.texi
-
-application/x-troff: \
-	description=Troff Source;\
-	file_extensions=.t,.tr,.roff;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
-
-application/x-troff-man: \
-	description=Troff Manpage Source;\
-	file_extensions=.man;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
-
-application/x-troff-me: \
-	description=Troff ME Macros;\
-	file_extensions=.me;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
-
-application/x-troff-ms: \
-	description=Troff MS Macros;\
-	file_extensions=.ms;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
-
-application/x-wais-source: \
-	description=Wais Source;\
-	file_extensions=.src,.wsrc
-
-application/zip: \
-	description=Zip File;\
-	file_extensions=.zip;\
-	icon=zip;\
-	action=save
-
-application/x-bcpio: \
-	description=Old Binary CPIO Archive;\
-	file_extensions=.bcpio; action=save
-
-application/x-cpio: \
-	description=Unix CPIO Archive;\
-	file_extensions=.cpio; action=save
-
-application/x-gtar: \
-	description=Gnu Tar Archive;\
-	file_extensions=.gtar;\
-	icon=tar;\
-	action=save
-
-application/x-shar: \
-	description=Shell Archive;\
-	file_extensions=.sh,.shar;\
-	action=save
-
-application/x-sv4cpio: \
-	description=SVR4 CPIO Archive;\
-	file_extensions=.sv4cpio; action=save
-
-application/x-sv4crc: \
-	description=SVR4 CPIO with CRC;\
-	file_extensions=.sv4crc; action=save
-
-application/x-tar: \
-	description=Tar Archive;\
-	file_extensions=.tar;\
-	icon=tar;\
-	action=save
-
-application/x-ustar: \
-	description=US Tar Archive;\
-	file_extensions=.ustar;\
-	action=save
-
-audio/basic: \
-	description=Basic Audio;\
-	file_extensions=.snd,.au;\
-	icon=audio;\
-	action=application;\
-	application=audiotool %s
-
-audio/x-aiff: \
-	description=Audio Interchange Format File;\
-	file_extensions=.aifc,.aif,.aiff;\
-	icon=aiff
-
-audio/x-wav: \
-	description=Wav Audio;\
-	file_extensions=.wav;\
-	icon=wav
-
-image/gif: \
-	description=GIF Image;\
-	file_extensions=.gif;\
-	icon=gif;\
-	action=browser
-
-image/ief: \
-	description=Image Exchange Format;\
-	file_extensions=.ief
-
-image/jpeg: \
-	description=JPEG Image;\
-	file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
-	icon=jpeg;\
-	action=browser;\
-	application=imagetool %s
-
-image/tiff: \
-	description=TIFF Image;\
-	file_extensions=.tif,.tiff;\
-	icon=tiff
-
-image/vnd.fpx: \
-	description=FlashPix Image;\
-	file_extensions=.fpx,.fpix
-
-image/x-cmu-rast: \
-	description=CMU Raster Image;\
-	file_extensions=.ras
-
-image/x-portable-anymap: \
-	description=PBM Anymap Format;\
-	file_extensions=.pnm
-
-image/x-portable-bitmap: \
-	description=PBM Bitmap Format;\
-	file_extensions=.pbm
-
-image/x-portable-graymap: \
-	description=PBM Graymap Format;\
-	file_extensions=.pgm
-
-image/x-portable-pixmap: \
-	description=PBM Pixmap Format;\
-	file_extensions=.ppm
-
-image/x-rgb: \
-	description=RGB Image;\
-	file_extensions=.rgb
-
-image/x-xbitmap: \
-	description=X Bitmap Image;\
-	file_extensions=.xbm,.xpm
-
-image/x-xwindowdump: \
-	description=X Window Dump Image;\
-	file_extensions=.xwd
-
-image/png: \
-	description=PNG Image;\
-	file_extensions=.png;\
-	icon=png;\
-	action=browser
-
-text/html: \
-	description=HTML Document;\
-	file_extensions=.htm,.html;\
-	icon=html
-
-text/plain: \
-	description=Plain Text;\
-	file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
-	icon=text;\
-	action=browser
-
-text/tab-separated-values: \
-	description=Tab Separated Values Text;\
-	file_extensions=.tsv
-
-text/x-setext: \
-	description=Structure Enhanced Text;\
-	file_extensions=.etx
-
-video/mpeg: \
-	description=MPEG Video Clip;\
-	file_extensions=.mpg,.mpe,.mpeg;\
-	icon=mpeg;\
-	action=application;\
-	application=mpeg_play %s
-
-video/quicktime: \
-	description=QuickTime Video Clip;\
-	file_extensions=.mov,.qt
-
-application/x-troff-msvideo: \
-	description=AVI Video;\
-	file_extensions=.avi;\
-	icon=avi
-
-video/x-sgi-movie: \
-	description=SGI Movie;\
-	file_extensions=.movie,.mv
-
-message/rfc822: \
-	description=Internet Email Message;\
-	file_extensions=.mime
-
-application/xml: \
-	description=XML document;\
-	file_extensions=.xml
-
-
-
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m	Wed Jul 05 19:37:28 2017 +0200
@@ -221,15 +221,16 @@
 Java_sun_lwawt_macosx_LWCToolkit_initIDs
 (JNIEnv *env, jclass klass) {
     // set thread names
-    dispatch_async(dispatch_get_main_queue(), ^(void){
-        [[NSThread currentThread] setName:@"AppKit Thread"];
-
-        JNIEnv *env = [ThreadUtilities getJNIEnv];
-        static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
-        static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadNameInJava, jc_LWCToolkit, "installToolkitThreadNameInJava", "()V");
-        JNFCallStaticVoidMethod(env, jsm_installToolkitThreadNameInJava);
-    });
-
+    if (![ThreadUtilities isAWTEmbedded]) {
+        dispatch_async(dispatch_get_main_queue(), ^(void){
+            [[NSThread currentThread] setName:@"AppKit Thread"];
+            JNIEnv *env = [ThreadUtilities getJNIEnv];
+            static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
+            static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V");
+            JNFCallStaticVoidMethod(env, jsm_installToolkitThreadInJava);
+        });
+    }
+    
     gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS;
 
     jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent");
--- a/jdk/src/macosx/native/sun/awt/awt.m	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/native/sun/awt/awt.m	Wed Jul 05 19:37:28 2017 +0200
@@ -363,6 +363,7 @@
     //  AppKit Application.
     NSApplication *app = [NSApplicationAWT sharedApplication];
     isEmbedded = ![NSApp isKindOfClass:[NSApplicationAWT class]];
+    [ThreadUtilities setAWTEmbedded:isEmbedded];
 
     if (!isEmbedded) {
         // Install run loop observers and set the AppKit Java thread name
@@ -433,6 +434,14 @@
     if (isSWTInWebStart(env)) {
         forceEmbeddedMode = YES;
     }
+    JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
+    jclass jc_ThreadGroupUtils = (*env)->FindClass(env, "sun/misc/ThreadGroupUtils");
+    jmethodID sjm_getRootThreadGroup = (*env)->GetStaticMethodID(env, jc_ThreadGroupUtils, "getRootThreadGroup", "()Ljava/lang/ThreadGroup;");
+    jobject rootThreadGroup = (*env)->CallStaticObjectMethod(env, jc_ThreadGroupUtils, sjm_getRootThreadGroup);
+    [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, rootThreadGroup)];
+    // The current thread was attached in getJNIEnvUnchached.
+    // Detach it back. It will be reattached later if needed with a proper TG
+    [ThreadUtilities detachCurrentThread];
 
     BOOL headless = isHeadless(env);
 
--- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h	Wed Jul 05 19:37:28 2017 +0200
@@ -127,6 +127,10 @@
 
 + (JNIEnv*)getJNIEnv;
 + (JNIEnv*)getJNIEnvUncached;
++ (void)detachCurrentThread;
++ (void)setAppkitThreadGroup:(jobject)group;
++ (void)setAWTEmbedded:(BOOL)embedded;
++ (BOOL)isAWTEmbedded;
 
 //Wrappers for the corresponding JNFRunLoop methods with a check for main thread
 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block;
--- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m	Wed Jul 05 19:37:28 2017 +0200
@@ -33,23 +33,45 @@
 // The following must be named "jvm", as there are extern references to it in AWT
 JavaVM *jvm = NULL;
 static JNIEnv *appKitEnv = NULL;
+static jobject appkitThreadGroup = NULL;
+static BOOL awtEmbedded = NO;
+
+inline void attachCurrentThread(void** env) {
+    if ([NSThread isMainThread]) {
+        JavaVMAttachArgs args;
+        args.version = JNI_VERSION_1_4;
+        args.name = "AppKit Thread";
+        args.group = appkitThreadGroup;
+        (*jvm)->AttachCurrentThreadAsDaemon(jvm, env, &args);
+    } else {
+        (*jvm)->AttachCurrentThreadAsDaemon(jvm, env, NULL);
+    }
+}
 
 @implementation ThreadUtilities
 
 + (JNIEnv*)getJNIEnv {
 AWT_ASSERT_APPKIT_THREAD;
     if (appKitEnv == NULL) {
-        (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&appKitEnv, NULL);
+        attachCurrentThread((void **)&appKitEnv);
     }
     return appKitEnv;
 }
 
 + (JNIEnv*)getJNIEnvUncached {
     JNIEnv *env = NULL;
-    (*jvm)->AttachCurrentThreadAsDaemon(jvm, (void **)&env, nil);
+    attachCurrentThread((void **)&env);
     return env;
 }
 
++ (void)detachCurrentThread {
+    (*jvm)->DetachCurrentThread(jvm);
+}
+
++ (void)setAppkitThreadGroup:(jobject)group {
+    appkitThreadGroup = group;
+}
+
 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block {
     if ([NSThread isMainThread] && wait == YES) {
         block(); 
@@ -66,6 +88,14 @@
     }
 }
 
++ (void)setAWTEmbedded:(BOOL)embedded {
+    awtEmbedded = embedded;
+}
+
++ (BOOL)isAWTEmbedded {
+    return awtEmbedded;
+}
+
 @end
 
 
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1220,7 +1220,7 @@
             throw new RuntimeOperationsException(new
                 IllegalArgumentException(listener.getCanonicalName()),
                 "The MBean " + listener.getCanonicalName() +
-                "does not implement the NotificationListener interface") ;
+                " does not implement the NotificationListener interface") ;
         }
 
         // ----------------
--- a/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java	Wed Jul 05 19:37:28 2017 +0200
@@ -35,6 +35,8 @@
 import javax.management.remote.SubjectDelegationPermission;
 
 import com.sun.jmx.remote.util.CacheMap;
+import java.util.ArrayList;
+import java.util.Collection;
 
 public class SubjectDelegator {
     private static final int PRINCIPALS_CACHE_SIZE = 10;
@@ -53,11 +55,14 @@
                          boolean removeCallerContext)
             throws SecurityException {
 
+        if (System.getSecurityManager() != null && authenticatedACC == null) {
+            throw new SecurityException("Illegal AccessControlContext: null");
+        }
         if (principalsCache == null || accCache == null) {
             principalsCache =
-                    new CacheMap<Subject, Principal[]>(PRINCIPALS_CACHE_SIZE);
+                    new CacheMap<>(PRINCIPALS_CACHE_SIZE);
             accCache =
-                    new CacheMap<Subject, AccessControlContext>(ACC_CACHE_SIZE);
+                    new CacheMap<>(ACC_CACHE_SIZE);
         }
 
         // Retrieve the principals for the given
@@ -101,14 +106,15 @@
         // principal in the delegated subject
         //
         final Principal[] dp = delegatedPrincipals;
+        final Collection<Permission> permissions = new ArrayList<>(dp.length);
+        for(Principal p : dp) {
+            final String pname = p.getClass().getName() + "." + p.getName();
+            permissions.add(new SubjectDelegationPermission(pname));
+        }
         PrivilegedAction<Void> action =
             new PrivilegedAction<Void>() {
                 public Void run() {
-                    for (int i = 0 ; i < dp.length ; i++) {
-                        final String pname =
-                            dp[i].getClass().getName() + "." + dp[i].getName();
-                        Permission sdp =
-                            new SubjectDelegationPermission(pname);
+                    for (Permission sdp : permissions) {
                         AccessController.checkPermission(sdp);
                     }
                     return null;
--- a/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsClient.java	Wed Jul 05 19:37:28 2017 +0200
@@ -30,13 +30,14 @@
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.security.SecureRandom;
 import javax.naming.*;
 
 import java.util.Collections;
 import java.util.Map;
 import java.util.HashMap;
-import java.util.Set;
-import java.util.HashSet;
+
+import sun.security.jca.JCAUtil;
 
 // Some of this code began life as part of sun.javaos.net.DnsClient
 // originally by sritchie@eng 1/96.  It was first hacked up for JNDI
@@ -77,6 +78,8 @@
     };
 
     private static final int DEFAULT_PORT = 53;
+    private static final int TRANSACTION_ID_BOUND = 0x10000;
+    private static final SecureRandom random = JCAUtil.getSecureRandom();
     private InetAddress[] servers;
     private int[] serverPorts;
     private int timeout;                // initial timeout on UDP queries in ms
@@ -85,7 +88,7 @@
     private DatagramSocket udpSocket;
 
     // Requests sent
-    private Set<Integer> reqs;
+    private Map<Integer, ResourceRecord> reqs;
 
     // Responses received
     private Map<Integer, byte[]> resps;
@@ -134,7 +137,8 @@
                 throw ne;
             }
         }
-        reqs = Collections.synchronizedSet(new HashSet<Integer>());
+        reqs = Collections.synchronizedMap(
+            new HashMap<Integer, ResourceRecord>());
         resps = Collections.synchronizedMap(new HashMap<Integer, byte[]>());
     }
 
@@ -153,10 +157,6 @@
         }
     }
 
-
-    private int ident = 0;              // used to set the msg ID field
-    private Object identLock = new Object();
-
     /*
      * If recursion is true, recursion is requested on the query.
      * If auth is true, only authoritative responses are accepted; other
@@ -167,15 +167,19 @@
             throws NamingException {
 
         int xid;
-        synchronized (identLock) {
-            ident = 0xFFFF & (ident + 1);
-            xid = ident;
-        }
+        Packet pkt;
+        ResourceRecord collision;
 
-        // enqueue the outstanding request
-        reqs.add(xid);
+        do {
+            // Generate a random transaction ID
+            xid = random.nextInt(TRANSACTION_ID_BOUND);
+            pkt = makeQueryPacket(fqdn, xid, qclass, qtype, recursion);
 
-        Packet pkt = makeQueryPacket(fqdn, xid, qclass, qtype, recursion);
+            // enqueue the outstanding request
+            collision = reqs.putIfAbsent(xid, new ResourceRecord(pkt.getData(),
+                pkt.length(), Header.HEADER_SIZE, true, false));
+
+        } while (collision != null);
 
         Exception caughtException = null;
         boolean[] doNotRetry = new boolean[servers.length];
@@ -305,11 +309,8 @@
     ResourceRecords queryZone(DnsName zone, int qclass, boolean recursion)
             throws NamingException {
 
-        int xid;
-        synchronized (identLock) {
-            ident = 0xFFFF & (ident + 1);
-            xid = ident;
-        }
+        int xid = random.nextInt(TRANSACTION_ID_BOUND);
+
         Packet pkt = makeQueryPacket(zone, xid, qclass,
                                      ResourceRecord.QTYPE_AXFR, recursion);
         Exception caughtException = null;
@@ -390,6 +391,7 @@
             DatagramPacket opkt = new DatagramPacket(
                     pkt.getData(), pkt.length(), server, port);
             DatagramPacket ipkt = new DatagramPacket(new byte[8000], 8000);
+            // Packets may only be sent to or received from this server address
             udpSocket.connect(server, port);
             int pktTimeout = (timeout * (1 << retry));
             try {
@@ -542,6 +544,9 @@
      * Checks the header of an incoming DNS response.
      * Returns true if it matches the given xid and throws a naming
      * exception, if appropriate, based on the response code.
+     *
+     * Also checks that the domain name, type and class in the response
+     * match those in the original query.
      */
     private boolean isMatchResponse(byte[] pkt, int xid)
                 throws NamingException {
@@ -551,7 +556,7 @@
             throw new CommunicationException("DNS error: expecting response");
         }
 
-        if (!reqs.contains(xid)) { // already received, ignore the response
+        if (!reqs.containsKey(xid)) { // already received, ignore the response
             return false;
         }
 
@@ -560,14 +565,47 @@
             if (debug) {
                 dprint("XID MATCH:" + xid);
             }
+            checkResponseCode(hdr);
+            if (!hdr.query && hdr.numQuestions == 1) {
 
-            checkResponseCode(hdr);
-            // remove the response for the xid if received by some other thread.
-            synchronized (queuesLock) {
-                resps.remove(xid);
-                reqs.remove(xid);
+                ResourceRecord rr = new ResourceRecord(pkt, pkt.length,
+                    Header.HEADER_SIZE, true, false);
+
+                // Retrieve the original query
+                ResourceRecord query = reqs.get(xid);
+                int qtype = query.getType();
+                int qclass = query.getRrclass();
+                DnsName qname = query.getName();
+
+                // Check that the type/class/name in the query section of the
+                // response match those in the original query
+                if ((qtype == ResourceRecord.QTYPE_STAR ||
+                    qtype == rr.getType()) &&
+                    (qclass == ResourceRecord.QCLASS_STAR ||
+                    qclass == rr.getRrclass()) &&
+                    qname.equals(rr.getName())) {
+
+                    if (debug) {
+                        dprint("MATCH NAME:" + qname + " QTYPE:" + qtype +
+                            " QCLASS:" + qclass);
+                    }
+
+                    // Remove the response for the xid if received by some other
+                    // thread.
+                    synchronized (queuesLock) {
+                        resps.remove(xid);
+                        reqs.remove(xid);
+                    }
+                    return true;
+
+                } else {
+                    if (debug) {
+                        dprint("NO-MATCH NAME:" + qname + " QTYPE:" + qtype +
+                            " QCLASS:" + qclass);
+                    }
+                }
             }
-            return true;
+            return false;
         }
 
         //
@@ -576,7 +614,7 @@
         // enqueue only the first response, responses for retries are ignored.
         //
         synchronized (queuesLock) {
-            if (reqs.contains(hdr.xid)) { // enqueue only the first response
+            if (reqs.containsKey(hdr.xid)) { // enqueue only the first response
                 resps.put(hdr.xid, pkt);
             }
         }
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapAttribute.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapAttribute.java	Wed Jul 05 19:37:28 2017 +0200
@@ -188,7 +188,7 @@
 
         if(syntaxAttr == null || syntaxAttr.size() == 0) {
             throw new NameNotFoundException(
-                getID() + "does not have a syntax associated with it");
+                getID() + " does not have a syntax associated with it");
         }
 
         String syntaxName = (String)syntaxAttr.get();
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapBindingEnumeration.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,6 +25,10 @@
 
 package com.sun.jndi.ldap;
 
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Vector;
 import javax.naming.*;
 import javax.naming.directory.*;
@@ -36,6 +40,8 @@
 final class LdapBindingEnumeration
         extends AbstractLdapNamingEnumeration<Binding> {
 
+    private final AccessControlContext acc = AccessController.getContext();
+
     LdapBindingEnumeration(LdapCtx homeCtx, LdapResult answer, Name remain,
         Continuation cont) throws NamingException
     {
@@ -52,7 +58,16 @@
 
         if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) {
             // serialized object or object reference
-            obj = Obj.decodeObject(attrs);
+            try {
+                obj = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                    @Override
+                    public Object run() throws NamingException {
+                        return Obj.decodeObject(attrs);
+                    }
+                }, acc);
+            } catch (PrivilegedActionException e) {
+                throw (NamingException)e.getException();
+            }
         }
         if (obj == null) {
             // DirContext object
--- a/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/jndi/ldap/LdapSearchEnumeration.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,6 +25,10 @@
 
 package com.sun.jndi.ldap;
 
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Vector;
 import javax.naming.*;
 import javax.naming.directory.*;
@@ -40,6 +44,8 @@
     private Name startName;             // prefix of names of search results
     private LdapCtx.SearchArgs searchArgs = null;
 
+    private final AccessControlContext acc = AccessController.getContext();
+
     LdapSearchEnumeration(LdapCtx homeCtx, LdapResult search_results,
         String starter, LdapCtx.SearchArgs args, Continuation cont)
         throws NamingException {
@@ -112,8 +118,16 @@
             if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) {
                 // Entry contains Java-object attributes (ser/ref object)
                 // serialized object or object reference
-                obj = Obj.decodeObject(attrs);
-
+                try {
+                    obj = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                        @Override
+                        public Object run() throws NamingException {
+                            return Obj.decodeObject(attrs);
+                        }
+                    }, acc);
+                } catch (PrivilegedActionException e) {
+                    throw (NamingException)e.getException();
+                }
             }
             if (obj == null) {
                 obj = new LdapCtx(homeCtx, dn);
--- a/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,27 +25,33 @@
 
 package com.sun.media.sound;
 
+import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
 import javax.sound.midi.Receiver;
 import javax.sound.midi.Sequencer;
 import javax.sound.midi.Synthesizer;
 import javax.sound.midi.Transmitter;
+import javax.sound.midi.spi.MidiDeviceProvider;
+import javax.sound.midi.spi.MidiFileReader;
+import javax.sound.midi.spi.MidiFileWriter;
+import javax.sound.midi.spi.SoundbankReader;
 import javax.sound.sampled.Clip;
 import javax.sound.sampled.Port;
 import javax.sound.sampled.SourceDataLine;
 import javax.sound.sampled.TargetDataLine;
+import javax.sound.sampled.spi.AudioFileReader;
+import javax.sound.sampled.spi.AudioFileWriter;
+import javax.sound.sampled.spi.FormatConversionProvider;
+import javax.sound.sampled.spi.MixerProvider;
 
 
 /**
- * JDK13Services uses the Service class in JDK 1.3
- * to discover a list of service providers installed
- * in the system.
- *
+ * JDK13Services uses the Service class in JDK 1.3 to discover a list of service
+ * providers installed in the system.
+ * <p>
  * This class is public because it is called from javax.sound.midi.MidiSystem
  * and javax.sound.sampled.AudioSystem. The alternative would be to make
  * JSSecurityManager public, which is considered worse.
@@ -54,80 +60,55 @@
  */
 public final class JDK13Services {
 
-    /** The default for the length of the period to hold the cache.
-        This value is given in milliseconds. It is equivalent to
-        1 minute.
-    */
-    private static final long DEFAULT_CACHING_PERIOD = 60000;
-
-    /** Filename of the properties file for default provider properties.
-        This file is searched in the subdirectory "lib" of the JRE directory
-        (this behaviour is hardcoded).
-    */
+    /**
+     * Filename of the properties file for default provider properties. This
+     * file is searched in the subdirectory "lib" of the JRE directory (this
+     * behaviour is hardcoded).
+     */
     private static final String PROPERTIES_FILENAME = "sound.properties";
 
-    /** Cache for the providers.
-        Class objects of the provider type (MixerProvider, MidiDeviceProvider
-        ...) are used as keys. The values are instances of ProviderCache.
-    */
-    private static final Map providersCacheMap = new HashMap();
-
-
-    /** The length of the period to hold the cache.
-        This value is given in milliseconds.
-    */
-    private static long cachingPeriod = DEFAULT_CACHING_PERIOD;
-
-    /** Properties loaded from the properties file for default provider
-        properties.
-    */
+    /**
+     * Properties loaded from the properties file for default provider
+     * properties.
+     */
     private static Properties properties;
 
-
-    /** Private, no-args constructor to ensure against instantiation.
+    /**
+     * Private, no-args constructor to ensure against instantiation.
      */
     private JDK13Services() {
     }
 
-
-    /** Set the period provider lists are cached.
-        This method is only intended for testing.
+    /**
+     * Obtains a List containing installed instances of the providers for the
+     * requested service. The returned List is immutable.
+     *
+     * @param serviceClass The type of providers requested. This should be one
+     *                     of AudioFileReader.class, AudioFileWriter.class,
+     *                     FormatConversionProvider.class, MixerProvider.class,
+     *                     MidiDeviceProvider.class, MidiFileReader.class,
+     *                     MidiFileWriter.class or SoundbankReader.class.
+     *
+     * @return A List of providers of the requested type. This List is
+     *         immutable.
      */
-    public static void setCachingPeriod(int seconds) {
-        cachingPeriod = seconds * 1000L;
+    public static List<?> getProviders(final Class<?> serviceClass) {
+        final List<?> providers;
+        if (!MixerProvider.class.equals(serviceClass)
+                && !FormatConversionProvider.class.equals(serviceClass)
+                && !AudioFileReader.class.equals(serviceClass)
+                && !AudioFileWriter.class.equals(serviceClass)
+                && !MidiDeviceProvider.class.equals(serviceClass)
+                && !SoundbankReader.class.equals(serviceClass)
+                && !MidiFileWriter.class.equals(serviceClass)
+                && !MidiFileReader.class.equals(serviceClass)) {
+            providers = new ArrayList<>(0);
+        } else {
+            providers = JSSecurityManager.getProviders(serviceClass);
+        }
+        return Collections.unmodifiableList(providers);
     }
 
-
-    /** Obtains a List containing installed instances of the
-        providers for the requested service.
-        The List of providers is cached for the period of time given by
-        {@link #cachingPeriod cachingPeriod}. During this period, the same
-        List instance is returned for the same type of provider. After this
-        period, a new instance is constructed and returned. The returned
-        List is immutable.
-        @param serviceClass The type of providers requested. This should be one
-        of AudioFileReader.class, AudioFileWriter.class,
-        FormatConversionProvider.class, MixerProvider.class,
-        MidiDeviceProvider.class, MidiFileReader.class, MidiFileWriter.class or
-        SoundbankReader.class.
-        @return A List of providers of the requested type. This List is
-        immutable.
-     */
-    public static synchronized List getProviders(Class serviceClass) {
-        ProviderCache cache = (ProviderCache) providersCacheMap.get(serviceClass);
-        if (cache == null) {
-            cache = new ProviderCache();
-            providersCacheMap.put(serviceClass, cache);
-        }
-        if (cache.providers == null ||
-            System.currentTimeMillis() > cache.lastUpdate + cachingPeriod) {
-            cache.providers = Collections.unmodifiableList(JSSecurityManager.getProviders(serviceClass));
-            cache.lastUpdate = System.currentTimeMillis();
-        }
-        return cache.providers;
-    }
-
-
     /** Obtain the provider class name part of a default provider property.
         @param typeClass The type of the default provider property. This
         should be one of Receiver.class, Transmitter.class, Sequencer.class,
@@ -219,14 +200,4 @@
         }
         return properties;
     }
-
-    // INNER CLASSES
-
-    private static class ProviderCache {
-        // System time of the last update in milliseconds.
-        public long lastUpdate;
-
-        // The providers.
-        public List providers;
-    }
 }
--- a/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java	Wed Jul 05 19:37:28 2017 +0200
@@ -185,8 +185,8 @@
         return thread;
     }
 
-    static <T> List<T> getProviders(final Class<T> providerClass) {
-        List<T> p = new ArrayList<>();
+    static synchronized <T> List<T> getProviders(final Class<T> providerClass) {
+        List<T> p = new ArrayList<>(7);
         // ServiceLoader creates "lazy" iterator instance, but it ensures that
         // next/hasNext run with permissions that are restricted by whatever
         // creates the ServiceLoader instance, so it requires to be called from
--- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java	Wed Jul 05 19:37:28 2017 +0200
@@ -922,7 +922,7 @@
         Element foundElement = null;
 
         String id = value.trim();
-        if (id.charAt(0) == '#') {
+        if (!id.isEmpty() && id.charAt(0) == '#') {
             id = id.substring(1);
         }
 
@@ -982,7 +982,7 @@
         Node processedNode = null;
 
         String id = value.trim();
-        if (id.charAt(0) == '#') {
+        if (!id.isEmpty() && id.charAt(0) == '#') {
             id = id.substring(1);
         }
 
--- a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -37,6 +37,7 @@
 import javax.sql.rowset.serial.*;
 import com.sun.rowset.internal.*;
 import com.sun.rowset.providers.*;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * The standard implementation of the <code>CachedRowSet</code> interface.
@@ -2959,13 +2960,9 @@
                 // create new instance of the class
                 SQLData obj = null;
                 try {
-                    obj = (SQLData)c.newInstance();
-                } catch (java.lang.InstantiationException ex) {
-                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
-                    ex.getMessage()));
-                } catch (java.lang.IllegalAccessException ex) {
-                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
-                    ex.getMessage()));
+                    obj = (SQLData) ReflectUtil.newInstance(c);
+                } catch(Exception ex) {
+                    throw new SQLException("Unable to Instantiate: ", ex);
                 }
                 // get the attributes from the struct
                 Object attribs[] = s.getAttributes(map);
@@ -5710,13 +5707,9 @@
                 // create new instance of the class
                 SQLData obj = null;
                 try {
-                    obj = (SQLData)c.newInstance();
-                } catch (java.lang.InstantiationException ex) {
-                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
-                    ex.getMessage()));
-                } catch (java.lang.IllegalAccessException ex) {
-                    throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
-                    ex.getMessage()));
+                    obj = (SQLData) ReflectUtil.newInstance(c);
+                } catch(Exception ex) {
+                    throw new SQLException("Unable to Instantiate: ", ex);
                 }
                 // get the attributes from the struct
                 Object attribs[] = s.getAttributes(map);
--- a/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -29,6 +29,7 @@
 import javax.sql.*;
 import java.util.*;
 import java.io.*;
+import sun.reflect.misc.ReflectUtil;
 
 import com.sun.rowset.*;
 import java.text.MessageFormat;
@@ -572,13 +573,9 @@
                         // create new instance of the class
                         SQLData obj = null;
                         try {
-                            obj = (SQLData)c.newInstance();
-                        } catch (java.lang.InstantiationException ex) {
-                            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
-                            ex.getMessage()));
-                        } catch (java.lang.IllegalAccessException ex) {
-                            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
-                            ex.getMessage()));
+                            obj = (SQLData)ReflectUtil.newInstance(c);
+                        } catch (Exception ex) {
+                            throw new SQLException("Unable to Instantiate: ", ex);
                         }
                         // get the attributes from the struct
                         Object attribs[] = s.getAttributes(map);
--- a/jdk/src/share/classes/java/awt/EventQueue.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/awt/EventQueue.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -1061,11 +1061,11 @@
                             t.setContextClassLoader(classLoader);
                             t.setPriority(Thread.NORM_PRIORITY + 1);
                             t.setDaemon(false);
+                            AWTAutoShutdown.getInstance().notifyThreadBusy(t);
                             return t;
                         }
                     }
                 );
-                AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
                 dispatchThread.start();
             }
         } finally {
--- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Wed Jul 05 19:37:28 2017 +0200
@@ -46,6 +46,7 @@
 import java.util.Set;
 import java.util.WeakHashMap;
 
+import sun.awt.AppContext;
 import sun.awt.datatransfer.DataTransferer;
 
 /**
@@ -65,10 +66,7 @@
      */
     private static String JavaMIME = "JAVA_DATAFLAVOR:";
 
-    /**
-     * System singleton which maps a thread's ClassLoader to a SystemFlavorMap.
-     */
-    private static final WeakHashMap<ClassLoader, FlavorMap> flavorMaps = new WeakHashMap<>();
+    private static final Object FLAVOR_MAP_KEY = new Object();
 
     /**
      * Copied from java.util.Properties.
@@ -183,22 +181,12 @@
      * @return the default FlavorMap for this thread's ClassLoader
      */
     public static FlavorMap getDefaultFlavorMap() {
-        ClassLoader contextClassLoader =
-            Thread.currentThread().getContextClassLoader();
-        if (contextClassLoader == null) {
-            contextClassLoader = ClassLoader.getSystemClassLoader();
+        AppContext context = AppContext.getAppContext();
+        FlavorMap fm = (FlavorMap) context.get(FLAVOR_MAP_KEY);
+        if (fm == null) {
+            fm = new SystemFlavorMap();
+            context.put(FLAVOR_MAP_KEY, fm);
         }
-
-        FlavorMap fm;
-
-        synchronized(flavorMaps) {
-            fm = flavorMaps.get(contextClassLoader);
-            if (fm == null) {
-                fm = new SystemFlavorMap();
-                flavorMaps.put(contextClassLoader, fm);
-            }
-        }
-
         return fm;
     }
 
@@ -239,26 +227,11 @@
                     }
                 });
 
-        BufferedReader flavormapURL =
+        String url =
             java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<BufferedReader>() {
-                    public BufferedReader run() {
-                        String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
-
-                        if (url == null) {
-                            return null;
-                        }
-
-                        try {
-                            return new BufferedReader
-                                (new InputStreamReader
-                                    (new URL(url).openStream(), "ISO-8859-1"));
-                        } catch (MalformedURLException e) {
-                            System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
-                        } catch (IOException e) {
-                            System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
-                        }
-                        return null;
+                new java.security.PrivilegedAction<String>() {
+                    public String run() {
+                        return Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
                     }
                 });
 
@@ -270,6 +243,19 @@
             }
         }
 
+        BufferedReader flavormapURL = null;
+        if (url != null) {
+            try {
+                flavormapURL = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "ISO-8859-1"));
+            } catch (MalformedURLException e) {
+                System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
+            } catch (IOException e) {
+                System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
+            } catch (SecurityException e) {
+                // ignored
+            }
+        }
+
         if (flavormapURL != null) {
             try {
                 parseAndStoreReader(flavormapURL);
--- a/jdk/src/share/classes/java/io/ObjectOutputStream.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/io/ObjectOutputStream.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1254,7 +1254,7 @@
         }
 
         bout.setBlockDataMode(true);
-        if (isCustomSubclass()) {
+        if (cl != null && isCustomSubclass()) {
             ReflectUtil.checkPackageAccess(cl);
         }
         annotateProxyClass(cl);
@@ -1283,7 +1283,7 @@
 
         Class<?> cl = desc.forClass();
         bout.setBlockDataMode(true);
-        if (isCustomSubclass()) {
+        if (cl != null && isCustomSubclass()) {
             ReflectUtil.checkPackageAccess(cl);
         }
         annotateClass(cl);
--- a/jdk/src/share/classes/java/lang/Thread.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java	Wed Jul 05 19:37:28 2017 +0200
@@ -366,6 +366,8 @@
             throw new NullPointerException("name cannot be null");
         }
 
+        this.name = name.toCharArray();
+
         Thread parent = currentThread();
         SecurityManager security = System.getSecurityManager();
         if (g == null) {
@@ -402,7 +404,6 @@
         this.group = g;
         this.daemon = parent.isDaemon();
         this.priority = parent.getPriority();
-        this.name = name.toCharArray();
         if (security == null || isCCLOverridden(parent.getClass()))
             this.contextClassLoader = parent.getContextClassLoader();
         else
--- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java	Wed Jul 05 19:37:28 2017 +0200
@@ -140,7 +140,7 @@
      * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
      * static field containing this value, and they must accordingly implement this method.
      */
-    protected abstract SpeciesData speciesData();
+    /*non-public*/ abstract SpeciesData speciesData();
 
     @Override
     final Object internalProperties() {
@@ -156,7 +156,7 @@
         return Arrays.asList(boundValues);
     }
 
-    public final Object arg(int i) {
+    /*non-public*/ final Object arg(int i) {
         try {
             switch (speciesData().fieldType(i)) {
             case 'L': return argL(i);
@@ -170,22 +170,22 @@
         }
         throw new InternalError("unexpected type: " + speciesData().types+"."+i);
     }
-    public final Object argL(int i) throws Throwable { return          speciesData().getters[i].invokeBasic(this); }
-    public final int    argI(int i) throws Throwable { return (int)    speciesData().getters[i].invokeBasic(this); }
-    public final float  argF(int i) throws Throwable { return (float)  speciesData().getters[i].invokeBasic(this); }
-    public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
-    public final long   argJ(int i) throws Throwable { return (long)   speciesData().getters[i].invokeBasic(this); }
+    /*non-public*/ final Object argL(int i) throws Throwable { return          speciesData().getters[i].invokeBasic(this); }
+    /*non-public*/ final int    argI(int i) throws Throwable { return (int)    speciesData().getters[i].invokeBasic(this); }
+    /*non-public*/ final float  argF(int i) throws Throwable { return (float)  speciesData().getters[i].invokeBasic(this); }
+    /*non-public*/ final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
+    /*non-public*/ final long   argJ(int i) throws Throwable { return (long)   speciesData().getters[i].invokeBasic(this); }
 
     //
     // cloning API
     //
 
-    public abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
-    public abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
-    public abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int    narg) throws Throwable;
-    public abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long   narg) throws Throwable;
-    public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float  narg) throws Throwable;
-    public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
+    /*non-public*/ abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
+    /*non-public*/ abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
+    /*non-public*/ abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int    narg) throws Throwable;
+    /*non-public*/ abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long   narg) throws Throwable;
+    /*non-public*/ abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float  narg) throws Throwable;
+    /*non-public*/ abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
 
     // The following is a grossly irregular hack:
     @Override MethodHandle reinvokerTarget() {
@@ -203,39 +203,39 @@
     private  // make it private to force users to access the enclosing class first
     static final class Species_L extends BoundMethodHandle {
         final Object argL0;
-        public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
+        /*non-public*/ Species_L(MethodType mt, LambdaForm lf, Object argL0) {
             super(mt, lf);
             this.argL0 = argL0;
         }
         // The following is a grossly irregular hack:
         @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
         @Override
-        public SpeciesData speciesData() {
+        /*non-public*/ SpeciesData speciesData() {
             return SPECIES_DATA;
         }
-        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
+        /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
         @Override
-        public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
+        /*non-public*/ final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
             return new Species_L(mt, lf, argL0);
         }
         @Override
-        public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
+        /*non-public*/ final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
         }
         @Override
-        public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
+        /*non-public*/ final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
         }
         @Override
-        public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
+        /*non-public*/ final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
         }
         @Override
-        public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
+        /*non-public*/ final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
         }
         @Override
-        public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
+        /*non-public*/ final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
         }
     }
@@ -338,10 +338,10 @@
         final MethodHandle[]                     getters;
         final SpeciesData[]                      extensions;
 
-        public int fieldCount() {
+        /*non-public*/ int fieldCount() {
             return types.length();
         }
-        public char fieldType(int i) {
+        /*non-public*/ char fieldType(int i) {
             return types.charAt(i);
         }
 
@@ -551,30 +551,30 @@
          *     final Object argL0;
          *     final Object argL1;
          *     final int argI2;
-         *     public Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
+         *     Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
          *         super(mt, lf);
          *         this.argL0 = argL0;
          *         this.argL1 = argL1;
          *         this.argI2 = argI2;
          *     }
-         *     public final SpeciesData speciesData() { return SPECIES_DATA; }
-         *     public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
-         *     public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
+         *     final SpeciesData speciesData() { return SPECIES_DATA; }
+         *     static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
+         *     final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
          *         return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
          *     }
-         *     public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
+         *     final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
          *         return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
-         *     public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
+         *     final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
          *         return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
-         *     public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
+         *     final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
          *         return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
-         *     public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
+         *     final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
          *         return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
-         *     public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
+         *     final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
          *         return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
          *     }
          * }
@@ -588,11 +588,12 @@
 
             final String className  = SPECIES_PREFIX_PATH + types;
             final String sourceFile = SPECIES_PREFIX_NAME + types;
-            cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
+            final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
+            cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
             cw.visitSource(sourceFile, null);
 
             // emit static types and SPECIES_DATA fields
-            cw.visitField(ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
+            cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
 
             // emit bound argument fields
             for (int i = 0; i < types.length(); ++i) {
@@ -605,7 +606,7 @@
             MethodVisitor mv;
 
             // emit constructor
-            mv = cw.visitMethod(ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
+            mv = cw.visitMethod(NOT_ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
             mv.visitCode();
             mv.visitVarInsn(ALOAD, 0);
             mv.visitVarInsn(ALOAD, 1);
@@ -629,7 +630,7 @@
             mv.visitEnd();
 
             // emit implementation of reinvokerTarget()
-            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
+            mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
             mv.visitCode();
             mv.visitVarInsn(ALOAD, 0);
             mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG);
@@ -639,7 +640,7 @@
             mv.visitEnd();
 
             // emit implementation of speciesData()
-            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
+            mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
             mv.visitCode();
             mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
             mv.visitInsn(ARETURN);
@@ -647,7 +648,7 @@
             mv.visitEnd();
 
             // emit clone()
-            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
+            mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
             mv.visitCode();
             // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...)
             // obtain constructor
@@ -670,7 +671,7 @@
             // for each type, emit cloneExtendT()
             for (Class<?> c : TYPES) {
                 char t = Wrapper.basicTypeChar(c);
-                mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
+                mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
                 mv.visitCode();
                 // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
                 // obtain constructor
@@ -697,7 +698,7 @@
             }
 
             // emit class initializer
-            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
+            mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
             mv.visitCode();
             mv.visitLdcInsn(types);
             mv.visitLdcInsn(Type.getObjectType(className));
--- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed Jul 05 19:37:28 2017 +0200
@@ -272,8 +272,9 @@
      * Set up class file generation.
      */
     private void classFilePrologue() {
+        final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
         cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
-        cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null);
+        cw.visit(Opcodes.V1_8, NOT_ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null);
         cw.visitSource(sourceFile, null);
 
         String invokerDesc = invokerType.toMethodDescriptorString();
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java	Wed Jul 05 19:37:28 2017 +0200
@@ -2070,6 +2070,7 @@
      */
     public static
     MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
+        reorder = reorder.clone();
         checkReorder(reorder, newType, target.type());
         return target.permuteArguments(newType, reorder);
     }
@@ -2264,6 +2265,7 @@
             throw newIllegalArgumentException("no argument type to remove");
         ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList());
         ptypes.addAll(pos, valueTypes);
+        if (ptypes.size() != inargs)  throw newIllegalArgumentException("valueTypes");
         MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
         return target.dropArguments(newType, pos, dropped);
     }
--- a/jdk/src/share/classes/java/math/BigDecimal.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/math/BigDecimal.java	Wed Jul 05 19:37:28 2017 +0200
@@ -29,8 +29,8 @@
 
 package java.math;
 
+import static java.math.BigInteger.LONG_MASK;
 import java.util.Arrays;
-import static java.math.BigInteger.LONG_MASK;
 
 /**
  * Immutable, arbitrary-precision signed decimal numbers.  A
@@ -283,7 +283,7 @@
     };
 
     // Cache of common small BigDecimal values.
-    private static final BigDecimal zeroThroughTen[] = {
+    private static final BigDecimal ZERO_THROUGH_TEN[] = {
         new BigDecimal(BigInteger.ZERO,       0,  0, 1),
         new BigDecimal(BigInteger.ONE,        1,  0, 1),
         new BigDecimal(BigInteger.valueOf(2), 2,  0, 1),
@@ -299,7 +299,7 @@
 
     // Cache of zero scaled by 0 - 15
     private static final BigDecimal[] ZERO_SCALED_BY = {
-        zeroThroughTen[0],
+        ZERO_THROUGH_TEN[0],
         new BigDecimal(BigInteger.ZERO, 0, 1, 1),
         new BigDecimal(BigInteger.ZERO, 0, 2, 1),
         new BigDecimal(BigInteger.ZERO, 0, 3, 1),
@@ -328,7 +328,7 @@
      * @since  1.5
      */
     public static final BigDecimal ZERO =
-        zeroThroughTen[0];
+        ZERO_THROUGH_TEN[0];
 
     /**
      * The value 1, with a scale of 0.
@@ -336,7 +336,7 @@
      * @since  1.5
      */
     public static final BigDecimal ONE =
-        zeroThroughTen[1];
+        ZERO_THROUGH_TEN[1];
 
     /**
      * The value 10, with a scale of 0.
@@ -344,7 +344,7 @@
      * @since  1.5
      */
     public static final BigDecimal TEN =
-        zeroThroughTen[10];
+        ZERO_THROUGH_TEN[10];
 
     // Constructors
 
@@ -920,20 +920,20 @@
             significand >>= 1;
             exponent++;
         }
-        int scale = 0;
+        int scl = 0;
         // Calculate intVal and scale
-        BigInteger intVal;
+        BigInteger rb;
         long compactVal = sign * significand;
         if (exponent == 0) {
-            intVal = (compactVal == INFLATED) ? INFLATED_BIGINT : null;
+            rb = (compactVal == INFLATED) ? INFLATED_BIGINT : null;
         } else {
             if (exponent < 0) {
-                intVal = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal);
-                scale = -exponent;
+                rb = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal);
+                scl = -exponent;
             } else { //  (exponent > 0)
-                intVal = BigInteger.valueOf(2).pow(exponent).multiply(compactVal);
+                rb = BigInteger.valueOf(2).pow(exponent).multiply(compactVal);
             }
-            compactVal = compactValFor(intVal);
+            compactVal = compactValFor(rb);
         }
         int prec = 0;
         int mcp = mc.precision;
@@ -941,16 +941,16 @@
             int mode = mc.roundingMode.oldMode;
             int drop;
             if (compactVal == INFLATED) {
-                prec = bigDigitLength(intVal);
+                prec = bigDigitLength(rb);
                 drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
-                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
-                    compactVal = compactValFor(intVal);
+                    scl = checkScaleNonZero((long) scl - drop);
+                    rb = divideAndRoundByTenPow(rb, drop, mode);
+                    compactVal = compactValFor(rb);
                     if (compactVal != INFLATED) {
                         break;
                     }
-                    prec = bigDigitLength(intVal);
+                    prec = bigDigitLength(rb);
                     drop = prec - mcp;
                 }
             }
@@ -958,17 +958,17 @@
                 prec = longDigitLength(compactVal);
                 drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
+                    scl = checkScaleNonZero((long) scl - drop);
                     compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
                     prec = longDigitLength(compactVal);
                     drop = prec - mcp;
                 }
-                intVal = null;
+                rb = null;
             }
         }
-        this.intVal = intVal;
+        this.intVal = rb;
         this.intCompact = compactVal;
-        this.scale = scale;
+        this.scale = scl;
         this.precision = prec;
     }
 
@@ -1098,13 +1098,13 @@
     public BigDecimal(int val, MathContext mc) {
         int mcp = mc.precision;
         long compactVal = val;
-        int scale = 0;
+        int scl = 0;
         int prec = 0;
         if (mcp > 0) { // do rounding
             prec = longDigitLength(compactVal);
             int drop = prec - mcp; // drop can't be more than 18
             while (drop > 0) {
-                scale = checkScaleNonZero((long) scale - drop);
+                scl = checkScaleNonZero((long) scl - drop);
                 compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
                 prec = longDigitLength(compactVal);
                 drop = prec - mcp;
@@ -1112,7 +1112,7 @@
         }
         this.intVal = null;
         this.intCompact = compactVal;
-        this.scale = scale;
+        this.scale = scl;
         this.precision = prec;
     }
 
@@ -1144,20 +1144,20 @@
         int mcp = mc.precision;
         int mode = mc.roundingMode.oldMode;
         int prec = 0;
-        int scale = 0;
-        BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
+        int scl = 0;
+        BigInteger rb = (val == INFLATED) ? INFLATED_BIGINT : null;
         if (mcp > 0) { // do rounding
             if (val == INFLATED) {
                 prec = 19;
                 int drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
-                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
-                    val = compactValFor(intVal);
+                    scl = checkScaleNonZero((long) scl - drop);
+                    rb = divideAndRoundByTenPow(rb, drop, mode);
+                    val = compactValFor(rb);
                     if (val != INFLATED) {
                         break;
                     }
-                    prec = bigDigitLength(intVal);
+                    prec = bigDigitLength(rb);
                     drop = prec - mcp;
                 }
             }
@@ -1165,17 +1165,17 @@
                 prec = longDigitLength(val);
                 int drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
+                    scl = checkScaleNonZero((long) scl - drop);
                     val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
                     prec = longDigitLength(val);
                     drop = prec - mcp;
                 }
-                intVal = null;
+                rb = null;
             }
         }
-        this.intVal = intVal;
+        this.intVal = rb;
         this.intCompact = val;
-        this.scale = scale;
+        this.scale = scl;
         this.precision = prec;
     }
 
@@ -1215,16 +1215,16 @@
      * @return a {@code BigDecimal} whose value is {@code val}.
      */
     public static BigDecimal valueOf(long val) {
-        if (val >= 0 && val < zeroThroughTen.length)
-            return zeroThroughTen[(int)val];
+        if (val >= 0 && val < ZERO_THROUGH_TEN.length)
+            return ZERO_THROUGH_TEN[(int)val];
         else if (val != INFLATED)
             return new BigDecimal(null, val, 0, 0);
         return new BigDecimal(INFLATED_BIGINT, val, 0, 0);
     }
 
     static BigDecimal valueOf(long unscaledVal, int scale, int prec) {
-        if (scale == 0 && unscaledVal >= 0 && unscaledVal < zeroThroughTen.length) {
-            return zeroThroughTen[(int) unscaledVal];
+        if (scale == 0 && unscaledVal >= 0 && unscaledVal < ZERO_THROUGH_TEN.length) {
+            return ZERO_THROUGH_TEN[(int) unscaledVal];
         } else if (unscaledVal == 0) {
             return zeroValueOf(scale);
         }
@@ -1236,8 +1236,8 @@
         long val = compactValFor(intVal);
         if (val == 0) {
             return zeroValueOf(scale);
-        } else if (scale == 0 && val >= 0 && val < zeroThroughTen.length) {
-            return zeroThroughTen[(int) val];
+        } else if (scale == 0 && val >= 0 && val < ZERO_THROUGH_TEN.length) {
+            return ZERO_THROUGH_TEN[(int) val];
         }
         return new BigDecimal(intVal, val, scale, prec);
     }
@@ -2620,6 +2620,7 @@
      * @return -1, 0, or 1 as this {@code BigDecimal} is numerically
      *          less than, equal to, or greater than {@code val}.
      */
+    @Override
     public int compareTo(BigDecimal val) {
         // Quick path for equal scale and non-inflated case.
         if (scale == val.scale) {
@@ -2659,14 +2660,13 @@
                 return -1;
             if (xae > yae)
                 return 1;
-            BigInteger rb = null;
             if (sdiff < 0) {
                 // The cases sdiff <= Integer.MIN_VALUE intentionally fall through.
                 if ( sdiff > Integer.MIN_VALUE &&
                       (xs == INFLATED ||
                       (xs = longMultiplyPowerTen(xs, (int)-sdiff)) == INFLATED) &&
                      ys == INFLATED) {
-                    rb = bigMultiplyPowerTen((int)-sdiff);
+                    BigInteger rb = bigMultiplyPowerTen((int)-sdiff);
                     return rb.compareMagnitude(val.intVal);
                 }
             } else { // sdiff > 0
@@ -2675,7 +2675,7 @@
                       (ys == INFLATED ||
                       (ys = longMultiplyPowerTen(ys, (int)sdiff)) == INFLATED) &&
                      xs == INFLATED) {
-                    rb = val.bigMultiplyPowerTen((int)sdiff);
+                    BigInteger rb = val.bigMultiplyPowerTen((int)sdiff);
                     return this.intVal.compareMagnitude(rb);
                 }
             }
@@ -2880,8 +2880,9 @@
     @Override
     public String toString() {
         String sc = stringCache;
-        if (sc == null)
+        if (sc == null) {
             stringCache = sc = layoutChars(true);
+        }
         return sc;
     }
 
@@ -2958,18 +2959,19 @@
             if(signum()==0) {
                 return "0";
             }
-            int tailingZeros = checkScaleNonZero((-(long)scale));
+            int trailingZeros = checkScaleNonZero((-(long)scale));
             StringBuilder buf;
             if(intCompact!=INFLATED) {
-                buf = new StringBuilder(20+tailingZeros);
+                buf = new StringBuilder(20+trailingZeros);
                 buf.append(intCompact);
             } else {
                 String str = intVal.toString();
-                buf = new StringBuilder(str.length()+tailingZeros);
+                buf = new StringBuilder(str.length()+trailingZeros);
                 buf.append(str);
             }
-            for (int i = 0; i < tailingZeros; i++)
+            for (int i = 0; i < trailingZeros; i++) {
                 buf.append('0');
+            }
             return buf.toString();
         }
         String str ;
@@ -2996,8 +2998,9 @@
         } else { /* We must insert zeros between point and intVal */
             buf = new StringBuilder(3-insertionPoint + intString.length());
             buf.append(signum<0 ? "-0." : "0.");
-            for (int i=0; i<-insertionPoint; i++)
+            for (int i=0; i<-insertionPoint; i++) {
                 buf.append('0');
+            }
             buf.append(intString);
         }
         return buf.toString();
@@ -3056,6 +3059,7 @@
      *
      * @return this {@code BigDecimal} converted to a {@code long}.
      */
+    @Override
     public long longValue(){
         return (intCompact != INFLATED && scale == 0) ?
             intCompact:
@@ -3124,6 +3128,7 @@
      *
      * @return this {@code BigDecimal} converted to an {@code int}.
      */
+    @Override
     public int intValue() {
         return  (intCompact != INFLATED && scale == 0) ?
             (int)intCompact :
@@ -3206,6 +3211,7 @@
      *
      * @return this {@code BigDecimal} converted to a {@code float}.
      */
+    @Override
     public float floatValue(){
         if(intCompact != INFLATED) {
             if (scale == 0) {
@@ -3221,10 +3227,10 @@
                     // Don't have too guard against
                     // Math.abs(MIN_VALUE) because of outer check
                     // against INFLATED.
-                    if (scale > 0 && scale < float10pow.length) {
-                        return (float)intCompact / float10pow[scale];
-                    } else if (scale < 0 && scale > -float10pow.length) {
-                        return (float)intCompact * float10pow[-scale];
+                    if (scale > 0 && scale < FLOAT_10_POW.length) {
+                        return (float)intCompact / FLOAT_10_POW[scale];
+                    } else if (scale < 0 && scale > -FLOAT_10_POW.length) {
+                        return (float)intCompact * FLOAT_10_POW[-scale];
                     }
                 }
             }
@@ -3249,6 +3255,7 @@
      *
      * @return this {@code BigDecimal} converted to a {@code double}.
      */
+    @Override
     public double doubleValue(){
         if(intCompact != INFLATED) {
             if (scale == 0) {
@@ -3264,10 +3271,10 @@
                     // Don't have too guard against
                     // Math.abs(MIN_VALUE) because of outer check
                     // against INFLATED.
-                    if (scale > 0 && scale < double10pow.length) {
-                        return (double)intCompact / double10pow[scale];
-                    } else if (scale < 0 && scale > -double10pow.length) {
-                        return (double)intCompact * double10pow[-scale];
+                    if (scale > 0 && scale < DOUBLE_10_POW.length) {
+                        return (double)intCompact / DOUBLE_10_POW[scale];
+                    } else if (scale < 0 && scale > -DOUBLE_10_POW.length) {
+                        return (double)intCompact * DOUBLE_10_POW[-scale];
                     }
                 }
             }
@@ -3280,7 +3287,7 @@
      * Powers of 10 which can be represented exactly in {@code
      * double}.
      */
-    private static final double double10pow[] = {
+    private static final double DOUBLE_10_POW[] = {
         1.0e0,  1.0e1,  1.0e2,  1.0e3,  1.0e4,  1.0e5,
         1.0e6,  1.0e7,  1.0e8,  1.0e9,  1.0e10, 1.0e11,
         1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17,
@@ -3291,7 +3298,7 @@
      * Powers of 10 which can be represented exactly in {@code
      * float}.
      */
-    private static final float float10pow[] = {
+    private static final float FLOAT_10_POW[] = {
         1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
         1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
     };
@@ -3504,8 +3511,9 @@
                 } else if (sig >= coeffLen) {   // significand all in integer
                     buf.append(coeff, offset, coeffLen);
                     // may need some zeros, too
-                    for (int i = sig - coeffLen; i > 0; i--)
+                    for (int i = sig - coeffLen; i > 0; i--) {
                         buf.append('0');
+                    }
                 } else {                     // xx.xxE form
                     buf.append(coeff, offset, sig);
                     buf.append('.');
@@ -3559,11 +3567,13 @@
             // to prevent multiple threads from expanding the same array.
             if (curLen <= n) {
                 int newLen = curLen << 1;
-                while (newLen <= n)
+                while (newLen <= n) {
                     newLen <<= 1;
+                }
                 pows = Arrays.copyOf(pows, newLen);
-                for (int i = curLen; i < newLen; i++)
+                for (int i = curLen; i < newLen; i++) {
                     pows[i] = pows[i - 1].multiply(BigInteger.TEN);
+                }
                 // Based on the following facts:
                 // 1. pows is a private local varible;
                 // 2. the following store is a volatile store.
@@ -3703,9 +3713,7 @@
      *         {@code BigDecimal}s to be aligned.
      */
     private static void matchScale(BigDecimal[] val) {
-        if (val[0].scale == val[1].scale) {
-            return;
-        } else if (val[0].scale < val[1].scale) {
+        if (val[0].scale < val[1].scale) {
             val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
         } else if (val[1].scale < val[0].scale) {
             val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
@@ -4209,16 +4217,16 @@
      * do rounding based on the passed in roundingMode.
      */
     private static BigInteger divideAndRound(BigInteger bdividend, long ldivisor, int roundingMode) {
-        boolean isRemainderZero; // record remainder is zero or not
-        int qsign; // quotient sign
-        long r = 0; // store quotient & remainder in long
-        MutableBigInteger mq = null; // store quotient
         // Descend into mutables for faster remainder checks
         MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
-        mq = new MutableBigInteger();
-        r = mdividend.divide(ldivisor, mq);
-        isRemainderZero = (r == 0);
-        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+        // store quotient
+        MutableBigInteger mq = new MutableBigInteger();
+        // store quotient & remainder in long
+        long r = mdividend.divide(ldivisor, mq);
+        // record remainder is zero or not
+        boolean isRemainderZero = (r == 0);
+        // quotient sign
+        int qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
         if (!isRemainderZero) {
             if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
                 mq.add(MutableBigInteger.ONE);
@@ -4238,16 +4246,16 @@
      */
     private static BigDecimal divideAndRound(BigInteger bdividend,
                                              long ldivisor, int scale, int roundingMode, int preferredScale) {
-        boolean isRemainderZero; // record remainder is zero or not
-        int qsign; // quotient sign
-        long r = 0; // store quotient & remainder in long
-        MutableBigInteger mq = null; // store quotient
         // Descend into mutables for faster remainder checks
         MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
-        mq = new MutableBigInteger();
-        r = mdividend.divide(ldivisor, mq);
-        isRemainderZero = (r == 0);
-        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+        // store quotient
+        MutableBigInteger mq = new MutableBigInteger();
+        // store quotient & remainder in long
+        long r = mdividend.divide(ldivisor, mq);
+        // record remainder is zero or not
+        boolean isRemainderZero = (r == 0);
+        // quotient sign
+        int qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
         if (!isRemainderZero) {
             if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
                 mq.add(MutableBigInteger.ONE);
--- a/jdk/src/share/classes/java/net/DatagramSocket.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/DatagramSocket.java	Wed Jul 05 19:37:28 2017 +0200
@@ -29,6 +29,8 @@
 import java.nio.channels.DatagramChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+import java.util.Collections;
 
 /**
  * This class represents a socket for sending and receiving datagram packets.
@@ -315,6 +317,7 @@
         }
         // creates a udp socket
         impl.create();
+        impl.setDatagramSocket(this);
         created = true;
     }
 
@@ -445,7 +448,7 @@
      *
      * <p> If given an {@link InetSocketAddress InetSocketAddress}, this method
      * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)}
-     * with the the given socket addresses IP address and port number.
+     * with the given socket addresses IP address and port number.
      *
      * @param   addr    The remote address.
      *
@@ -1258,4 +1261,94 @@
         }
         factory = fac;
     }
+
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param name The socket option
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     *
+     * @return this DatagramSocket
+     *
+     * @throws UnsupportedOperationException if the datagram socket
+     *         does not support the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @since 1.9
+     */
+    public <T> DatagramSocket setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        getImpl().setOption(name, value);
+        return this;
+    }
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the datagram socket
+     *         does not support the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 1.9
+     */
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return getImpl().getOption(name);
+    }
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    /**
+     * Returns a set of the socket options supported by this socket.
+     *
+     * This method will continue to return the set of options even after
+     * the socket has been closed.
+     *
+     * @return A set of the socket options supported by this socket. This set
+     *        may be empty if the socket's DatagramSocketImpl cannot be created.
+     *
+     * @since 1.9
+     */
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized(DatagramSocket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                DatagramSocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (IOException e) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
 }
--- a/jdk/src/share/classes/java/net/DatagramSocketImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/DatagramSocketImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -28,6 +28,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InterruptedIOException;
+import java.util.Set;
+import java.util.HashSet;
 
 /**
  * Abstract datagram and multicast socket implementation base class.
@@ -48,6 +50,20 @@
     protected FileDescriptor fd;
 
     /**
+     * The DatagramSocket or MulticastSocket
+     * that owns this impl
+     */
+    DatagramSocket socket;
+
+    void setDatagramSocket(DatagramSocket socket) {
+        this.socket = socket;
+    }
+
+    DatagramSocket getDatagramSocket() {
+        return socket;
+    }
+
+    /**
      * Creates a datagram socket.
      * @exception SocketException if there is an error in the
      * underlying protocol, such as a TCP error.
@@ -241,4 +257,116 @@
     protected FileDescriptor getFileDescriptor() {
         return fd;
     }
+
+    /**
+     * Called to set a socket option.
+     *
+     * @param name The socket option
+     *
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     *
+     * @throws UnsupportedOperationException if the DatagramSocketImpl does not
+     *         support the option
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @since 1.9
+     */
+    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
+        if (name == StandardSocketOptions.SO_SNDBUF) {
+            setOption(SocketOptions.SO_SNDBUF, value);
+        } else if (name == StandardSocketOptions.SO_RCVBUF) {
+            setOption(SocketOptions.SO_RCVBUF, value);
+        } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+            setOption(SocketOptions.SO_REUSEADDR, value);
+        } else if (name == StandardSocketOptions.IP_TOS) {
+            setOption(SocketOptions.IP_TOS, value);
+        } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
+            (getDatagramSocket() instanceof MulticastSocket)) {
+            setOption(SocketOptions.IP_MULTICAST_IF2, value);
+        } else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
+            (getDatagramSocket() instanceof MulticastSocket)) {
+            if (! (value instanceof Integer)) {
+                throw new IllegalArgumentException("not an integer");
+            }
+            setTimeToLive((Integer)value);
+        } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
+            (getDatagramSocket() instanceof MulticastSocket)) {
+            setOption(SocketOptions.IP_MULTICAST_LOOP, value);
+        } else {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+    }
+
+    /**
+     * Called to get a socket option.
+     *
+     * @param name The socket option
+     *
+     * @throws UnsupportedOperationException if the DatagramSocketImpl does not
+     *         support the option
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @since 1.9
+     */
+    protected <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == StandardSocketOptions.SO_SNDBUF) {
+            return (T) getOption(SocketOptions.SO_SNDBUF);
+        } else if (name == StandardSocketOptions.SO_RCVBUF) {
+            return (T) getOption(SocketOptions.SO_RCVBUF);
+        } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+            return (T) getOption(SocketOptions.SO_REUSEADDR);
+        } else if (name == StandardSocketOptions.IP_TOS) {
+            return (T) getOption(SocketOptions.IP_TOS);
+        } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
+            (getDatagramSocket() instanceof MulticastSocket)) {
+            return (T) getOption(SocketOptions.IP_MULTICAST_IF2);
+        } else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
+            (getDatagramSocket() instanceof MulticastSocket)) {
+            Integer ttl = getTimeToLive();
+            return (T)ttl;
+        } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
+            (getDatagramSocket() instanceof MulticastSocket)) {
+            return (T) getOption(SocketOptions.IP_MULTICAST_LOOP);
+        } else {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+    }
+
+    private static final  Set<SocketOption<?>> dgSocketOptions =
+        new HashSet<>();
+
+    private static final  Set<SocketOption<?>> mcSocketOptions =
+        new HashSet<>();
+
+    static {
+        dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
+        dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
+        dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
+        dgSocketOptions.add(StandardSocketOptions.IP_TOS);
+
+        mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
+        mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
+        mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
+        mcSocketOptions.add(StandardSocketOptions.IP_TOS);
+        mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
+        mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
+        mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+    };
+
+    /**
+     * Returns a set of SocketOptions supported by this impl
+     * and by this impl's socket (DatagramSocket or MulticastSocket)
+     *
+     * @return a Set of SocketOptions
+     */
+    protected Set<SocketOption<?>> supportedOptions() {
+        if (getDatagramSocket() instanceof MulticastSocket) {
+            return mcSocketOptions;
+        } else {
+            return dgSocketOptions;
+        }
+    }
 }
--- a/jdk/src/share/classes/java/net/HttpCookie.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/HttpCookie.java	Wed Jul 05 19:37:28 2017 +0200
@@ -74,7 +74,7 @@
     private boolean httpOnly;   // HttpOnly ... i.e. not accessible to scripts
     private int version = 1;    // Version=1 ... RFC 2965 style
 
-    // The original header this cookie was consructed from, if it was
+    // The original header this cookie was constructed from, if it was
     // constructed by parsing a header, otherwise null.
     private final String header;
 
@@ -985,7 +985,7 @@
     }
 
     /*
-     * Returns the original header this cookie was consructed from, if it was
+     * Returns the original header this cookie was constructed from, if it was
      * constructed by parsing a header, otherwise null.
      */
     private String header() {
--- a/jdk/src/share/classes/java/net/InetAddress.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/InetAddress.java	Wed Jul 05 19:37:28 2017 +0200
@@ -159,7 +159,7 @@
  * <dl>
  * <dt><b>networkaddress.cache.ttl</b></dt>
  * <dd>Indicates the caching policy for successful name lookups from
- * the name service. The value is specified as as integer to indicate
+ * the name service. The value is specified as an integer to indicate
  * the number of seconds to cache the successful lookup. The default
  * setting is to cache for an implementation specific period of time.
  * <p>
@@ -167,7 +167,7 @@
  * </dd>
  * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
  * <dd>Indicates the caching policy for un-successful name lookups
- * from the name service. The value is specified as as integer to
+ * from the name service. The value is specified as an integer to
  * indicate the number of seconds to cache the failure for
  * un-successful lookups.
  * <p>
--- a/jdk/src/share/classes/java/net/ServerSocket.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/ServerSocket.java	Wed Jul 05 19:37:28 2017 +0200
@@ -30,6 +30,8 @@
 import java.nio.channels.ServerSocketChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+import java.util.Collections;
 
 /**
  * This class implements server sockets. A server socket waits for
@@ -919,4 +921,92 @@
         /* Not implemented yet */
     }
 
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param name The socket option
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     * @return this ServerSocket
+     *
+     * @throws UnsupportedOperationException if the server socket does not
+     *         support the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 1.9
+     */
+    public <T> ServerSocket setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        getImpl().setOption(name, value);
+        return this;
+    }
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the server socket does not
+     *         support the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 1.9
+     */
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return getImpl().getOption(name);
+    }
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    /**
+     * Returns a set of the socket options supported by this server socket.
+     *
+     * This method will continue to return the set of options even after
+     * the socket has been closed.
+     *
+     * @return A set of the socket options supported by this socket. This set
+     *         may be empty if the socket's SocketImpl cannot be created.
+     *
+     * @since 1.9
+     */
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized (ServerSocket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                SocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (IOException e) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
 }
--- a/jdk/src/share/classes/java/net/Socket.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/Socket.java	Wed Jul 05 19:37:28 2017 +0200
@@ -32,6 +32,8 @@
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedAction;
+import java.util.Set;
+import java.util.Collections;
 
 /**
  * This class implements client sockets (also called just
@@ -1720,4 +1722,93 @@
     {
         /* Not implemented yet */
     }
+
+
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param name The socket option
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     * @return this Socket
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 1.9
+     */
+    public <T> Socket setOption(SocketOption<T> name, T value) throws IOException {
+        getImpl().setOption(name, value);
+        return this;
+    }
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 1.9
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return getImpl().getOption(name);
+    }
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    /**
+     * Returns a set of the socket options supported by this socket.
+     *
+     * This method will continue to return the set of options even after
+     * the socket has been closed.
+     *
+     * @return A set of the socket options supported by this socket. This set
+     *         may be empty if the socket's SocketImpl cannot be created.
+     *
+     * @since 1.9
+     */
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized (Socket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                SocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (IOException e) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
 }
--- a/jdk/src/share/classes/java/net/SocketImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/net/SocketImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -29,6 +29,9 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.FileDescriptor;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
 
 /**
  * The abstract class {@code SocketImpl} is a common superclass
@@ -355,4 +358,106 @@
     {
         /* Not implemented yet */
     }
+
+    /**
+     * Called to set a socket option.
+     *
+     * @param name The socket option
+     *
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     *
+     * @throws UnsupportedOperationException if the SocketImpl does not
+     *         support the option
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @since 1.9
+     */
+    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
+        if (name == StandardSocketOptions.SO_KEEPALIVE) {
+            setOption(SocketOptions.SO_KEEPALIVE, value);
+        } else if (name == StandardSocketOptions.SO_SNDBUF) {
+            setOption(SocketOptions.SO_SNDBUF, value);
+        } else if (name == StandardSocketOptions.SO_RCVBUF) {
+            setOption(SocketOptions.SO_RCVBUF, value);
+        } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+            setOption(SocketOptions.SO_REUSEADDR, value);
+        } else if (name == StandardSocketOptions.SO_LINGER) {
+            setOption(SocketOptions.SO_LINGER, value);
+        } else if (name == StandardSocketOptions.IP_TOS) {
+            setOption(SocketOptions.IP_TOS, value);
+        } else if (name == StandardSocketOptions.TCP_NODELAY) {
+            setOption(SocketOptions.TCP_NODELAY, value);
+        } else {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+    }
+
+    /**
+     * Called to get a socket option.
+     *
+     * @param name The socket option
+     *
+     * @return the value of the named option
+     *
+     * @throws UnsupportedOperationException if the SocketImpl does not
+     *         support the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @since 1.9
+     */
+    protected <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == StandardSocketOptions.SO_KEEPALIVE) {
+            return (T)getOption(SocketOptions.SO_KEEPALIVE);
+        } else if (name == StandardSocketOptions.SO_SNDBUF) {
+            return (T)getOption(SocketOptions.SO_SNDBUF);
+        } else if (name == StandardSocketOptions.SO_RCVBUF) {
+            return (T)getOption(SocketOptions.SO_RCVBUF);
+        } else if (name == StandardSocketOptions.SO_REUSEADDR) {
+            return (T)getOption(SocketOptions.SO_REUSEADDR);
+        } else if (name == StandardSocketOptions.SO_LINGER) {
+            return (T)getOption(SocketOptions.SO_LINGER);
+        } else if (name == StandardSocketOptions.IP_TOS) {
+            return (T)getOption(SocketOptions.IP_TOS);
+        } else if (name == StandardSocketOptions.TCP_NODELAY) {
+            return (T)getOption(SocketOptions.TCP_NODELAY);
+        } else {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+    }
+
+    private static final  Set<SocketOption<?>> socketOptions =
+        new HashSet<>();
+
+    private static final  Set<SocketOption<?>> serverSocketOptions =
+        new HashSet<>();
+
+    static {
+        socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
+        socketOptions.add(StandardSocketOptions.SO_SNDBUF);
+        socketOptions.add(StandardSocketOptions.SO_RCVBUF);
+        socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
+        socketOptions.add(StandardSocketOptions.SO_LINGER);
+        socketOptions.add(StandardSocketOptions.IP_TOS);
+        socketOptions.add(StandardSocketOptions.TCP_NODELAY);
+
+        serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
+        serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
+    };
+
+    /**
+     * Returns a set of SocketOptions supported by this impl
+     * and by this impl's socket (Socket or ServerSocket)
+     *
+     * @return a Set of SocketOptions
+     */
+    protected Set<SocketOption<?>> supportedOptions() {
+        if (getSocket() != null) {
+            return socketOptions;
+        } else {
+            return serverSocketOptions;
+        }
+    }
 }
--- a/jdk/src/share/classes/java/nio/file/Files.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java	Wed Jul 05 19:37:28 2017 +0200
@@ -38,7 +38,6 @@
 import java.io.UncheckedIOException;
 import java.io.Writer;
 import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
@@ -739,7 +738,7 @@
             // don't have permission to get absolute path
             se = x;
         }
-        // find a decendent that exists
+        // find a descendant that exists
         Path parent = dir.getParent();
         while (parent != null) {
             try {
@@ -1400,7 +1399,7 @@
         return target;
     }
 
-    // -- Miscellenous --
+    // -- Miscellaneous --
 
     /**
      * Reads the target of a symbolic link <i>(optional operation)</i>.
@@ -1535,7 +1534,7 @@
     private static class FileTypeDetectors{
         static final FileTypeDetector defaultFileTypeDetector =
             createDefaultFileTypeDetector();
-        static final List<FileTypeDetector> installeDetectors =
+        static final List<FileTypeDetector> installedDetectors =
             loadInstalledDetectors();
 
         // creates the default file type detector
@@ -1614,7 +1613,7 @@
         throws IOException
     {
         // try installed file type detectors
-        for (FileTypeDetector detector: FileTypeDetectors.installeDetectors) {
+        for (FileTypeDetector detector: FileTypeDetectors.installedDetectors) {
             String result = detector.probeContentType(path);
             if (result != null)
                 return result;
@@ -1922,7 +1921,7 @@
      * </tr>
      * <tr>
      *   <td> {@code "posix:permissions,owner,size"} </td>
-     *   <td> Reads the POSX file permissions, owner, and file size. </td>
+     *   <td> Reads the POSIX file permissions, owner, and file size. </td>
      * </tr>
      * </table>
      * </blockquote>
@@ -2448,7 +2447,7 @@
     }
 
     /**
-     * Used by isReadbale, isWritable, isExecutable to test access to a file.
+     * Used by isReadable, isWritable, isExecutable to test access to a file.
      */
     private static boolean isAccessible(Path path, AccessMode... modes) {
         try {
--- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java	Wed Jul 05 19:37:28 2017 +0200
@@ -81,7 +81,7 @@
     // installed providers
     private static volatile List<FileSystemProvider> installedProviders;
 
-    // used to avoid recursive loading of instaled providers
+    // used to avoid recursive loading of installed providers
     private static boolean loadingProviders  = false;
 
     private static Void checkPermission() {
--- a/jdk/src/share/classes/java/security/Provider.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/security/Provider.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1332,7 +1332,7 @@
         addEngine("SSLContext",                         false, null);
         addEngine("TrustManagerFactory",                false, null);
         // JGSS
-        addEngine("GssApiMechanism",                    true, "sun.security.jgss.GSSCaller");
+        addEngine("GssApiMechanism",                    false, null);
         // SASL
         addEngine("SaslClientFactory",                  false, null);
         addEngine("SaslServerFactory",                  false, null);
--- a/jdk/src/share/classes/java/util/Locale.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/Locale.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -3040,6 +3040,7 @@
          *     2616</a>
          * @param map a map containing information to customize language ranges
          * @return a Language Priority List with customization. The list is
+         *     modifiable.
          * @throws NullPointerException if {@code ranges} is null
          * @throws IllegalArgumentException if a language range or a weight
          *     found in the given {@code ranges} is ill-formed
--- a/jdk/src/share/classes/java/util/Random.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/Random.java	Wed Jul 05 19:37:28 2017 +0200
@@ -874,7 +874,7 @@
      * (inclusive) and one (exclusive).
      *
      * <p>A pseudorandom {@code double} value is generated as if it's the result
-     * of calling the method {@link #nextDouble()}}.
+     * of calling the method {@link #nextDouble()}.
      *
      * @param streamSize the number of values to generate
      * @return a stream of {@code double} values
@@ -897,7 +897,7 @@
      * (exclusive).
      *
      * <p>A pseudorandom {@code double} value is generated as if it's the result
-     * of calling the method {@link #nextDouble()}}.
+     * of calling the method {@link #nextDouble()}.
      *
      * @implNote This method is implemented to be equivalent to {@code
      * doubles(Long.MAX_VALUE)}.
--- a/jdk/src/share/classes/java/util/ServiceLoader.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/ServiceLoader.java	Wed Jul 05 19:37:28 2017 +0200
@@ -382,7 +382,7 @@
                 return p;
             } catch (Throwable x) {
                 fail(service,
-                     "Provider " + cn + " could not be instantiated: " + x,
+                     "Provider " + cn + " could not be instantiated",
                      x);
             }
             throw new Error();          // This cannot happen
--- a/jdk/src/share/classes/java/util/jar/JarVerifier.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java	Wed Jul 05 19:37:28 2017 +0200
@@ -676,6 +676,8 @@
                 } else {
                     matchUnsigned = true;
                 }
+            } else {
+                matchUnsigned = true;
             }
         }
 
@@ -778,23 +780,7 @@
 
     // true if file is part of the signature mechanism itself
     static boolean isSigningRelated(String name) {
-        name = name.toUpperCase(Locale.ENGLISH);
-        if (!name.startsWith("META-INF/")) {
-            return false;
-        }
-        name = name.substring(9);
-        if (name.indexOf('/') != -1) {
-            return false;
-        }
-        if (name.endsWith(".DSA")
-                || name.endsWith(".RSA")
-                || name.endsWith(".SF")
-                || name.endsWith(".EC")
-                || name.startsWith("SIG-")
-                || name.equals("MANIFEST.MF")) {
-            return true;
-        }
-        return false;
+        return SignatureFileVerifier.isSigningRelated(name);
     }
 
     private Enumeration<String> unsignedEntryNames(JarFile jar) {
--- a/jdk/src/share/classes/java/util/logging/LogManager.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java	Wed Jul 05 19:37:28 2017 +0200
@@ -464,7 +464,7 @@
         Logger result = getLogger(name);
         if (result == null) {
             // only allocate the new logger once
-            Logger newLogger = new Logger(name, resourceBundleName, caller, this);
+            Logger newLogger = new Logger(name, resourceBundleName, caller, this, false);
             do {
                 if (addLogger(newLogger)) {
                     // We successfully added the new Logger that we
@@ -511,13 +511,13 @@
         } while (logger == null);
 
         // LogManager will set the sysLogger's handlers via LogManager.addLogger method.
-        if (logger != sysLogger && sysLogger.getHandlers().length == 0) {
+        if (logger != sysLogger && sysLogger.accessCheckedHandlers().length == 0) {
             // if logger already exists but handlers not set
             final Logger l = logger;
             AccessController.doPrivileged(new PrivilegedAction<Void>() {
                 @Override
                 public Void run() {
-                    for (Handler hdl : l.getHandlers()) {
+                    for (Handler hdl : l.accessCheckedHandlers()) {
                         sysLogger.addHandler(hdl);
                     }
                     return null;
@@ -835,7 +835,7 @@
             Logger result = findLogger(name);
             if (result == null) {
                 // only allocate the new system logger once
-                Logger newLogger = new Logger(name, resourceBundleName, null, getOwner());
+                Logger newLogger = new Logger(name, resourceBundleName, null, getOwner(), true);
                 do {
                     if (addLocalLogger(newLogger)) {
                         // We successfully added the new Logger that we
@@ -1527,7 +1527,7 @@
             // We do not call the protected Logger two args constructor here,
             // to avoid calling LogManager.getLogManager() from within the
             // RootLogger constructor.
-            super("", null, null, LogManager.this);
+            super("", null, null, LogManager.this, true);
         }
 
         @Override
@@ -1550,9 +1550,9 @@
         }
 
         @Override
-        public Handler[] getHandlers() {
+        Handler[] accessCheckedHandlers() {
             initializeGlobalHandlers();
-            return super.getHandlers();
+            return super.accessCheckedHandlers();
         }
     }
 
--- a/jdk/src/share/classes/java/util/logging/Logger.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java	Wed Jul 05 19:37:28 2017 +0200
@@ -277,6 +277,7 @@
     private volatile Level levelObject;
     private volatile int levelValue;  // current effective level value
     private WeakReference<ClassLoader> callersClassLoaderRef;
+    private final boolean isSystemLogger;
 
     /**
      * GLOBAL_LOGGER_NAME is a name for the global logger.
@@ -370,11 +371,12 @@
      *             no corresponding resource can be found.
      */
     protected Logger(String name, String resourceBundleName) {
-        this(name, resourceBundleName, null, LogManager.getLogManager());
+        this(name, resourceBundleName, null, LogManager.getLogManager(), false);
     }
 
-    Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager) {
+    Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager, boolean isSystemLogger) {
         this.manager = manager;
+        this.isSystemLogger = isSystemLogger;
         setupResourceInfo(resourceBundleName, caller);
         this.name = name;
         levelValue = Level.INFO.intValue();
@@ -401,6 +403,7 @@
     private Logger(String name) {
         // The manager field is not initialized here.
         this.name = name;
+        this.isSystemLogger = true;
         levelValue = Level.INFO.intValue();
     }
 
@@ -635,7 +638,7 @@
         // cleanup some Loggers that have been GC'ed
         manager.drainLoggerRefQueueBounded();
         Logger result = new Logger(null, resourceBundleName,
-                                   Reflection.getCallerClass(), manager);
+                                   Reflection.getCallerClass(), manager, false);
         result.anonymous = true;
         Logger root = manager.getLogger("");
         result.doSetParent(root);
@@ -727,15 +730,23 @@
 
         Logger logger = this;
         while (logger != null) {
-            for (Handler handler : logger.getHandlers()) {
+            final Handler[] loggerHandlers = isSystemLogger
+                ? logger.accessCheckedHandlers()
+                : logger.getHandlers();
+
+            for (Handler handler : loggerHandlers) {
                 handler.publish(record);
             }
 
-            if (!logger.getUseParentHandlers()) {
+            final boolean useParentHdls = isSystemLogger
+                ? logger.useParentHandlers
+                : logger.getUseParentHandlers();
+
+            if (!useParentHdls) {
                 break;
             }
 
-            logger = logger.getParent();
+            logger = isSystemLogger ? logger.parent : logger.getParent();
         }
     }
 
@@ -1762,6 +1773,12 @@
      * @return  an array of all registered Handlers
      */
     public Handler[] getHandlers() {
+        return accessCheckedHandlers();
+    }
+
+    // This method should ideally be marked final - but unfortunately
+    // it needs to be overridden by LogManager.RootLogger
+    Handler[] accessCheckedHandlers() {
         return handlers.toArray(emptyHandlers);
     }
 
@@ -2149,12 +2166,14 @@
             if (trb.userBundle != null) {
                 return trb;
             }
-            final String rbName = target.getResourceBundleName();
+            final String rbName = isSystemLogger
+                ? trb.resourceBundleName
+                : target.getResourceBundleName();
             if (rbName != null) {
                 return LoggerBundle.get(rbName,
                             findResourceBundle(rbName, true));
             }
-            target = target.getParent();
+            target = isSystemLogger ? target.parent : target.getParent();
         }
         return NO_RESOURCE_BUNDLE;
     }
--- a/jdk/src/share/classes/java/util/logging/Logging.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logging.java	Wed Jul 05 19:37:28 2017 +0200
@@ -87,7 +87,7 @@
         Logger logger = logManager.getLogger(loggerName);
         if (logger == null) {
             throw new IllegalArgumentException("Logger " + loggerName +
-                "does not exist");
+                " does not exist");
         }
 
         Level level = null;
--- a/jdk/src/share/classes/javax/naming/NameImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/javax/naming/NameImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -232,7 +232,7 @@
             syntaxDirection = FLAT;
         } else {
             throw new IllegalArgumentException(syntaxDirectionStr +
-                "is not a valid value for the jndi.syntax.direction property");
+                " is not a valid value for the jndi.syntax.direction property");
         }
 
         if (syntaxDirection != FLAT) {
--- a/jdk/src/share/classes/javax/script/ScriptEngineManager.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/javax/script/ScriptEngineManager.java	Wed Jul 05 19:37:28 2017 +0200
@@ -81,23 +81,28 @@
         nameAssociations = new HashMap<String, ScriptEngineFactory>();
         extensionAssociations = new HashMap<String, ScriptEngineFactory>();
         mimeTypeAssociations = new HashMap<String, ScriptEngineFactory>();
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            public Object run() {
-                initEngines(loader);
-                return null;
-            }
-        });
+        initEngines(loader);
+    }
+
+    private ServiceLoader<ScriptEngineFactory> getServiceLoader(final ClassLoader loader) {
+        if (loader != null) {
+            return ServiceLoader.load(ScriptEngineFactory.class, loader);
+        } else {
+            return ServiceLoader.loadInstalled(ScriptEngineFactory.class);
+        }
     }
 
     private void initEngines(final ClassLoader loader) {
         Iterator<ScriptEngineFactory> itr = null;
         try {
-            ServiceLoader<ScriptEngineFactory> sl;
-            if (loader != null) {
-                sl = ServiceLoader.load(ScriptEngineFactory.class, loader);
-            } else {
-                sl = ServiceLoader.loadInstalled(ScriptEngineFactory.class);
-            }
+            ServiceLoader<ScriptEngineFactory> sl = AccessController.doPrivileged(
+                new PrivilegedAction<ServiceLoader<ScriptEngineFactory>>() {
+                    @Override
+                    public ServiceLoader<ScriptEngineFactory> run() {
+                        return getServiceLoader(loader);
+                    }
+                });
+
             itr = sl.iterator();
         } catch (ServiceConfigurationError err) {
             System.err.println("Can't find ScriptEngineFactory providers: " +
--- a/jdk/src/share/classes/javax/security/auth/Subject.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/javax/security/auth/Subject.java	Wed Jul 05 19:37:28 2017 +0200
@@ -959,14 +959,30 @@
     /**
      * Reads this object from a stream (i.e., deserializes it)
      */
+    @SuppressWarnings("unchecked")
     private void readObject(java.io.ObjectInputStream s)
                 throws java.io.IOException, ClassNotFoundException {
 
-        s.defaultReadObject();
+        ObjectInputStream.GetField gf = s.readFields();
+
+        readOnly = gf.get("readOnly", false);
+
+        Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
 
         // Rewrap the principals into a SecureSet
-        principals = Collections.synchronizedSet(new SecureSet<Principal>
-                                (this, PRINCIPAL_SET, principals));
+        if (inputPrincs == null) {
+            throw new NullPointerException
+                (ResourcesMgr.getString("invalid.null.input.s."));
+        }
+        try {
+            principals = Collections.synchronizedSet(new SecureSet<Principal>
+                                (this, PRINCIPAL_SET, inputPrincs));
+        } catch (NullPointerException npe) {
+            // Sometimes people deserialize the principals set only.
+            // Subject is not accessible, so just don't fail.
+            principals = Collections.synchronizedSet
+                        (new SecureSet<Principal>(this, PRINCIPAL_SET));
+        }
 
         // The Credential {@code Set} is not serialized, but we do not
         // want the default deserialization routine to set it to null.
--- a/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java	Wed Jul 05 19:37:28 2017 +0200
@@ -28,8 +28,11 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.sql.SQLException;
+import java.util.PropertyPermission;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
+import javax.sql.rowset.spi.SyncFactoryException;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * A factory API that enables applications to obtain a
@@ -129,15 +132,11 @@
             factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);
             if (factoryClassName != null) {
                 trace("Found system property, value=" + factoryClassName);
-                factory = (RowSetFactory) getFactoryClass(factoryClassName, null, true).newInstance();
+                factory = (RowSetFactory) ReflectUtil.newInstance(getFactoryClass(factoryClassName, null, true));
             }
-        } catch (ClassNotFoundException e) {
-            throw new SQLException(
-                    "RowSetFactory: " + factoryClassName + " not found", e);
-        } catch (Exception e) {
-            throw new SQLException(
-                    "RowSetFactory: " + factoryClassName + " could not be instantiated: " + e,
-                    e);
+        }  catch (Exception e) {
+            throw new SQLException( "RowSetFactory: " + factoryClassName +
+                    " could not be instantiated: ", e);
         }
 
         // Check to see if we found the RowSetFactory via a System property
@@ -182,6 +181,16 @@
             throws SQLException {
 
         trace("***In newInstance()");
+
+        if(factoryClassName == null) {
+            throw new SQLException("Error: factoryClassName cannot be null");
+        }
+        try {
+            ReflectUtil.checkPackageAccess(factoryClassName);
+        } catch (java.security.AccessControlException e) {
+            throw new SQLException("Access Exception",e);
+        }
+
         try {
             Class<?> providerClass = getFactoryClass(factoryClassName, cl, false);
             RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
@@ -291,8 +300,9 @@
                 public String run() {
                     return System.getProperty(propName);
                 }
-            });
+            }, null, new PropertyPermission(propName, "read"));
         } catch (SecurityException se) {
+            trace("error getting " + propName + ":  "+ se);
             if (debug) {
                 se.printStackTrace();
             }
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SQLInputImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -27,6 +27,7 @@
 import java.sql.*;
 import java.util.Arrays;
 import java.util.Map;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * An input stream used for custom mapping user-defined types (UDTs).
@@ -476,13 +477,9 @@
                 // create new instance of the class
                 SQLData obj = null;
                 try {
-                    obj = (SQLData)c.newInstance();
-                } catch (java.lang.InstantiationException ex) {
-                    throw new SQLException("Unable to instantiate: " +
-                            ex.getMessage());
-                } catch (java.lang.IllegalAccessException ex) {
-                    throw new SQLException("Unable to instantiate: " +
-                            ex.getMessage());
+                    obj = (SQLData)ReflectUtil.newInstance(c);
+                } catch (Exception ex) {
+                    throw new SQLException("Unable to Instantiate: ", ex);
                 }
                 // get the attributes from the struct
                 Object attribs[] = s.getAttributes(map);
--- a/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Wed Jul 05 19:37:28 2017 +0200
@@ -37,8 +37,11 @@
 import java.io.FileNotFoundException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 
 import javax.naming.*;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * The Service Provider Interface (SPI) mechanism that generates <code>SyncProvider</code>
@@ -329,7 +332,7 @@
         // Local implementation class names and keys from Properties
         // file, translate names into Class objects using Class.forName
         // and store mappings
-        Properties properties = new Properties();
+        final Properties properties = new Properties();
 
         if (implementations == null) {
             implementations = new Hashtable<>();
@@ -356,10 +359,11 @@
                         public String run() {
                             return System.getProperty("rowset.properties");
                         }
-                    }, null, new PropertyPermission("rowset.properties","read"));
+                    }, null, new PropertyPermission("rowset.properties", "read"));
                 } catch (Exception ex) {
+                    System.out.println("errorget rowset.properties: " + ex);
                     strRowsetProperties = null;
-                }
+                };
 
                 if (strRowsetProperties != null) {
                     // Load user's implementation of SyncProvider
@@ -380,14 +384,27 @@
 
                 ClassLoader cl = Thread.currentThread().getContextClassLoader();
 
-                try (InputStream stream =
-                         (cl == null) ? ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES)
-                                      : cl.getResourceAsStream(ROWSET_PROPERTIES)) {
-                    if (stream == null) {
-                        throw new SyncFactoryException(
-                            "Resource " + ROWSET_PROPERTIES + " not found");
+                try {
+                    AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
+                        try (InputStream stream = (cl == null) ?
+                                ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES)
+                                : cl.getResourceAsStream(ROWSET_PROPERTIES)) {
+                            if (stream == null) {
+                                throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found");
+                            }
+                            properties.load(stream);
+                        }
+                        return null;
+                    });
+                } catch (PrivilegedActionException ex) {
+                    Throwable e = ex.getException();
+                    if (e instanceof SyncFactoryException) {
+                      throw (SyncFactoryException) e;
+                    } else {
+                        SyncFactoryException sfe = new SyncFactoryException();
+                        sfe.initCause(ex.getException());
+                        throw sfe;
                     }
-                    properties.load(stream);
                 }
 
                 parseProperties(properties);
@@ -411,7 +428,7 @@
                     public String run() {
                         return System.getProperty(ROWSET_SYNC_PROVIDER);
                     }
-                }, null, new PropertyPermission(ROWSET_SYNC_PROVIDER,"read"));
+                }, null, new PropertyPermission(ROWSET_SYNC_PROVIDER, "read"));
             } catch (Exception ex) {
                 providerImpls = null;
             }
@@ -547,6 +564,14 @@
             return new com.sun.rowset.providers.RIOptimisticProvider();
         }
 
+        try {
+            ReflectUtil.checkPackageAccess(providerID);
+        } catch (java.security.AccessControlException e) {
+            SyncFactoryException sfe = new SyncFactoryException();
+            sfe.initCause(e);
+            throw sfe;
+        }
+
         // Attempt to invoke classname from registered SyncProvider list
         Class<?> c = null;
         try {
@@ -555,7 +580,7 @@
             /**
              * The SyncProvider implementation of the user will be in
              * the classpath. We need to find the ClassLoader which loads
-             * this SyncFactory and try to laod the SyncProvider class from
+             * this SyncFactory and try to load the SyncProvider class from
              * there.
              **/
             c = Class.forName(providerID, true, cl);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * 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.net;
+
+import java.net.SocketOption;
+
+/**
+ * Defines extended socket options, beyond those defined in
+ * {@link java.net.StandardSocketOptions}. These options may be platform
+ * specific.
+ *
+ * @since 1.9
+ */
+@jdk.Exported
+public final class ExtendedSocketOptions {
+
+    private static class ExtSocketOption<T> implements SocketOption<T> {
+        private final String name;
+        private final Class<T> type;
+        ExtSocketOption(String name, Class<T> type) {
+            this.name = name;
+            this.type = type;
+        }
+        @Override public String name() { return name; }
+        @Override public Class<T> type() { return type; }
+        @Override public String toString() { return name; }
+    }
+
+    private ExtendedSocketOptions() {}
+
+    /**
+     * Service level properties. When a security manager is installed,
+     * setting or getting this option requires a {@link NetworkPermission}
+     * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
+     * respectively.
+     */
+    public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
+        ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/net/NetworkPermission.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.net;
+
+import java.security.BasicPermission;
+
+/**
+ * Represents permission to access the extended networking capabilities
+ * defined in the jdk.net package. These permissions contain a target
+ * name, but no actions list. Callers either possess the permission or not.
+ * <p>
+ * The following targets are defined:
+ * <p>
+ * <table border=1 cellpadding=5 summary="permission target name,
+ *  what the target allows,and associated risks">
+ * <tr>
+ *   <th>Permission Target Name</th>
+ *   <th>What the Permission Allows</th>
+ *   <th>Risks of Allowing this Permission</th>
+ * </tr>
+ * <tr>
+ *   <td>setOption.SO_FLOW_SLA</td>
+ *   <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option
+ *       on any socket that supports it</td>
+ *   <td>allows caller to set a higher priority or bandwidth allocation
+ *       to sockets it creates, than they might otherwise be allowed.</td>
+ * </tr>
+ * <tr>
+ *   <td>getOption.SO_FLOW_SLA</td>
+ *   <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA}
+ *       setting from any socket that supports the option</td>
+ *   <td>allows caller access to SLA information that it might not
+ *       otherwise have</td>
+ * </tr></table>
+ *
+ * @see jdk.net.ExtendedSocketOptions
+ *
+ * @since 1.9
+ */
+
+@jdk.Exported
+public final class NetworkPermission extends BasicPermission {
+
+    private static final long serialVersionUID = -2012939586906722291L;
+
+    /**
+     * Creates a NetworkPermission with the given target name.
+     *
+     * @param name the permission target name
+     * @throws NullPointerException if {@code name} is {@code null}.
+     * @throws IllegalArgumentException if {@code name} is empty.
+     */
+    public NetworkPermission(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Creates a NetworkPermission with the given target name.
+     *
+     * @param name the permission target name
+     * @param actions should be {@code null}. Is ignored if not.
+     * @throws NullPointerException if {@code name} is {@code null}.
+     * @throws IllegalArgumentException if {@code name} is empty.
+     */
+    public NetworkPermission(String name, String actions)
+    {
+        super(name, actions);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/net/SocketFlow.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * 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.net;
+
+import java.lang.annotation.Native;
+
+/**
+ * Represents the service level properties for the platform specific socket
+ * option {@link ExtendedSocketOptions#SO_FLOW_SLA}.
+ * <p>
+ * The priority and bandwidth parameters must be set before
+ * setting the socket option.
+ * <p>
+ * When the {@code SO_FLOW_SLA} option is set then it may not take effect
+ * immediately. If the value of the socket option is obtained with
+ * {@code getOption()} then the status may be returned as {@code INPROGRESS}
+ * until it takes effect. The priority and bandwidth values are only valid when
+ * the status is returned as OK.
+ * <p>
+ * When a security manager is installed, a {@link NetworkPermission}
+ * is required to set or get this option.
+ *
+ * @since 1.9
+ */
+@jdk.Exported
+public class SocketFlow {
+
+    private static final int UNSET = -1;
+    @Native public static final int NORMAL_PRIORITY = 1;
+    @Native public static final int HIGH_PRIORITY = 2;
+
+    private int priority = NORMAL_PRIORITY;
+
+    private long bandwidth = UNSET;
+
+    private Status status = Status.NO_STATUS;
+
+    private SocketFlow() {}
+
+    /**
+     * Enumeration of the return values from the SO_FLOW_SLA
+     * socket option. Both setting and getting the option return
+     * one of these statuses, which reflect the state of socket's
+     * flow.
+     *
+     * @since 1.9
+     */
+    @jdk.Exported
+    public enum Status {
+        /**
+         * Set or get socket option has not been called yet. Status
+         * values can only be retrieved after calling set or get.
+         */
+        NO_STATUS,
+        /**
+         * Flow successfully created.
+         */
+        OK,
+        /**
+         * Caller has no permission to create flow.
+         */
+        NO_PERMISSION,
+        /**
+         * Flow can not be created because socket is not connected.
+         */
+        NOT_CONNECTED,
+        /**
+         * Flow creation not supported for this socket.
+         */
+        NOT_SUPPORTED,
+        /**
+         * A flow already exists with identical attributes.
+         */
+        ALREADY_CREATED,
+        /**
+         * A flow is being created.
+         */
+        IN_PROGRESS,
+        /**
+         * Some other unspecified error.
+         */
+        OTHER
+    }
+
+    /**
+     * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
+     * socket option and create a socket flow.
+     */
+    public static SocketFlow create() {
+        return new SocketFlow();
+    }
+
+    /**
+     * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
+     * HIGH_PRIORITY. If not set, a flow's priority is normal.
+     *
+     * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or
+     *         HIGH_PRIORITY.
+     */
+    public SocketFlow priority(int priority) {
+        if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) {
+            throw new IllegalArgumentException("invalid priority");
+        }
+        this.priority = priority;
+        return this;
+    }
+
+    /**
+     * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero.
+     * A value of zero drops all packets for the socket.
+     *
+     * @throws IllegalArgumentException if bandwidth is less than zero.
+     */
+    public SocketFlow bandwidth(long bandwidth) {
+        if (bandwidth < 0) {
+            throw new IllegalArgumentException("invalid bandwidth");
+        } else {
+            this.bandwidth = bandwidth;
+        }
+        return this;
+    }
+
+    /**
+     * Returns this SocketFlow's priority.
+     */
+    public int priority() {
+        return priority;
+    }
+
+    /**
+     * Returns this SocketFlow's bandwidth.
+     *
+     * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK.
+     */
+    public long bandwidth() {
+        return bandwidth;
+    }
+
+    /**
+     * Returns the Status value of this SocketFlow. NO_STATUS is returned
+     * if the object was not used in a call to set or get the option.
+     */
+    public Status status() {
+        return status;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/net/Sockets.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,311 @@
+/*
+ * 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.net;
+
+import java.net.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.lang.reflect.Field;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Collections;
+import sun.net.ExtendedOptionsImpl;
+
+/**
+ * Defines static methods to set and get socket options defined by the
+ * {@link java.net.SocketOption} interface. All of the standard options defined
+ * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and
+ * {@link java.net.DatagramSocket} can be set this way, as well as additional
+ * or platform specific options supported by each socket type.
+ * <p>
+ * The {@link #supportedOptions(Class)} method can be called to determine
+ * the complete set of options available (per socket type) on the
+ * current system.
+ * <p>
+ * When a security manager is installed, some non-standard socket options
+ * may require a security permission before being set or get.
+ * The details are specified in {@link ExtendedSocketOptions}. No permission
+ * is required for {@link java.net.StandardSocketOption}s.
+ *
+ * @see java.nio.channels.NetworkChannel
+ */
+@jdk.Exported
+public class Sockets {
+
+    private final static HashMap<Class<?>,Set<SocketOption<?>>>
+        options = new HashMap<>();
+
+    static {
+        initOptionSets();
+    }
+
+    private Sockets() {}
+
+    /**
+     * Sets the value of a socket option on a {@link java.net.Socket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     * @param value The value of the socket option. May be null for some
+     *              options.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or socket is closed.
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException
+    {
+        s.setOption(name, value);
+    }
+
+    /**
+     * Returns the value of a socket option from a {@link java.net.Socket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException
+    {
+        return s.getOption(name);
+    }
+
+    /**
+     * Sets the value of a socket option on a {@link java.net.ServerSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     * @param value The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException
+    {
+        s.setOption(name, value);
+    }
+
+    /**
+     * Returns the value of a socket option from a {@link java.net.ServerSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException
+    {
+        return s.getOption(name);
+    }
+
+    /**
+     * Sets the value of a socket option on a {@link java.net.DatagramSocket}
+     * or {@link java.net.MulticastSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     * @param value The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException
+    {
+        s.setOption(name, value);
+    }
+
+    /**
+     * Returns the value of a socket option from a
+     * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException
+    {
+        return s.getOption(name);
+    }
+
+    /**
+     * Returns a set of {@link java.net.SocketOption}s supported by the
+     * given socket type. This set may include standard options and also
+     * non standard extended options.
+     *
+     * @param socketType the type of java.net socket
+     *
+     * @throws IllegalArgumentException if socketType is not a valid
+     *         socket type from the java.net package.
+     */
+    public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) {
+        Set<SocketOption<?>> set = options.get(socketType);
+        if (set == null) {
+            throw new IllegalArgumentException("unknown socket type");
+        }
+        return set;
+    }
+
+    private static void checkValueType(Object value, Class<?> type) {
+        if (!type.isAssignableFrom(value.getClass())) {
+            String s = "Found: " + value.getClass().toString() + " Expected: "
+                        + type.toString();
+            throw new IllegalArgumentException(s);
+        }
+    }
+
+    private static void initOptionSets() {
+        boolean flowsupported = ExtendedOptionsImpl.flowSupported();
+
+        // Socket
+
+        Set<SocketOption<?>> set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_KEEPALIVE);
+        set.add(StandardSocketOptions.SO_SNDBUF);
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        set.add(StandardSocketOptions.SO_LINGER);
+        set.add(StandardSocketOptions.IP_TOS);
+        set.add(StandardSocketOptions.TCP_NODELAY);
+        if (flowsupported) {
+            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        set = Collections.unmodifiableSet(set);
+        options.put(Socket.class, set);
+
+        // ServerSocket
+
+        set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        set = Collections.unmodifiableSet(set);
+        options.put(ServerSocket.class, set);
+
+        // DatagramSocket
+
+        set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_SNDBUF);
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        set.add(StandardSocketOptions.IP_TOS);
+        if (flowsupported) {
+            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        set = Collections.unmodifiableSet(set);
+        options.put(DatagramSocket.class, set);
+
+        // MulticastSocket
+
+        set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_SNDBUF);
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        set.add(StandardSocketOptions.IP_TOS);
+        set.add(StandardSocketOptions.IP_MULTICAST_IF);
+        set.add(StandardSocketOptions.IP_MULTICAST_TTL);
+        set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+        if (flowsupported) {
+            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        set = Collections.unmodifiableSet(set);
+        options.put(MulticastSocket.class, set);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/net/package-info.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/**
+ * Platform specific socket options for the {@code java.net} and {@code java.nio.channels}
+ * socket classes.
+ *
+ * @since 1.9
+ */
+
+@jdk.Exported
+package jdk.net;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/JarFileSystemProvider.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007, 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.nio.zipfs;
+
+import java.nio.file.*;
+import java.nio.file.spi.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.FileSystemProvider;
+
+import java.net.URI;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.channels.FileChannel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+class JarFileSystemProvider extends ZipFileSystemProvider
+{
+
+    @Override
+    public String getScheme() {
+        return "jar";
+    }
+
+    @Override
+    protected Path uriToPath(URI uri) {
+        String scheme = uri.getScheme();
+        if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
+            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
+        }
+        try {
+            String uristr = uri.toString();
+            int end = uristr.indexOf("!/");
+            uristr = uristr.substring(4, (end == -1) ? uristr.length() : end);
+            uri = new URI(uristr);
+            return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
+                        .toAbsolutePath();
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+    }
+
+    @Override
+    public Path getPath(URI uri) {
+        FileSystem fs = getFileSystem(uri);
+        String path = uri.getFragment();
+        if (path == null) {
+            String uristr = uri.toString();
+            int off = uristr.indexOf("!/");
+            if (off != -1)
+                path = uristr.substring(off + 2);
+        }
+        if (path != null)
+            return fs.getPath(path);
+        throw new IllegalArgumentException("URI: "
+            + uri
+            + " does not contain path fragment ex. jar:///c:/foo.zip!/BAR");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,2 @@
+jdk.nio.zipfs.ZipFileSystemProvider
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipCoder.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.util.Arrays;
+
+/**
+ * Utility class for zipfile name and comment decoding and encoding
+ *
+ * @author  Xueming Shen
+ */
+
+final class ZipCoder {
+
+    String toString(byte[] ba, int length) {
+        CharsetDecoder cd = decoder().reset();
+        int len = (int)(length * cd.maxCharsPerByte());
+        char[] ca = new char[len];
+        if (len == 0)
+            return new String(ca);
+        ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        CoderResult cr = cd.decode(bb, cb, true);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        cr = cd.flush(cb);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        return new String(ca, 0, cb.position());
+    }
+
+    String toString(byte[] ba) {
+        return toString(ba, ba.length);
+    }
+
+    byte[] getBytes(String s) {
+        CharsetEncoder ce = encoder().reset();
+        char[] ca = s.toCharArray();
+        int len = (int)(ca.length * ce.maxBytesPerChar());
+        byte[] ba = new byte[len];
+        if (len == 0)
+            return ba;
+        ByteBuffer bb = ByteBuffer.wrap(ba);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        CoderResult cr = ce.encode(cb, bb, true);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        cr = ce.flush(bb);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        if (bb.position() == ba.length)  // defensive copy?
+            return ba;
+        else
+            return Arrays.copyOf(ba, bb.position());
+    }
+
+    // assume invoked only if "this" is not utf8
+    byte[] getBytesUTF8(String s) {
+        if (isutf8)
+            return getBytes(s);
+        if (utf8 == null)
+            utf8 = new ZipCoder(Charset.forName("UTF-8"));
+        return utf8.getBytes(s);
+    }
+
+    String toStringUTF8(byte[] ba, int len) {
+        if (isutf8)
+            return toString(ba, len);
+        if (utf8 == null)
+            utf8 = new ZipCoder(Charset.forName("UTF-8"));
+        return utf8.toString(ba, len);
+    }
+
+    boolean isUTF8() {
+        return isutf8;
+    }
+
+    private Charset cs;
+    private boolean isutf8;
+    private ZipCoder utf8;
+
+    private ZipCoder(Charset cs) {
+        this.cs = cs;
+        this.isutf8 = cs.name().equals("UTF-8");
+    }
+
+    static ZipCoder get(Charset charset) {
+        return new ZipCoder(charset);
+    }
+
+    static ZipCoder get(String csn) {
+        try {
+            return new ZipCoder(Charset.forName(csn));
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+        return new ZipCoder(Charset.defaultCharset());
+    }
+
+    private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>();
+    private final ThreadLocal<CharsetEncoder> encTL = new ThreadLocal<>();
+
+    private CharsetDecoder decoder() {
+        CharsetDecoder dec = decTL.get();
+        if (dec == null) {
+            dec = cs.newDecoder()
+              .onMalformedInput(CodingErrorAction.REPORT)
+              .onUnmappableCharacter(CodingErrorAction.REPORT);
+            decTL.set(dec);
+        }
+        return dec;
+    }
+
+    private CharsetEncoder encoder() {
+        CharsetEncoder enc = encTL.get();
+        if (enc == null) {
+            enc = cs.newEncoder()
+              .onMalformedInput(CodingErrorAction.REPORT)
+              .onUnmappableCharacter(CodingErrorAction.REPORT);
+            encTL.set(enc);
+        }
+        return enc;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipConstants.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+/**
+ *
+ * @author Xueming Shen
+ */
+
+class ZipConstants {
+    /*
+     * Compression methods
+     */
+    static final int METHOD_STORED     = 0;
+    static final int METHOD_DEFLATED   = 8;
+    static final int METHOD_DEFLATED64 = 9;
+    static final int METHOD_BZIP2      = 12;
+    static final int METHOD_LZMA       = 14;
+    static final int METHOD_LZ77       = 19;
+    static final int METHOD_AES        = 99;
+
+    /*
+     * General purpose big flag
+     */
+    static final int FLAG_ENCRYPTED  = 0x01;
+    static final int FLAG_DATADESCR  = 0x08;    // crc, size and csize in dd
+    static final int FLAG_EFS        = 0x800;   // If this bit is set the filename and
+                                                // comment fields for this file must be
+                                                // encoded using UTF-8.
+    /*
+     * Header signatures
+     */
+    static long LOCSIG = 0x04034b50L;   // "PK\003\004"
+    static long EXTSIG = 0x08074b50L;   // "PK\007\008"
+    static long CENSIG = 0x02014b50L;   // "PK\001\002"
+    static long ENDSIG = 0x06054b50L;   // "PK\005\006"
+
+    /*
+     * Header sizes in bytes (including signatures)
+     */
+    static final int LOCHDR = 30;       // LOC header size
+    static final int EXTHDR = 16;       // EXT header size
+    static final int CENHDR = 46;       // CEN header size
+    static final int ENDHDR = 22;       // END header size
+
+    /*
+     * Local file (LOC) header field offsets
+     */
+    static final int LOCVER = 4;        // version needed to extract
+    static final int LOCFLG = 6;        // general purpose bit flag
+    static final int LOCHOW = 8;        // compression method
+    static final int LOCTIM = 10;       // modification time
+    static final int LOCCRC = 14;       // uncompressed file crc-32 value
+    static final int LOCSIZ = 18;       // compressed size
+    static final int LOCLEN = 22;       // uncompressed size
+    static final int LOCNAM = 26;       // filename length
+    static final int LOCEXT = 28;       // extra field length
+
+    /*
+     * Extra local (EXT) header field offsets
+     */
+    static final int EXTCRC = 4;        // uncompressed file crc-32 value
+    static final int EXTSIZ = 8;        // compressed size
+    static final int EXTLEN = 12;       // uncompressed size
+
+    /*
+     * Central directory (CEN) header field offsets
+     */
+    static final int CENVEM = 4;        // version made by
+    static final int CENVER = 6;        // version needed to extract
+    static final int CENFLG = 8;        // encrypt, decrypt flags
+    static final int CENHOW = 10;       // compression method
+    static final int CENTIM = 12;       // modification time
+    static final int CENCRC = 16;       // uncompressed file crc-32 value
+    static final int CENSIZ = 20;       // compressed size
+    static final int CENLEN = 24;       // uncompressed size
+    static final int CENNAM = 28;       // filename length
+    static final int CENEXT = 30;       // extra field length
+    static final int CENCOM = 32;       // comment length
+    static final int CENDSK = 34;       // disk number start
+    static final int CENATT = 36;       // internal file attributes
+    static final int CENATX = 38;       // external file attributes
+    static final int CENOFF = 42;       // LOC header offset
+
+    /*
+     * End of central directory (END) header field offsets
+     */
+    static final int ENDSUB = 8;        // number of entries on this disk
+    static final int ENDTOT = 10;       // total number of entries
+    static final int ENDSIZ = 12;       // central directory size in bytes
+    static final int ENDOFF = 16;       // offset of first CEN header
+    static final int ENDCOM = 20;       // zip file comment length
+
+    /*
+     * ZIP64 constants
+     */
+    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
+    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
+    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
+    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
+    static final int  ZIP64_EXTHDR = 24;           // EXT header size
+    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
+
+    static final int  ZIP64_MINVAL32 = 0xFFFF;
+    static final long ZIP64_MINVAL = 0xFFFFFFFFL;
+
+    /*
+     * Zip64 End of central directory (END) header field offsets
+     */
+    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
+    static final int  ZIP64_ENDVEM = 12;      // version made by
+    static final int  ZIP64_ENDVER = 14;      // version needed to extract
+    static final int  ZIP64_ENDNMD = 16;      // number of this disk
+    static final int  ZIP64_ENDDSK = 20;      // disk number of start
+    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
+    static final int  ZIP64_ENDTOT = 32;      // total number of entries
+    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
+    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
+    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
+
+    /*
+     * Zip64 End of central directory locator field offsets
+     */
+    static final int  ZIP64_LOCDSK = 4;       // disk number start
+    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
+    static final int  ZIP64_LOCTOT = 16;      // total number of disks
+
+    /*
+     * Zip64 Extra local (EXT) header field offsets
+     */
+    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
+    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
+    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
+
+    /*
+     * Extra field header ID
+     */
+    static final int  EXTID_ZIP64 = 0x0001;      // ZIP64
+    static final int  EXTID_NTFS  = 0x000a;      // NTFS
+    static final int  EXTID_UNIX  = 0x000d;      // UNIX
+    static final int  EXTID_EFS   = 0x0017;      // Strong Encryption
+    static final int  EXTID_EXTT  = 0x5455;      // Info-ZIP Extended Timestamp
+
+    /*
+     * fields access methods
+     */
+    ///////////////////////////////////////////////////////
+    static final int CH(byte[] b, int n) {
+        return Byte.toUnsignedInt(b[n]);
+    }
+
+    static final int SH(byte[] b, int n) {
+        return Byte.toUnsignedInt(b[n]) | (Byte.toUnsignedInt(b[n + 1]) << 8);
+    }
+
+    static final long LG(byte[] b, int n) {
+        return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
+    }
+
+    static final long LL(byte[] b, int n) {
+        return (LG(b, n)) | (LG(b, n + 4) << 32);
+    }
+
+    static final long GETSIG(byte[] b) {
+        return LG(b, 0);
+    }
+
+    // local file (LOC) header fields
+    static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
+    static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
+    static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
+    static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
+    static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
+    static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
+    static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
+    static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
+    static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
+    static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
+
+    // extra local (EXT) header fields
+    static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
+    static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
+    static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
+
+    // end of central directory header (END) fields
+    static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
+    static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
+    static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
+    static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
+    static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
+    static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
+
+    // zip64 end of central directory recoder fields
+    static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
+    static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
+    static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
+    static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
+    static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
+
+    // central directory header (CEN) fields
+    static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
+    static final int  CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
+    static final int  CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
+    static final int  CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
+    static final int  CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
+    static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
+    static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
+    static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
+    static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
+    static final int  CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
+    static final int  CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
+    static final int  CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
+    static final int  CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
+    static final int  CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
+    static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
+    static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);}
+
+    /* The END header is followed by a variable length comment of size < 64k. */
+    static final long END_MAXLEN = 0xFFFF + ENDHDR;
+    static final int READBLOCKSZ = 128;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.nio.file.DirectoryStream;
+import java.nio.file.ClosedDirectoryStreamException;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.io.IOException;
+
+/**
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+class ZipDirectoryStream implements DirectoryStream<Path> {
+
+    private final ZipFileSystem zipfs;
+    private final byte[] path;
+    private final DirectoryStream.Filter<? super Path> filter;
+    private volatile boolean isClosed;
+    private volatile Iterator<Path> itr;
+
+    ZipDirectoryStream(ZipPath zipPath,
+                       DirectoryStream.Filter<? super java.nio.file.Path> filter)
+        throws IOException
+    {
+        this.zipfs = zipPath.getFileSystem();
+        this.path = zipPath.getResolvedPath();
+        this.filter = filter;
+        // sanity check
+        if (!zipfs.isDirectory(path))
+            throw new NotDirectoryException(zipPath.toString());
+    }
+
+    @Override
+    public synchronized Iterator<Path> iterator() {
+        if (isClosed)
+            throw new ClosedDirectoryStreamException();
+        if (itr != null)
+            throw new IllegalStateException("Iterator has already been returned");
+
+        try {
+            itr = zipfs.iteratorOf(path, filter);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+        return new Iterator<Path>() {
+            private Path next;
+            @Override
+            public boolean hasNext() {
+                if (isClosed)
+                    return false;
+                return itr.hasNext();
+            }
+
+            @Override
+            public synchronized Path next() {
+                if (isClosed)
+                    throw new NoSuchElementException();
+                return itr.next();
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        isClosed = true;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributeView.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/*
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+class ZipFileAttributeView implements BasicFileAttributeView
+{
+    private static enum AttrID {
+        size,
+        creationTime,
+        lastAccessTime,
+        lastModifiedTime,
+        isDirectory,
+        isRegularFile,
+        isSymbolicLink,
+        isOther,
+        fileKey,
+        compressedSize,
+        crc,
+        method
+    };
+
+    private final ZipPath path;
+    private final boolean isZipView;
+
+    private ZipFileAttributeView(ZipPath path, boolean isZipView) {
+        this.path = path;
+        this.isZipView = isZipView;
+    }
+
+    static <V extends FileAttributeView> V get(ZipPath path, Class<V> type) {
+        if (type == null)
+            throw new NullPointerException();
+        if (type == BasicFileAttributeView.class)
+            return (V)new ZipFileAttributeView(path, false);
+        if (type == ZipFileAttributeView.class)
+            return (V)new ZipFileAttributeView(path, true);
+        return null;
+    }
+
+    static ZipFileAttributeView get(ZipPath path, String type) {
+        if (type == null)
+            throw new NullPointerException();
+        if (type.equals("basic"))
+            return new ZipFileAttributeView(path, false);
+        if (type.equals("zip"))
+            return new ZipFileAttributeView(path, true);
+        return null;
+    }
+
+    @Override
+    public String name() {
+        return isZipView ? "zip" : "basic";
+    }
+
+    public ZipFileAttributes readAttributes() throws IOException
+    {
+        return path.getAttributes();
+    }
+
+    @Override
+    public void setTimes(FileTime lastModifiedTime,
+                         FileTime lastAccessTime,
+                         FileTime createTime)
+        throws IOException
+    {
+        path.setTimes(lastModifiedTime, lastAccessTime, createTime);
+    }
+
+    void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        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);
+            return;
+        } catch (IllegalArgumentException x) {}
+        throw new UnsupportedOperationException("'" + attribute +
+            "' is unknown or read-only attribute");
+    }
+
+    Map<String, Object> readAttributes(String attributes)
+        throws IOException
+    {
+        ZipFileAttributes zfas = readAttributes();
+        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
+        if ("*".equals(attributes)) {
+            for (AttrID id : AttrID.values()) {
+                try {
+                    map.put(id.name(), attribute(id, zfas));
+                } catch (IllegalArgumentException x) {}
+            }
+        } else {
+            String[] as = attributes.split(",");
+            for (String a : as) {
+                try {
+                    map.put(a, attribute(AttrID.valueOf(a), zfas));
+                } catch (IllegalArgumentException x) {}
+            }
+        }
+        return map;
+    }
+
+    Object attribute(AttrID id, ZipFileAttributes zfas) {
+        switch (id) {
+        case size:
+            return zfas.size();
+        case creationTime:
+            return zfas.creationTime();
+        case lastAccessTime:
+            return zfas.lastAccessTime();
+        case lastModifiedTime:
+            return zfas.lastModifiedTime();
+        case isDirectory:
+            return zfas.isDirectory();
+        case isRegularFile:
+            return zfas.isRegularFile();
+        case isSymbolicLink:
+            return zfas.isSymbolicLink();
+        case isOther:
+            return zfas.isOther();
+        case fileKey:
+            return zfas.fileKey();
+        case compressedSize:
+            if (isZipView)
+                return zfas.compressedSize();
+            break;
+        case crc:
+            if (isZipView)
+                return zfas.crc();
+            break;
+        case method:
+            if (isZipView)
+                return zfas.method();
+            break;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileAttributes.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.Arrays;
+import java.util.Formatter;
+import static jdk.nio.zipfs.ZipUtils.*;
+
+/**
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli,Jaya Hangal
+ */
+
+class ZipFileAttributes implements BasicFileAttributes
+{
+    private final ZipFileSystem.Entry e;
+
+    ZipFileAttributes(ZipFileSystem.Entry e) {
+        this.e = e;
+    }
+
+    ///////// basic attributes ///////////
+    @Override
+    public FileTime creationTime() {
+        if (e.ctime != -1)
+            return FileTime.fromMillis(e.ctime);
+        return null;
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return e.isDir();
+    }
+
+    @Override
+    public boolean isOther() {
+        return false;
+    }
+
+    @Override
+    public boolean isRegularFile() {
+        return !e.isDir();
+    }
+
+    @Override
+    public FileTime lastAccessTime() {
+        if (e.atime != -1)
+            return FileTime.fromMillis(e.atime);
+        return null;
+    }
+
+    @Override
+    public FileTime lastModifiedTime() {
+        return FileTime.fromMillis(e.mtime);
+    }
+
+    @Override
+    public long size() {
+        return e.size;
+    }
+
+    @Override
+    public boolean isSymbolicLink() {
+        return false;
+    }
+
+    @Override
+    public Object fileKey() {
+        return null;
+    }
+
+    ///////// zip entry attributes ///////////
+    public long compressedSize() {
+        return e.csize;
+    }
+
+    public long crc() {
+        return e.crc;
+    }
+
+    public int method() {
+        return e.method;
+    }
+
+    public byte[] extra() {
+        if (e.extra != null)
+            return Arrays.copyOf(e.extra, e.extra.length);
+        return null;
+    }
+
+    public byte[] comment() {
+        if (e.comment != null)
+            return Arrays.copyOf(e.comment, e.comment.length);
+        return null;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(1024);
+        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("    crc             : %x%n", crc());
+        fm.format("    method          : %d%n", method());
+        fm.close();
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileStore.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileStoreAttributeView;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.util.Formatter;
+
+/*
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+class ZipFileStore extends FileStore {
+
+    private final ZipFileSystem zfs;
+
+    ZipFileStore(ZipPath zpath) {
+        this.zfs = zpath.getFileSystem();
+    }
+
+    @Override
+    public String name() {
+        return zfs.toString() + "/";
+    }
+
+    @Override
+    public String type() {
+        return "zipfs";
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return zfs.isReadOnly();
+    }
+
+    @Override
+    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        return (type == BasicFileAttributeView.class ||
+                type == ZipFileAttributeView.class);
+    }
+
+    @Override
+    public boolean supportsFileAttributeView(String name) {
+        return name.equals("basic") || name.equals("zip");
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
+        if (type == null)
+            throw new NullPointerException();
+        return (V)null;
+    }
+
+    @Override
+    public long getTotalSpace() throws IOException {
+         return new ZipFileStoreAttributes(this).totalSpace();
+    }
+
+    @Override
+    public long getUsableSpace() throws IOException {
+         return new ZipFileStoreAttributes(this).usableSpace();
+    }
+
+    @Override
+    public long getUnallocatedSpace() throws IOException {
+         return new ZipFileStoreAttributes(this).unallocatedSpace();
+    }
+
+    @Override
+    public Object getAttribute(String attribute) throws IOException {
+         if (attribute.equals("totalSpace"))
+               return getTotalSpace();
+         if (attribute.equals("usableSpace"))
+               return getUsableSpace();
+         if (attribute.equals("unallocatedSpace"))
+               return getUnallocatedSpace();
+         throw new UnsupportedOperationException("does not support the given attribute");
+    }
+
+    private static class ZipFileStoreAttributes {
+        final FileStore fstore;
+        final long size;
+
+        public ZipFileStoreAttributes(ZipFileStore fileStore)
+            throws IOException
+        {
+            Path path = FileSystems.getDefault().getPath(fileStore.name());
+            this.size = Files.size(path);
+            this.fstore = Files.getFileStore(path);
+        }
+
+        public long totalSpace() {
+            return size;
+        }
+
+        public long usableSpace() throws IOException {
+            if (!fstore.isReadOnly())
+                return fstore.getUsableSpace();
+            return 0;
+        }
+
+        public long unallocatedSpace()  throws IOException {
+            if (!fstore.isReadOnly())
+                return fstore.getUnallocatedSpace();
+            return 0;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystem.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,2386 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.Inflater;
+import java.util.zip.Deflater;
+import java.util.zip.InflaterInputStream;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.ZipException;
+import java.util.zip.ZipError;
+import static java.lang.Boolean.*;
+import static jdk.nio.zipfs.ZipConstants.*;
+import static jdk.nio.zipfs.ZipUtils.*;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/**
+ * A FileSystem built on a zip file
+ *
+ * @author Xueming Shen
+ */
+
+class ZipFileSystem extends FileSystem {
+
+    private final ZipFileSystemProvider provider;
+    private final ZipPath defaultdir;
+    private boolean readOnly = false;
+    private final Path zfpath;
+    private final ZipCoder zc;
+
+    // configurable by env map
+    private final String  defaultDir;    // default dir for the file system
+    private final String  nameEncoding;  // default encoding for name/comment
+    private final boolean useTempFile;   // use a temp file for newOS, default
+                                         // is to use BAOS for better performance
+    private final boolean createNew;     // create a new zip if not exists
+    private static final boolean isWindows = AccessController.doPrivileged(
+            (PrivilegedAction<Boolean>) () -> System.getProperty("os.name")
+                                                    .startsWith("Windows"));
+
+    ZipFileSystem(ZipFileSystemProvider provider,
+                  Path zfpath,
+                  Map<String, ?> env)
+        throws IOException
+    {
+        // configurable env setup
+        this.createNew    = "true".equals(env.get("create"));
+        this.nameEncoding = env.containsKey("encoding") ?
+                            (String)env.get("encoding") : "UTF-8";
+        this.useTempFile  = TRUE.equals(env.get("useTempFile"));
+        this.defaultDir   = env.containsKey("default.dir") ?
+                            (String)env.get("default.dir") : "/";
+        if (this.defaultDir.charAt(0) != '/')
+            throw new IllegalArgumentException("default dir should be absolute");
+
+        this.provider = provider;
+        this.zfpath = zfpath;
+        if (Files.notExists(zfpath)) {
+            if (createNew) {
+                try (OutputStream os = Files.newOutputStream(zfpath, CREATE_NEW, WRITE)) {
+                    new END().write(os, 0);
+                }
+            } else {
+                throw new FileSystemNotFoundException(zfpath.toString());
+            }
+        }
+        // sm and existence check
+        zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
+        if (!Files.isWritable(zfpath))
+            this.readOnly = true;
+        this.zc = ZipCoder.get(nameEncoding);
+        this.defaultdir = new ZipPath(this, getBytes(defaultDir));
+        this.ch = Files.newByteChannel(zfpath, READ);
+        this.cen = initCEN();
+    }
+
+    @Override
+    public FileSystemProvider provider() {
+        return provider;
+    }
+
+    @Override
+    public String getSeparator() {
+        return "/";
+    }
+
+    @Override
+    public boolean isOpen() {
+        return isOpen;
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return readOnly;
+    }
+
+    private void checkWritable() throws IOException {
+        if (readOnly)
+            throw new ReadOnlyFileSystemException();
+    }
+
+    @Override
+    public Iterable<Path> getRootDirectories() {
+        ArrayList<Path> pathArr = new ArrayList<>();
+        pathArr.add(new ZipPath(this, new byte[]{'/'}));
+        return pathArr;
+    }
+
+    ZipPath getDefaultDir() {  // package private
+        return defaultdir;
+    }
+
+    @Override
+    public ZipPath 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 new ZipPath(this, getBytes(path));
+    }
+
+    @Override
+    public UserPrincipalLookupService getUserPrincipalLookupService() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WatchService newWatchService() {
+        throw new UnsupportedOperationException();
+    }
+
+    FileStore getFileStore(ZipPath path) {
+        return new ZipFileStore(path);
+    }
+
+    @Override
+    public Iterable<FileStore> getFileStores() {
+        ArrayList<FileStore> list = new ArrayList<>(1);
+        list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'})));
+        return list;
+    }
+
+    private static final Set<String> supportedFileAttributeViews =
+            Collections.unmodifiableSet(
+                new HashSet<String>(Arrays.asList("basic", "zip")));
+
+    @Override
+    public Set<String> supportedFileAttributeViews() {
+        return supportedFileAttributeViews;
+    }
+
+    @Override
+    public String toString() {
+        return zfpath.toString();
+    }
+
+    Path getZipFile() {
+        return zfpath;
+    }
+
+    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.equals(GLOB_SYNTAX)) {
+            expr = toRegexPattern(input);
+        } else {
+            if (syntax.equals(REGEX_SYNTAX)) {
+                expr = input;
+            } else {
+                throw new UnsupportedOperationException("Syntax '" + syntax +
+                    "' not recognized");
+            }
+        }
+        // return matcher
+        final Pattern pattern = Pattern.compile(expr);
+        return new PathMatcher() {
+            @Override
+            public boolean matches(Path path) {
+                return pattern.matcher(path.toString()).matches();
+            }
+        };
+    }
+
+    @Override
+    public void close() throws IOException {
+        beginWrite();
+        try {
+            if (!isOpen)
+                return;
+            isOpen = false;             // set closed
+        } finally {
+            endWrite();
+        }
+        if (!streams.isEmpty()) {       // unlock and close all remaining streams
+            Set<InputStream> copy = new HashSet<>(streams);
+            for (InputStream is: copy)
+                is.close();
+        }
+        beginWrite();                   // lock and sync
+        try {
+            sync();
+            ch.close();                 // close the ch just in case no update
+        } finally {                     // and sync dose not close the ch
+            endWrite();
+        }
+
+        synchronized (inflaters) {
+            for (Inflater inf : inflaters)
+                inf.end();
+        }
+        synchronized (deflaters) {
+            for (Deflater def : deflaters)
+                def.end();
+        }
+
+        IOException ioe = null;
+        synchronized (tmppaths) {
+            for (Path p: tmppaths) {
+                try {
+                    Files.deleteIfExists(p);
+                } catch (IOException x) {
+                    if (ioe == null)
+                        ioe = x;
+                    else
+                        ioe.addSuppressed(x);
+                }
+            }
+        }
+        provider.removeFileSystem(zfpath, this);
+        if (ioe != null)
+           throw ioe;
+    }
+
+    ZipFileAttributes getFileAttributes(byte[] path)
+        throws IOException
+    {
+        Entry e;
+        beginRead();
+        try {
+            ensureOpen();
+            e = getEntry0(path);
+            if (e == null) {
+                IndexNode inode = getInode(path);
+                if (inode == null)
+                    return null;
+                e = new Entry(inode.name);       // pseudo directory
+                e.method = METHOD_STORED;        // STORED for dir
+                e.mtime = e.atime = e.ctime = -1;// -1 for all times
+            }
+        } finally {
+            endRead();
+        }
+        return new ZipFileAttributes(e);
+    }
+
+    void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
+        throws IOException
+    {
+        checkWritable();
+        beginWrite();
+        try {
+            ensureOpen();
+            Entry e = getEntry0(path);    // ensureOpen checked
+            if (e == null)
+                throw new NoSuchFileException(getString(path));
+            if (e.type == Entry.CEN)
+                e.type = Entry.COPY;      // copy e
+            if (mtime != null)
+                e.mtime = mtime.toMillis();
+            if (atime != null)
+                e.atime = atime.toMillis();
+            if (ctime != null)
+                e.ctime = ctime.toMillis();
+            update(e);
+        } finally {
+            endWrite();
+        }
+    }
+
+    boolean exists(byte[] path)
+        throws IOException
+    {
+        beginRead();
+        try {
+            ensureOpen();
+            return getInode(path) != null;
+        } finally {
+            endRead();
+        }
+    }
+
+    boolean isDirectory(byte[] path)
+        throws IOException
+    {
+        beginRead();
+        try {
+            IndexNode n = getInode(path);
+            return n != null && n.isDir();
+        } finally {
+            endRead();
+        }
+    }
+
+    private ZipPath toZipPath(byte[] path) {
+        // make it absolute
+        byte[] p = new byte[path.length + 1];
+        p[0] = '/';
+        System.arraycopy(path, 0, p, 1, path.length);
+        return new ZipPath(this, p);
+    }
+
+    // returns the list of child paths of "path"
+    Iterator<Path> iteratorOf(byte[] path,
+                              DirectoryStream.Filter<? super Path> filter)
+        throws IOException
+    {
+        beginWrite();    // iteration of inodes needs exclusive lock
+        try {
+            ensureOpen();
+            IndexNode inode = getInode(path);
+            if (inode == null)
+                throw new NotDirectoryException(getString(path));
+            List<Path> list = new ArrayList<>();
+            IndexNode child = inode.child;
+            while (child != null) {
+                ZipPath zp = toZipPath(child.name);
+                if (filter == null || filter.accept(zp))
+                    list.add(zp);
+                child = child.sibling;
+            }
+            return list.iterator();
+        } finally {
+            endWrite();
+        }
+    }
+
+    void createDirectory(byte[] dir, FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkWritable();
+        dir = toDirectoryPath(dir);
+        beginWrite();
+        try {
+            ensureOpen();
+            if (dir.length == 0 || exists(dir))  // root dir, or exiting dir
+                throw new FileAlreadyExistsException(getString(dir));
+            checkParents(dir);
+            Entry e = new Entry(dir, Entry.NEW);
+            e.method = METHOD_STORED;            // STORED for dir
+            update(e);
+        } finally {
+            endWrite();
+        }
+    }
+
+    void copyFile(boolean deletesrc, byte[]src, byte[] dst, CopyOption... options)
+        throws IOException
+    {
+        checkWritable();
+        if (Arrays.equals(src, dst))
+            return;    // do nothing, src and dst are the same
+
+        beginWrite();
+        try {
+            ensureOpen();
+            Entry eSrc = getEntry0(src);  // ensureOpen checked
+            if (eSrc == null)
+                throw new NoSuchFileException(getString(src));
+            if (eSrc.isDir()) {    // spec says to create dst dir
+                createDirectory(dst);
+                return;
+            }
+            boolean hasReplace = false;
+            boolean hasCopyAttrs = false;
+            for (CopyOption opt : options) {
+                if (opt == REPLACE_EXISTING)
+                    hasReplace = true;
+                else if (opt == COPY_ATTRIBUTES)
+                    hasCopyAttrs = true;
+            }
+            Entry eDst = getEntry0(dst);
+            if (eDst != null) {
+                if (!hasReplace)
+                    throw new FileAlreadyExistsException(getString(dst));
+            } else {
+                checkParents(dst);
+            }
+            Entry u = new Entry(eSrc, Entry.COPY);    // copy eSrc entry
+            u.name(dst);                              // change name
+            if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
+            {
+                u.type = eSrc.type;    // make it the same type
+                if (deletesrc) {       // if it's a "rename", take the data
+                    u.bytes = eSrc.bytes;
+                    u.file = eSrc.file;
+                } else {               // if it's not "rename", copy the data
+                    if (eSrc.bytes != null)
+                        u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
+                    else if (eSrc.file != null) {
+                        u.file = getTempPathForEntry(null);
+                        Files.copy(eSrc.file, u.file, REPLACE_EXISTING);
+                    }
+                }
+            }
+            if (!hasCopyAttrs)
+                u.mtime = u.atime= u.ctime = System.currentTimeMillis();
+            update(u);
+            if (deletesrc)
+                updateDelete(eSrc);
+        } finally {
+            endWrite();
+        }
+    }
+
+    // Returns an output stream for writing the contents into the specified
+    // entry.
+    OutputStream newOutputStream(byte[] path, OpenOption... options)
+        throws IOException
+    {
+        checkWritable();
+        boolean hasCreateNew = false;
+        boolean hasCreate = false;
+        boolean hasAppend = false;
+        for (OpenOption opt: options) {
+            if (opt == READ)
+                throw new IllegalArgumentException("READ not allowed");
+            if (opt == CREATE_NEW)
+                hasCreateNew = true;
+            if (opt == CREATE)
+                hasCreate = true;
+            if (opt == APPEND)
+                hasAppend = true;
+        }
+        beginRead();                 // only need a readlock, the "update()" will
+        try {                        // try to obtain a writelock when the os is
+            ensureOpen();            // being closed.
+            Entry e = getEntry0(path);
+            if (e != null) {
+                if (e.isDir() || hasCreateNew)
+                    throw new FileAlreadyExistsException(getString(path));
+                if (hasAppend) {
+                    InputStream is = getInputStream(e);
+                    OutputStream os = getOutputStream(new Entry(e, Entry.NEW));
+                    copyStream(is, os);
+                    is.close();
+                    return os;
+                }
+                return getOutputStream(new Entry(e, Entry.NEW));
+            } else {
+                if (!hasCreate && !hasCreateNew)
+                    throw new NoSuchFileException(getString(path));
+                checkParents(path);
+                return getOutputStream(new Entry(path, Entry.NEW));
+            }
+        } finally {
+            endRead();
+        }
+    }
+
+    // Returns an input stream for reading the contents of the specified
+    // file entry.
+    InputStream newInputStream(byte[] path) throws IOException {
+        beginRead();
+        try {
+            ensureOpen();
+            Entry e = getEntry0(path);
+            if (e == null)
+                throw new NoSuchFileException(getString(path));
+            if (e.isDir())
+                throw new FileSystemException(getString(path), "is a directory", null);
+            return getInputStream(e);
+        } finally {
+            endRead();
+        }
+    }
+
+    private 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();
+        }
+    }
+
+    // Returns a Writable/ReadByteChannel for now. Might consdier to use
+    // newFileChannel() instead, which dump the entry data into a regular
+    // file on the default file system and create a FileChannel on top of
+    // it.
+    SeekableByteChannel newByteChannel(byte[] path,
+                                       Set<? extends OpenOption> options,
+                                       FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkOptions(options);
+        if (options.contains(StandardOpenOption.WRITE) ||
+            options.contains(StandardOpenOption.APPEND)) {
+            checkWritable();
+            beginRead();
+            try {
+                final WritableByteChannel wbc = Channels.newChannel(
+                    newOutputStream(path, options.toArray(new OpenOption[0])));
+                long leftover = 0;
+                if (options.contains(StandardOpenOption.APPEND)) {
+                    Entry e = getEntry0(path);
+                    if (e != null && e.size >= 0)
+                        leftover = e.size;
+                }
+                final long offset = leftover;
+                return new SeekableByteChannel() {
+                    long written = offset;
+                    public boolean isOpen() {
+                        return wbc.isOpen();
+                    }
+
+                    public long position() throws IOException {
+                        return written;
+                    }
+
+                    public SeekableByteChannel position(long pos)
+                        throws IOException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public int read(ByteBuffer dst) throws IOException {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public SeekableByteChannel truncate(long size)
+                        throws IOException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public int write(ByteBuffer src) throws IOException {
+                        int n = wbc.write(src);
+                        written += n;
+                        return n;
+                    }
+
+                    public long size() throws IOException {
+                        return written;
+                    }
+
+                    public void close() throws IOException {
+                        wbc.close();
+                    }
+                };
+            } finally {
+                endRead();
+            }
+        } else {
+            beginRead();
+            try {
+                ensureOpen();
+                Entry e = getEntry0(path);
+                if (e == null || e.isDir())
+                    throw new NoSuchFileException(getString(path));
+                final ReadableByteChannel rbc =
+                    Channels.newChannel(getInputStream(e));
+                final long size = e.size;
+                return new SeekableByteChannel() {
+                    long read = 0;
+                    public boolean isOpen() {
+                        return rbc.isOpen();
+                    }
+
+                    public long position() throws IOException {
+                        return read;
+                    }
+
+                    public SeekableByteChannel position(long pos)
+                        throws IOException
+                    {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public int read(ByteBuffer dst) throws IOException {
+                        int n = rbc.read(dst);
+                        if (n > 0) {
+                            read += n;
+                        }
+                        return n;
+                    }
+
+                    public SeekableByteChannel truncate(long size)
+                    throws IOException
+                    {
+                        throw new NonWritableChannelException();
+                    }
+
+                    public int write (ByteBuffer src) throws IOException {
+                        throw new NonWritableChannelException();
+                    }
+
+                    public long size() throws IOException {
+                        return size;
+                    }
+
+                    public void close() throws IOException {
+                        rbc.close();
+                    }
+                };
+            } finally {
+                endRead();
+            }
+        }
+    }
+
+    // Returns a FileChannel of the specified entry.
+    //
+    // This implementation creates a temporary file on the default file system,
+    // copy the entry data into it if the entry exists, and then create a
+    // FileChannel on top of it.
+    FileChannel newFileChannel(byte[] path,
+                               Set<? extends OpenOption> options,
+                               FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkOptions(options);
+        final  boolean forWrite = (options.contains(StandardOpenOption.WRITE) ||
+                                   options.contains(StandardOpenOption.APPEND));
+        beginRead();
+        try {
+            ensureOpen();
+            Entry e = getEntry0(path);
+            if (forWrite) {
+                checkWritable();
+                if (e == null) {
+                if (!options.contains(StandardOpenOption.CREATE_NEW))
+                    throw new NoSuchFileException(getString(path));
+                } else {
+                    if (options.contains(StandardOpenOption.CREATE_NEW))
+                        throw new FileAlreadyExistsException(getString(path));
+                    if (e.isDir())
+                        throw new FileAlreadyExistsException("directory <"
+                            + getString(path) + "> exists");
+                }
+                options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile
+            } else if (e == null || e.isDir()) {
+                throw new NoSuchFileException(getString(path));
+            }
+
+            final boolean isFCH = (e != null && e.type == Entry.FILECH);
+            final Path tmpfile = isFCH ? e.file : getTempPathForEntry(path);
+            final FileChannel fch = tmpfile.getFileSystem()
+                                           .provider()
+                                           .newFileChannel(tmpfile, options, attrs);
+            final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH);
+            if (forWrite) {
+                u.flag = FLAG_DATADESCR;
+                u.method = METHOD_DEFLATED;
+            }
+            // is there a better way to hook into the FileChannel's close method?
+            return new FileChannel() {
+                public int write(ByteBuffer src) throws IOException {
+                    return fch.write(src);
+                }
+                public long write(ByteBuffer[] srcs, int offset, int length)
+                    throws IOException
+                {
+                    return fch.write(srcs, offset, length);
+                }
+                public long position() throws IOException {
+                    return fch.position();
+                }
+                public FileChannel position(long newPosition)
+                    throws IOException
+                {
+                    fch.position(newPosition);
+                    return this;
+                }
+                public long size() throws IOException {
+                    return fch.size();
+                }
+                public FileChannel truncate(long size)
+                    throws IOException
+                {
+                    fch.truncate(size);
+                    return this;
+                }
+                public void force(boolean metaData)
+                    throws IOException
+                {
+                    fch.force(metaData);
+                }
+                public long transferTo(long position, long count,
+                                       WritableByteChannel target)
+                    throws IOException
+                {
+                    return fch.transferTo(position, count, target);
+                }
+                public long transferFrom(ReadableByteChannel src,
+                                         long position, long count)
+                    throws IOException
+                {
+                    return fch.transferFrom(src, position, count);
+                }
+                public int read(ByteBuffer dst) throws IOException {
+                    return fch.read(dst);
+                }
+                public int read(ByteBuffer dst, long position)
+                    throws IOException
+                {
+                    return fch.read(dst, position);
+                }
+                public long read(ByteBuffer[] dsts, int offset, int length)
+                    throws IOException
+                {
+                    return fch.read(dsts, offset, length);
+                }
+                public int write(ByteBuffer src, long position)
+                    throws IOException
+                    {
+                   return fch.write(src, position);
+                }
+                public MappedByteBuffer map(MapMode mode,
+                                            long position, long size)
+                    throws IOException
+                {
+                    throw new UnsupportedOperationException();
+                }
+                public FileLock lock(long position, long size, boolean shared)
+                    throws IOException
+                {
+                    return fch.lock(position, size, shared);
+                }
+                public FileLock tryLock(long position, long size, boolean shared)
+                    throws IOException
+                {
+                    return fch.tryLock(position, size, shared);
+                }
+                protected void implCloseChannel() throws IOException {
+                    fch.close();
+                    if (forWrite) {
+                        u.mtime = System.currentTimeMillis();
+                        u.size = Files.size(u.file);
+
+                        update(u);
+                    } else {
+                        if (!isFCH)    // if this is a new fch for reading
+                            removeTempPathForEntry(tmpfile);
+                    }
+               }
+            };
+        } finally {
+            endRead();
+        }
+    }
+
+    // the outstanding input streams that need to be closed
+    private Set<InputStream> streams =
+        Collections.synchronizedSet(new HashSet<InputStream>());
+
+    // the ex-channel and ex-path that need to close when their outstanding
+    // input streams are all closed by the obtainers.
+    private Set<ExChannelCloser> exChClosers = new HashSet<>();
+
+    private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>());
+    private Path getTempPathForEntry(byte[] path) throws IOException {
+        Path tmpPath = createTempFileInSameDirectoryAs(zfpath);
+        if (path != null) {
+            Entry e = getEntry0(path);
+            if (e != null) {
+                try (InputStream is = newInputStream(path)) {
+                    Files.copy(is, tmpPath, REPLACE_EXISTING);
+                }
+            }
+        }
+        return tmpPath;
+    }
+
+    private void removeTempPathForEntry(Path path) throws IOException {
+        Files.delete(path);
+        tmppaths.remove(path);
+    }
+
+    // check if all parents really exit. ZIP spec does not require
+    // the existence of any "parent directory".
+    private void checkParents(byte[] path) throws IOException {
+        beginRead();
+        try {
+            while ((path = getParent(path)) != null && path.length != 0) {
+                if (!inodes.containsKey(IndexNode.keyOf(path))) {
+                    throw new NoSuchFileException(getString(path));
+                }
+            }
+        } finally {
+            endRead();
+        }
+    }
+
+    private static byte[] ROOTPATH = new byte[0];
+    private static byte[] getParent(byte[] path) {
+        int off = path.length - 1;
+        if (off > 0 && path[off] == '/')  // isDirectory
+            off--;
+        while (off > 0 && path[off] != '/') { off--; }
+        if (off <= 0)
+            return ROOTPATH;
+        return Arrays.copyOf(path, off + 1);
+    }
+
+    private final void beginWrite() {
+        rwlock.writeLock().lock();
+    }
+
+    private final void endWrite() {
+        rwlock.writeLock().unlock();
+    }
+
+    private final void beginRead() {
+        rwlock.readLock().lock();
+    }
+
+    private final void endRead() {
+        rwlock.readLock().unlock();
+    }
+
+    ///////////////////////////////////////////////////////////////////
+
+    private volatile boolean isOpen = true;
+    private final SeekableByteChannel ch; // channel to the zipfile
+    final byte[]  cen;     // CEN & ENDHDR
+    private END  end;
+    private long locpos;   // position of first LOC header (usually 0)
+
+    private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
+
+    // name -> pos (in cen), IndexNode itself can be used as a "key"
+    private LinkedHashMap<IndexNode, IndexNode> inodes;
+
+    final byte[] getBytes(String name) {
+        return zc.getBytes(name);
+    }
+
+    final String getString(byte[] name) {
+        return zc.toString(name);
+    }
+
+    protected void finalize() throws IOException {
+        close();
+    }
+
+    private long getDataPos(Entry e) throws IOException {
+        if (e.locoff == -1) {
+            Entry e2 = getEntry0(e.name);
+            if (e2 == null)
+                throw new ZipException("invalid loc for entry <" + e.name + ">");
+            e.locoff = e2.locoff;
+        }
+        byte[] buf = new byte[LOCHDR];
+        if (readFullyAt(buf, 0, buf.length, e.locoff) != buf.length)
+            throw new ZipException("invalid loc for entry <" + e.name + ">");
+        return locpos + e.locoff + LOCHDR + LOCNAM(buf) + LOCEXT(buf);
+    }
+
+    // Reads len bytes of data from the specified offset into buf.
+    // Returns the total number of bytes read.
+    // Each/every byte read from here (except the cen, which is mapped).
+    final long readFullyAt(byte[] buf, int off, long len, long pos)
+        throws IOException
+    {
+        ByteBuffer bb = ByteBuffer.wrap(buf);
+        bb.position(off);
+        bb.limit((int)(off + len));
+        return readFullyAt(bb, pos);
+    }
+
+    private final long readFullyAt(ByteBuffer bb, long pos)
+        throws IOException
+    {
+        synchronized(ch) {
+            return ch.position(pos).read(bb);
+        }
+    }
+
+    // Searches for end of central directory (END) header. The contents of
+    // the END header will be read and placed in endbuf. Returns the file
+    // position of the END header, otherwise returns -1 if the END header
+    // was not found or an error occurred.
+    private END findEND() throws IOException
+    {
+        byte[] buf = new byte[READBLOCKSZ];
+        long ziplen = ch.size();
+        long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
+        long minPos = minHDR - (buf.length - ENDHDR);
+
+        for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR))
+        {
+            int off = 0;
+            if (pos < 0) {
+                // Pretend there are some NUL bytes before start of file
+                off = (int)-pos;
+                Arrays.fill(buf, 0, off, (byte)0);
+            }
+            int len = buf.length - off;
+            if (readFullyAt(buf, off, len, pos + off) != len)
+                zerror("zip END header not found");
+
+            // Now scan the block backwards for END header signature
+            for (int i = buf.length - ENDHDR; i >= 0; i--) {
+                if (buf[i+0] == (byte)'P'    &&
+                    buf[i+1] == (byte)'K'    &&
+                    buf[i+2] == (byte)'\005' &&
+                    buf[i+3] == (byte)'\006' &&
+                    (pos + i + ENDHDR + ENDCOM(buf, i) == ziplen)) {
+                    // Found END header
+                    buf = Arrays.copyOfRange(buf, i, i + ENDHDR);
+                    END end = new END();
+                    end.endsub = ENDSUB(buf);
+                    end.centot = ENDTOT(buf);
+                    end.cenlen = ENDSIZ(buf);
+                    end.cenoff = ENDOFF(buf);
+                    end.comlen = ENDCOM(buf);
+                    end.endpos = pos + i;
+                    if (end.cenlen == ZIP64_MINVAL ||
+                        end.cenoff == ZIP64_MINVAL ||
+                        end.centot == ZIP64_MINVAL32)
+                    {
+                        // need to find the zip64 end;
+                        byte[] loc64 = new byte[ZIP64_LOCHDR];
+                        if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
+                            != loc64.length) {
+                            return end;
+                        }
+                        long end64pos = ZIP64_LOCOFF(loc64);
+                        byte[] end64buf = new byte[ZIP64_ENDHDR];
+                        if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
+                            != end64buf.length) {
+                            return end;
+                        }
+                        // end64 found, re-calcualte everything.
+                        end.cenlen = ZIP64_ENDSIZ(end64buf);
+                        end.cenoff = ZIP64_ENDOFF(end64buf);
+                        end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
+                        end.endpos = end64pos;
+                    }
+                    return end;
+                }
+            }
+        }
+        zerror("zip END header not found");
+        return null; //make compiler happy
+    }
+
+    // Reads zip file central directory. Returns the file position of first
+    // CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
+    // then the error was a zip format error and zip->msg has the error text.
+    // Always pass in -1 for knownTotal; it's used for a recursive call.
+    private byte[] initCEN() throws IOException {
+        end = findEND();
+        if (end.endpos == 0) {
+            inodes = new LinkedHashMap<>(10);
+            locpos = 0;
+            buildNodeTree();
+            return null;         // only END header present
+        }
+        if (end.cenlen > end.endpos)
+            zerror("invalid END header (bad central directory size)");
+        long cenpos = end.endpos - end.cenlen;     // position of CEN table
+
+        // Get position of first local file (LOC) header, taking into
+        // account that there may be a stub prefixed to the zip file.
+        locpos = cenpos - end.cenoff;
+        if (locpos < 0)
+            zerror("invalid END header (bad central directory offset)");
+
+        // read in the CEN and END
+        byte[] cen = new byte[(int)(end.cenlen + ENDHDR)];
+        if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
+            zerror("read CEN tables failed");
+        }
+        // Iterate through the entries in the central directory
+        inodes = new LinkedHashMap<>(end.centot + 1);
+        int pos = 0;
+        int limit = cen.length - ENDHDR;
+        while (pos < limit) {
+            if (CENSIG(cen, pos) != CENSIG)
+                zerror("invalid CEN header (bad signature)");
+            int method = CENHOW(cen, pos);
+            int nlen   = CENNAM(cen, pos);
+            int elen   = CENEXT(cen, pos);
+            int clen   = CENCOM(cen, pos);
+            if ((CENFLG(cen, pos) & 1) != 0)
+                zerror("invalid CEN header (encrypted entry)");
+            if (method != METHOD_STORED && method != METHOD_DEFLATED)
+                zerror("invalid CEN header (unsupported compression method: " + method + ")");
+            if (pos + CENHDR + nlen > limit)
+                zerror("invalid CEN header (bad header size)");
+            byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen);
+            IndexNode inode = new IndexNode(name, pos);
+            inodes.put(inode, inode);
+            // skip ext and comment
+            pos += (CENHDR + nlen + elen + clen);
+        }
+        if (pos + ENDHDR != cen.length) {
+            zerror("invalid CEN header (bad header size)");
+        }
+        buildNodeTree();
+        return cen;
+    }
+
+    private void ensureOpen() throws IOException {
+        if (!isOpen)
+            throw new ClosedFileSystemException();
+    }
+
+    // Creates a new empty temporary file in the same directory as the
+    // specified file.  A variant of Files.createTempFile.
+    private Path createTempFileInSameDirectoryAs(Path path)
+        throws IOException
+    {
+        Path parent = path.toAbsolutePath().getParent();
+        Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
+        Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
+        tmppaths.add(tmpPath);
+        return tmpPath;
+    }
+
+    ////////////////////update & sync //////////////////////////////////////
+
+    private boolean hasUpdate = false;
+
+    // shared key. consumer guarantees the "writeLock" before use it.
+    private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
+
+    private void updateDelete(IndexNode inode) {
+        beginWrite();
+        try {
+            removeFromTree(inode);
+            inodes.remove(inode);
+            hasUpdate = true;
+        } finally {
+             endWrite();
+        }
+    }
+
+    private void update(Entry e) {
+        beginWrite();
+        try {
+            IndexNode old = inodes.put(e, e);
+            if (old != null) {
+                removeFromTree(old);
+            }
+            if (e.type == Entry.NEW || e.type == Entry.FILECH || e.type == Entry.COPY) {
+                IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
+                e.sibling = parent.child;
+                parent.child = e;
+            }
+            hasUpdate = true;
+        } finally {
+            endWrite();
+        }
+    }
+
+    // copy over the whole LOC entry (header if necessary, data and ext) from
+    // old zip to the new one.
+    private long copyLOCEntry(Entry e, boolean updateHeader,
+                              OutputStream os,
+                              long written, byte[] buf)
+        throws IOException
+    {
+        long locoff = e.locoff;  // where to read
+        e.locoff = written;      // update the e.locoff with new value
+
+        // calculate the size need to write out
+        long size = 0;
+        //  if there is A ext
+        if ((e.flag & FLAG_DATADESCR) != 0) {
+            if (e.size >= ZIP64_MINVAL || e.csize >= ZIP64_MINVAL)
+                size = 24;
+            else
+                size = 16;
+        }
+        // read loc, use the original loc.elen/nlen
+        if (readFullyAt(buf, 0, LOCHDR , locoff) != LOCHDR)
+            throw new ZipException("loc: reading failed");
+        if (updateHeader) {
+            locoff += LOCHDR + LOCNAM(buf) + LOCEXT(buf);  // skip header
+            size += e.csize;
+            written = e.writeLOC(os) + size;
+        } else {
+            os.write(buf, 0, LOCHDR);    // write out the loc header
+            locoff += LOCHDR;
+            // use e.csize,  LOCSIZ(buf) is zero if FLAG_DATADESCR is on
+            // size += LOCNAM(buf) + LOCEXT(buf) + LOCSIZ(buf);
+            size += LOCNAM(buf) + LOCEXT(buf) + e.csize;
+            written = LOCHDR + size;
+        }
+        int n;
+        while (size > 0 &&
+            (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
+        {
+            if (size < n)
+                n = (int)size;
+            os.write(buf, 0, n);
+            size -= n;
+            locoff += n;
+        }
+        return written;
+    }
+
+    // sync the zip file system, if there is any udpate
+    private void sync() throws IOException {
+        //System.out.printf("->sync(%s) starting....!%n", toString());
+        // check ex-closer
+        if (!exChClosers.isEmpty()) {
+            for (ExChannelCloser ecc : exChClosers) {
+                if (ecc.streams.isEmpty()) {
+                    ecc.ch.close();
+                    Files.delete(ecc.path);
+                    exChClosers.remove(ecc);
+                }
+            }
+        }
+        if (!hasUpdate)
+            return;
+        Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
+        try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
+        {
+            ArrayList<Entry> elist = new ArrayList<>(inodes.size());
+            long written = 0;
+            byte[] buf = new byte[8192];
+            Entry e = null;
+
+            // write loc
+            for (IndexNode inode : inodes.values()) {
+                if (inode instanceof Entry) {    // an updated inode
+                    e = (Entry)inode;
+                    try {
+                        if (e.type == Entry.COPY) {
+                            // entry copy: the only thing changed is the "name"
+                            // and "nlen" in LOC header, so we udpate/rewrite the
+                            // LOC in new file and simply copy the rest (data and
+                            // ext) without enflating/deflating from the old zip
+                            // file LOC entry.
+                            written += copyLOCEntry(e, true, os, written, buf);
+                        } else {                          // NEW, FILECH or CEN
+                            e.locoff = written;
+                            written += e.writeLOC(os);    // write loc header
+                            if (e.bytes != null) {        // in-memory, deflated
+                                os.write(e.bytes);        // already
+                                written += e.bytes.length;
+                            } else if (e.file != null) {  // tmp file
+                                try (InputStream is = Files.newInputStream(e.file)) {
+                                    int n;
+                                    if (e.type == Entry.NEW) {  // deflated already
+                                        while ((n = is.read(buf)) != -1) {
+                                            os.write(buf, 0, n);
+                                            written += n;
+                                        }
+                                    } else if (e.type == Entry.FILECH) {
+                                        // the data are not deflated, use ZEOS
+                                        try (OutputStream os2 = new EntryOutputStream(e, os)) {
+                                            while ((n = is.read(buf)) != -1) {
+                                                os2.write(buf, 0, n);
+                                            }
+                                        }
+                                        written += e.csize;
+                                        if ((e.flag & FLAG_DATADESCR) != 0)
+                                            written += e.writeEXT(os);
+                                    }
+                                }
+                                Files.delete(e.file);
+                                tmppaths.remove(e.file);
+                            } else {
+                                // dir, 0-length data
+                            }
+                        }
+                        elist.add(e);
+                    } catch (IOException x) {
+                        x.printStackTrace();    // skip any in-accurate entry
+                    }
+                } else {                        // unchanged inode
+                    if (inode.pos == -1) {
+                        continue;               // pseudo directory node
+                    }
+                    e = Entry.readCEN(this, inode.pos);
+                    try {
+                        written += copyLOCEntry(e, false, os, written, buf);
+                        elist.add(e);
+                    } catch (IOException x) {
+                        x.printStackTrace();    // skip any wrong entry
+                    }
+                }
+            }
+
+            // now write back the cen and end table
+            end.cenoff = written;
+            for (Entry entry : elist) {
+                written += entry.writeCEN(os);
+            }
+            end.centot = elist.size();
+            end.cenlen = written - end.cenoff;
+            end.write(os, written);
+        }
+        if (!streams.isEmpty()) {
+            //
+            // TBD: ExChannelCloser should not be necessary if we only
+            // sync when being closed, all streams should have been
+            // closed already. Keep the logic here for now.
+            //
+            // There are outstanding input streams open on existing "ch",
+            // so, don't close the "cha" and delete the "file for now, let
+            // the "ex-channel-closer" to handle them
+            ExChannelCloser ecc = new ExChannelCloser(
+                                      createTempFileInSameDirectoryAs(zfpath),
+                                      ch,
+                                      streams);
+            Files.move(zfpath, ecc.path, REPLACE_EXISTING);
+            exChClosers.add(ecc);
+            streams = Collections.synchronizedSet(new HashSet<InputStream>());
+        } else {
+            ch.close();
+            Files.delete(zfpath);
+        }
+
+        Files.move(tmpFile, zfpath, REPLACE_EXISTING);
+        hasUpdate = false;    // clear
+        /*
+        if (isOpen) {
+            ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen"
+            cen = initCEN();
+        }
+         */
+        //System.out.printf("->sync(%s) done!%n", toString());
+    }
+
+    private IndexNode getInode(byte[] path) {
+        if (path == null)
+            throw new NullPointerException("path");
+        IndexNode key = IndexNode.keyOf(path);
+        IndexNode inode = inodes.get(key);
+        if (inode == null &&
+            (path.length == 0 || path[path.length -1] != '/')) {
+            // if does not ends with a slash
+            path = Arrays.copyOf(path, path.length + 1);
+            path[path.length - 1] = '/';
+            inode = inodes.get(key.as(path));
+        }
+        return inode;
+    }
+
+    private Entry getEntry0(byte[] path) throws IOException {
+        IndexNode inode = getInode(path);
+        if (inode instanceof Entry)
+            return (Entry)inode;
+        if (inode == null || inode.pos == -1)
+            return null;
+        return Entry.readCEN(this, inode.pos);
+    }
+
+    public void deleteFile(byte[] path, boolean failIfNotExists)
+        throws IOException
+    {
+        checkWritable();
+
+        IndexNode inode = getInode(path);
+        if (inode == null) {
+            if (path != null && path.length == 0)
+                throw new ZipException("root directory </> can't not be delete");
+            if (failIfNotExists)
+                throw new NoSuchFileException(getString(path));
+        } else {
+            if (inode.isDir() && inode.child != null)
+                throw new DirectoryNotEmptyException(getString(path));
+            updateDelete(inode);
+        }
+    }
+
+    private static void copyStream(InputStream is, OutputStream os)
+        throws IOException
+    {
+        byte[] copyBuf = new byte[8192];
+        int n;
+        while ((n = is.read(copyBuf)) != -1) {
+            os.write(copyBuf, 0, n);
+        }
+    }
+
+    // Returns an out stream for either
+    // (1) writing the contents of a new entry, if the entry exits, or
+    // (2) updating/replacing the contents of the specified existing entry.
+    private OutputStream getOutputStream(Entry e) throws IOException {
+
+        if (e.mtime == -1)
+            e.mtime = System.currentTimeMillis();
+        if (e.method == -1)
+            e.method = METHOD_DEFLATED;  // TBD:  use default method
+        // store size, compressed size, and crc-32 in LOC header
+        e.flag = 0;
+        if (zc.isUTF8())
+            e.flag |= FLAG_EFS;
+        OutputStream os;
+        if (useTempFile) {
+            e.file = getTempPathForEntry(null);
+            os = Files.newOutputStream(e.file, WRITE);
+        } else {
+            os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
+        }
+        return new EntryOutputStream(e, os);
+    }
+
+    private InputStream getInputStream(Entry e)
+        throws IOException
+    {
+        InputStream eis = null;
+
+        if (e.type == Entry.NEW) {
+            if (e.bytes != null)
+                eis = new ByteArrayInputStream(e.bytes);
+            else if (e.file != null)
+                eis = Files.newInputStream(e.file);
+            else
+                throw new ZipException("update entry data is missing");
+        } else if (e.type == Entry.FILECH) {
+            // FILECH result is un-compressed.
+            eis = Files.newInputStream(e.file);
+            // TBD: wrap to hook close()
+            // streams.add(eis);
+            return eis;
+        } else {  // untouced  CEN or COPY
+            eis = new EntryInputStream(e, ch);
+        }
+        if (e.method == METHOD_DEFLATED) {
+            // MORE: Compute good size for inflater stream:
+            long bufSize = e.size + 2; // Inflater likes a bit of slack
+            if (bufSize > 65536)
+                bufSize = 8192;
+            final long size = e.size;
+            eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) {
+
+                private boolean isClosed = false;
+                public void close() throws IOException {
+                    if (!isClosed) {
+                        releaseInflater(inf);
+                        this.in.close();
+                        isClosed = true;
+                        streams.remove(this);
+                    }
+                }
+                // Override fill() method to provide an extra "dummy" byte
+                // at the end of the input stream. This is required when
+                // using the "nowrap" Inflater option. (it appears the new
+                // zlib in 7 does not need it, but keep it for now)
+                protected void fill() throws IOException {
+                    if (eof) {
+                        throw new EOFException(
+                            "Unexpected end of ZLIB input stream");
+                    }
+                    len = this.in.read(buf, 0, buf.length);
+                    if (len == -1) {
+                        buf[0] = 0;
+                        len = 1;
+                        eof = true;
+                    }
+                    inf.setInput(buf, 0, len);
+                }
+                private boolean eof;
+
+                public int available() throws IOException {
+                    if (isClosed)
+                        return 0;
+                    long avail = size - inf.getBytesWritten();
+                    return avail > (long) Integer.MAX_VALUE ?
+                        Integer.MAX_VALUE : (int) avail;
+                }
+            };
+        } else if (e.method == METHOD_STORED) {
+            // TBD: wrap/ it does not seem necessary
+        } else {
+            throw new ZipException("invalid compression method");
+        }
+        streams.add(eis);
+        return eis;
+    }
+
+    // Inner class implementing the input stream used to read
+    // a (possibly compressed) zip file entry.
+    private class EntryInputStream extends InputStream {
+        private final SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might
+                                          // point to a new channel after sync()
+        private   long pos;               // current position within entry data
+        protected long rem;               // number of remaining bytes within entry
+        protected final long size;        // uncompressed size of this entry
+
+        EntryInputStream(Entry e, SeekableByteChannel zfch)
+            throws IOException
+        {
+            this.zfch = zfch;
+            rem = e.csize;
+            size = e.size;
+            pos = getDataPos(e);
+        }
+        public int read(byte b[], int off, int len) throws IOException {
+            ensureOpen();
+            if (rem == 0) {
+                return -1;
+            }
+            if (len <= 0) {
+                return 0;
+            }
+            if (len > rem) {
+                len = (int) rem;
+            }
+            // readFullyAt()
+            long n = 0;
+            ByteBuffer bb = ByteBuffer.wrap(b);
+            bb.position(off);
+            bb.limit(off + len);
+            synchronized(zfch) {
+                n = zfch.position(pos).read(bb);
+            }
+            if (n > 0) {
+                pos += n;
+                rem -= n;
+            }
+            if (rem == 0) {
+                close();
+            }
+            return (int)n;
+        }
+        public int read() throws IOException {
+            byte[] b = new byte[1];
+            if (read(b, 0, 1) == 1) {
+                return b[0] & 0xff;
+            } else {
+                return -1;
+            }
+        }
+        public long skip(long n) throws IOException {
+            ensureOpen();
+            if (n > rem)
+                n = rem;
+            pos += n;
+            rem -= n;
+            if (rem == 0) {
+                close();
+            }
+            return n;
+        }
+        public int available() {
+            return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem;
+        }
+        public long size() {
+            return size;
+        }
+        public void close() {
+            rem = 0;
+            streams.remove(this);
+        }
+    }
+
+    class EntryOutputStream extends DeflaterOutputStream
+    {
+        private CRC32 crc;
+        private Entry e;
+        private long written;
+
+        EntryOutputStream(Entry e, OutputStream os)
+            throws IOException
+        {
+            super(os, getDeflater());
+            if (e == null)
+                throw new NullPointerException("Zip entry is null");
+            this.e = e;
+            crc = new CRC32();
+        }
+
+        @Override
+        public void write(byte b[], int off, int len) throws IOException {
+            if (e.type != Entry.FILECH)    // only from sync
+                ensureOpen();
+            if (off < 0 || len < 0 || off > b.length - len) {
+                throw new IndexOutOfBoundsException();
+            } else if (len == 0) {
+                return;
+            }
+            switch (e.method) {
+            case METHOD_DEFLATED:
+                super.write(b, off, len);
+                break;
+            case METHOD_STORED:
+                written += len;
+                out.write(b, off, len);
+                break;
+            default:
+                throw new ZipException("invalid compression method");
+            }
+            crc.update(b, off, len);
+        }
+
+        @Override
+        public void close() throws IOException {
+            // TBD ensureOpen();
+            switch (e.method) {
+            case METHOD_DEFLATED:
+                finish();
+                e.size  = def.getBytesRead();
+                e.csize = def.getBytesWritten();
+                e.crc = crc.getValue();
+                break;
+            case METHOD_STORED:
+                // we already know that both e.size and e.csize are the same
+                e.size = e.csize = written;
+                e.crc = crc.getValue();
+                break;
+            default:
+                throw new ZipException("invalid compression method");
+            }
+            //crc.reset();
+            if (out instanceof ByteArrayOutputStream)
+                e.bytes = ((ByteArrayOutputStream)out).toByteArray();
+
+            if (e.type == Entry.FILECH) {
+                releaseDeflater(def);
+                return;
+            }
+            super.close();
+            releaseDeflater(def);
+            update(e);
+        }
+    }
+
+    static void zerror(String msg) {
+        throw new ZipError(msg);
+    }
+
+    // Maxmum number of de/inflater we cache
+    private final int MAX_FLATER = 20;
+    // List of available Inflater objects for decompression
+    private final List<Inflater> inflaters = new ArrayList<>();
+
+    // Gets an inflater from the list of available inflaters or allocates
+    // a new one.
+    private Inflater getInflater() {
+        synchronized (inflaters) {
+            int size = inflaters.size();
+            if (size > 0) {
+                Inflater inf = inflaters.remove(size - 1);
+                return inf;
+            } else {
+                return new Inflater(true);
+            }
+        }
+    }
+
+    // Releases the specified inflater to the list of available inflaters.
+    private void releaseInflater(Inflater inf) {
+        synchronized (inflaters) {
+            if (inflaters.size() < MAX_FLATER) {
+                inf.reset();
+                inflaters.add(inf);
+            } else {
+                inf.end();
+            }
+        }
+    }
+
+    // List of available Deflater objects for compression
+    private final List<Deflater> deflaters = new ArrayList<>();
+
+    // Gets an deflater from the list of available deflaters or allocates
+    // a new one.
+    private Deflater getDeflater() {
+        synchronized (deflaters) {
+            int size = deflaters.size();
+            if (size > 0) {
+                Deflater def = deflaters.remove(size - 1);
+                return def;
+            } else {
+                return new Deflater(Deflater.DEFAULT_COMPRESSION, true);
+            }
+        }
+    }
+
+    // Releases the specified inflater to the list of available inflaters.
+    private void releaseDeflater(Deflater def) {
+        synchronized (deflaters) {
+            if (inflaters.size() < MAX_FLATER) {
+               def.reset();
+               deflaters.add(def);
+            } else {
+               def.end();
+            }
+        }
+    }
+
+    // End of central directory record
+    static class END {
+        int  disknum;
+        int  sdisknum;
+        int  endsub;     // endsub
+        int  centot;     // 4 bytes
+        long cenlen;     // 4 bytes
+        long cenoff;     // 4 bytes
+        int  comlen;     // comment length
+        byte[] comment;
+
+        /* members of Zip64 end of central directory locator */
+        int diskNum;
+        long endpos;
+        int disktot;
+
+        void write(OutputStream os, long offset) throws IOException {
+            boolean hasZip64 = false;
+            long xlen = cenlen;
+            long xoff = cenoff;
+            if (xlen >= ZIP64_MINVAL) {
+                xlen = ZIP64_MINVAL;
+                hasZip64 = true;
+            }
+            if (xoff >= ZIP64_MINVAL) {
+                xoff = ZIP64_MINVAL;
+                hasZip64 = true;
+            }
+            int count = centot;
+            if (count >= ZIP64_MINVAL32) {
+                count = ZIP64_MINVAL32;
+                hasZip64 = true;
+            }
+            if (hasZip64) {
+                long off64 = offset;
+                //zip64 end of central directory record
+                writeInt(os, ZIP64_ENDSIG);       // zip64 END record signature
+                writeLong(os, ZIP64_ENDHDR - 12); // size of zip64 end
+                writeShort(os, 45);               // version made by
+                writeShort(os, 45);               // version needed to extract
+                writeInt(os, 0);                  // number of this disk
+                writeInt(os, 0);                  // central directory start disk
+                writeLong(os, centot);            // number of directory entires on disk
+                writeLong(os, centot);            // number of directory entires
+                writeLong(os, cenlen);            // length of central directory
+                writeLong(os, cenoff);            // offset of central directory
+
+                //zip64 end of central directory locator
+                writeInt(os, ZIP64_LOCSIG);       // zip64 END locator signature
+                writeInt(os, 0);                  // zip64 END start disk
+                writeLong(os, off64);             // offset of zip64 END
+                writeInt(os, 1);                  // total number of disks (?)
+            }
+            writeInt(os, ENDSIG);                 // END record signature
+            writeShort(os, 0);                    // number of this disk
+            writeShort(os, 0);                    // central directory start disk
+            writeShort(os, count);                // number of directory entries on disk
+            writeShort(os, count);                // total number of directory entries
+            writeInt(os, xlen);                   // length of central directory
+            writeInt(os, xoff);                   // offset of central directory
+            if (comment != null) {            // zip file comment
+                writeShort(os, comment.length);
+                writeBytes(os, comment);
+            } else {
+                writeShort(os, 0);
+            }
+        }
+    }
+
+    // Internal node that links a "name" to its pos in cen table.
+    // The node itself can be used as a "key" to lookup itself in
+    // the HashMap inodes.
+    static class IndexNode {
+        byte[] name;
+        int    hashcode;  // node is hashable/hashed by its name
+        int    pos = -1;  // position in cen table, -1 menas the
+                          // entry does not exists in zip file
+        IndexNode(byte[] name, int pos) {
+            name(name);
+            this.pos = pos;
+        }
+
+        final static IndexNode keyOf(byte[] name) { // get a lookup key;
+            return new IndexNode(name, -1);
+        }
+
+        final void name(byte[] name) {
+            this.name = name;
+            this.hashcode = Arrays.hashCode(name);
+        }
+
+        final IndexNode as(byte[] name) {           // reuse the node, mostly
+            name(name);                             // as a lookup "key"
+            return this;
+        }
+
+        boolean isDir() {
+            return name != null &&
+                   (name.length == 0 || name[name.length - 1] == '/');
+        }
+
+        public boolean equals(Object other) {
+            if (!(other instanceof IndexNode)) {
+                return false;
+            }
+            return Arrays.equals(name, ((IndexNode)other).name);
+        }
+
+        public int hashCode() {
+            return hashcode;
+        }
+
+        IndexNode() {}
+        IndexNode sibling;
+        IndexNode child;  // 1st child
+    }
+
+    static class Entry extends IndexNode {
+
+        static final int CEN    = 1;    // entry read from cen
+        static final int NEW    = 2;    // updated contents in bytes or file
+        static final int FILECH = 3;    // fch update in "file"
+        static final int COPY   = 4;    // copy of a CEN entry
+
+
+        byte[] bytes;      // updated content bytes
+        Path   file;       // use tmp file to store bytes;
+        int    type = CEN; // default is the entry read from cen
+
+        // entry attributes
+        int    version;
+        int    flag;
+        int    method = -1;    // compression method
+        long   mtime  = -1;    // last modification time (in DOS time)
+        long   atime  = -1;    // last access time
+        long   ctime  = -1;    // create time
+        long   crc    = -1;    // crc-32 of entry data
+        long   csize  = -1;    // compressed size of entry data
+        long   size   = -1;    // uncompressed size of entry data
+        byte[] extra;
+
+        // cen
+        int    versionMade;
+        int    disk;
+        int    attrs;
+        long   attrsEx;
+        long   locoff;
+        byte[] comment;
+
+        Entry() {}
+
+        Entry(byte[] name) {
+            name(name);
+            this.mtime  = this.ctime = this.atime = System.currentTimeMillis();
+            this.crc    = 0;
+            this.size   = 0;
+            this.csize  = 0;
+            this.method = METHOD_DEFLATED;
+        }
+
+        Entry(byte[] name, int type) {
+            this(name);
+            this.type = type;
+        }
+
+        Entry (Entry e, int type) {
+            name(e.name);
+            this.version   = e.version;
+            this.ctime     = e.ctime;
+            this.atime     = e.atime;
+            this.mtime     = e.mtime;
+            this.crc       = e.crc;
+            this.size      = e.size;
+            this.csize     = e.csize;
+            this.method    = e.method;
+            this.extra     = e.extra;
+            this.versionMade = e.versionMade;
+            this.disk      = e.disk;
+            this.attrs     = e.attrs;
+            this.attrsEx   = e.attrsEx;
+            this.locoff    = e.locoff;
+            this.comment   = e.comment;
+            this.type      = type;
+        }
+
+        Entry (byte[] name, Path file, int type) {
+            this(name, type);
+            this.file = file;
+            this.method = METHOD_STORED;
+        }
+
+        int version() throws ZipException {
+            if (method == METHOD_DEFLATED)
+                return 20;
+            else if (method == METHOD_STORED)
+                return 10;
+            throw new ZipException("unsupported compression method");
+        }
+
+        ///////////////////// CEN //////////////////////
+        static Entry readCEN(ZipFileSystem zipfs, int pos)
+            throws IOException
+        {
+            return new Entry().cen(zipfs, pos);
+        }
+
+        private Entry cen(ZipFileSystem zipfs, int pos)
+            throws IOException
+        {
+            byte[] cen = zipfs.cen;
+            if (CENSIG(cen, pos) != CENSIG)
+                zerror("invalid CEN header (bad signature)");
+            versionMade = CENVEM(cen, pos);
+            version     = CENVER(cen, pos);
+            flag        = CENFLG(cen, pos);
+            method      = CENHOW(cen, pos);
+            mtime       = dosToJavaTime(CENTIM(cen, pos));
+            crc         = CENCRC(cen, pos);
+            csize       = CENSIZ(cen, pos);
+            size        = CENLEN(cen, pos);
+            int nlen    = CENNAM(cen, pos);
+            int elen    = CENEXT(cen, pos);
+            int clen    = CENCOM(cen, pos);
+            disk        = CENDSK(cen, pos);
+            attrs       = CENATT(cen, pos);
+            attrsEx     = CENATX(cen, pos);
+            locoff      = CENOFF(cen, pos);
+
+            pos += CENHDR;
+            name(Arrays.copyOfRange(cen, pos, pos + nlen));
+
+            pos += nlen;
+            if (elen > 0) {
+                extra = Arrays.copyOfRange(cen, pos, pos + elen);
+                pos += elen;
+                readExtra(zipfs);
+            }
+            if (clen > 0) {
+                comment = Arrays.copyOfRange(cen, pos, pos + clen);
+            }
+            return this;
+        }
+
+        int writeCEN(OutputStream os) throws IOException
+        {
+            int written  = CENHDR;
+            int version0 = version();
+            long csize0  = csize;
+            long size0   = size;
+            long locoff0 = locoff;
+            int elen64   = 0;                // extra for ZIP64
+            int elenNTFS = 0;                // extra for NTFS (a/c/mtime)
+            int elenEXTT = 0;                // extra for Extended Timestamp
+            boolean foundExtraTime = false;  // if time stamp NTFS, EXTT present
+
+            // confirm size/length
+            int nlen = (name != null) ? name.length : 0;
+            int elen = (extra != null) ? extra.length : 0;
+            int eoff = 0;
+            int clen = (comment != null) ? comment.length : 0;
+            if (csize >= ZIP64_MINVAL) {
+                csize0 = ZIP64_MINVAL;
+                elen64 += 8;                 // csize(8)
+            }
+            if (size >= ZIP64_MINVAL) {
+                size0 = ZIP64_MINVAL;        // size(8)
+                elen64 += 8;
+            }
+            if (locoff >= ZIP64_MINVAL) {
+                locoff0 = ZIP64_MINVAL;
+                elen64 += 8;                 // offset(8)
+            }
+            if (elen64 != 0) {
+                elen64 += 4;                 // header and data sz 4 bytes
+            }
+            while (eoff + 4 < elen) {
+                int tag = SH(extra, eoff);
+                int sz = SH(extra, eoff + 2);
+                if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
+                    foundExtraTime = true;
+                }
+                eoff += (4 + sz);
+            }
+            if (!foundExtraTime) {
+                if (isWindows) {             // use NTFS
+                    elenNTFS = 36;           // total 36 bytes
+                } else {                     // Extended Timestamp otherwise
+                    elenEXTT = 9;            // only mtime in cen
+                }
+            }
+            writeInt(os, CENSIG);            // CEN header signature
+            if (elen64 != 0) {
+                writeShort(os, 45);          // ver 4.5 for zip64
+                writeShort(os, 45);
+            } else {
+                writeShort(os, version0);    // version made by
+                writeShort(os, version0);    // version needed to extract
+            }
+            writeShort(os, flag);            // general purpose bit flag
+            writeShort(os, method);          // compression method
+                                             // last modification time
+            writeInt(os, (int)javaToDosTime(mtime));
+            writeInt(os, crc);               // crc-32
+            writeInt(os, csize0);            // compressed size
+            writeInt(os, size0);             // uncompressed size
+            writeShort(os, name.length);
+            writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
+
+            if (comment != null) {
+                writeShort(os, Math.min(clen, 0xffff));
+            } else {
+                writeShort(os, 0);
+            }
+            writeShort(os, 0);              // starting disk number
+            writeShort(os, 0);              // internal file attributes (unused)
+            writeInt(os, 0);                // external file attributes (unused)
+            writeInt(os, locoff0);          // relative offset of local header
+            writeBytes(os, name);
+            if (elen64 != 0) {
+                writeShort(os, EXTID_ZIP64);// Zip64 extra
+                writeShort(os, elen64 - 4); // size of "this" extra block
+                if (size0 == ZIP64_MINVAL)
+                    writeLong(os, size);
+                if (csize0 == ZIP64_MINVAL)
+                    writeLong(os, csize);
+                if (locoff0 == ZIP64_MINVAL)
+                    writeLong(os, locoff);
+            }
+            if (elenNTFS != 0) {
+                writeShort(os, EXTID_NTFS);
+                writeShort(os, elenNTFS - 4);
+                writeInt(os, 0);            // reserved
+                writeShort(os, 0x0001);     // NTFS attr tag
+                writeShort(os, 24);
+                writeLong(os, javaToWinTime(mtime));
+                writeLong(os, javaToWinTime(atime));
+                writeLong(os, javaToWinTime(ctime));
+            }
+            if (elenEXTT != 0) {
+                writeShort(os, EXTID_EXTT);
+                writeShort(os, elenEXTT - 4);
+                if (ctime == -1)
+                    os.write(0x3);          // mtime and atime
+                else
+                    os.write(0x7);          // mtime, atime and ctime
+                writeInt(os, javaToUnixTime(mtime));
+            }
+            if (extra != null)              // whatever not recognized
+                writeBytes(os, extra);
+            if (comment != null)            //TBD: 0, Math.min(commentBytes.length, 0xffff));
+                writeBytes(os, comment);
+            return CENHDR + nlen + elen + clen + elen64 + elenNTFS + elenEXTT;
+        }
+
+        ///////////////////// LOC //////////////////////
+        static Entry readLOC(ZipFileSystem zipfs, long pos)
+            throws IOException
+        {
+            return readLOC(zipfs, pos, new byte[1024]);
+        }
+
+        static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf)
+            throws IOException
+        {
+            return new Entry().loc(zipfs, pos, buf);
+        }
+
+        Entry loc(ZipFileSystem zipfs, long pos, byte[] buf)
+            throws IOException
+        {
+            assert (buf.length >= LOCHDR);
+            if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR)
+                throw new ZipException("loc: reading failed");
+            if (LOCSIG(buf) != LOCSIG)
+                throw new ZipException("loc: wrong sig ->"
+                                       + Long.toString(LOCSIG(buf), 16));
+            //startPos = pos;
+            version  = LOCVER(buf);
+            flag     = LOCFLG(buf);
+            method   = LOCHOW(buf);
+            mtime    = dosToJavaTime(LOCTIM(buf));
+            crc      = LOCCRC(buf);
+            csize    = LOCSIZ(buf);
+            size     = LOCLEN(buf);
+            int nlen = LOCNAM(buf);
+            int elen = LOCEXT(buf);
+
+            name = new byte[nlen];
+            if (zipfs.readFullyAt(name, 0, nlen, pos + LOCHDR) != nlen) {
+                throw new ZipException("loc: name reading failed");
+            }
+            if (elen > 0) {
+                extra = new byte[elen];
+                if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
+                    != elen) {
+                    throw new ZipException("loc: ext reading failed");
+                }
+            }
+            pos += (LOCHDR + nlen + elen);
+            if ((flag & FLAG_DATADESCR) != 0) {
+                // Data Descriptor
+                Entry e = zipfs.getEntry0(name);  // get the size/csize from cen
+                if (e == null)
+                    throw new ZipException("loc: name not found in cen");
+                size = e.size;
+                csize = e.csize;
+                pos += (method == METHOD_STORED ? size : csize);
+                if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
+                    pos += 24;
+                else
+                    pos += 16;
+            } else {
+                if (extra != null &&
+                    (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
+                    // zip64 ext: must include both size and csize
+                    int off = 0;
+                    while (off + 20 < elen) {    // HeaderID+DataSize+Data
+                        int sz = SH(extra, off + 2);
+                        if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
+                            size = LL(extra, off + 4);
+                            csize = LL(extra, off + 12);
+                            break;
+                        }
+                        off += (sz + 4);
+                    }
+                }
+                pos += (method == METHOD_STORED ? size : csize);
+            }
+            return this;
+        }
+
+        int writeLOC(OutputStream os)
+            throws IOException
+        {
+            writeInt(os, LOCSIG);               // LOC header signature
+            int version = version();
+            int nlen = (name != null) ? name.length : 0;
+            int elen = (extra != null) ? extra.length : 0;
+            boolean foundExtraTime = false;     // if extra timestamp present
+            int eoff = 0;
+            int elen64 = 0;
+            int elenEXTT = 0;
+            int elenNTFS = 0;
+            if ((flag & FLAG_DATADESCR) != 0) {
+                writeShort(os, version());      // version needed to extract
+                writeShort(os, flag);           // general purpose bit flag
+                writeShort(os, method);         // compression method
+                // last modification time
+                writeInt(os, (int)javaToDosTime(mtime));
+                // store size, uncompressed size, and crc-32 in data descriptor
+                // immediately following compressed entry data
+                writeInt(os, 0);
+                writeInt(os, 0);
+                writeInt(os, 0);
+            } else {
+                if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
+                    elen64 = 20;    //headid(2) + size(2) + size(8) + csize(8)
+                    writeShort(os, 45);         // ver 4.5 for zip64
+                } else {
+                    writeShort(os, version());  // version needed to extract
+                }
+                writeShort(os, flag);           // general purpose bit flag
+                writeShort(os, method);         // compression method
+                                                // last modification time
+                writeInt(os, (int)javaToDosTime(mtime));
+                writeInt(os, crc);              // crc-32
+                if (elen64 != 0) {
+                    writeInt(os, ZIP64_MINVAL);
+                    writeInt(os, ZIP64_MINVAL);
+                } else {
+                    writeInt(os, csize);        // compressed size
+                    writeInt(os, size);         // uncompressed size
+                }
+            }
+            while (eoff + 4 < elen) {
+                int tag = SH(extra, eoff);
+                int sz = SH(extra, eoff + 2);
+                if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
+                    foundExtraTime = true;
+                }
+                eoff += (4 + sz);
+            }
+            if (!foundExtraTime) {
+                if (isWindows) {
+                    elenNTFS = 36;              // NTFS, total 36 bytes
+                } else {                        // on unix use "ext time"
+                    elenEXTT = 9;
+                    if (atime != -1)
+                        elenEXTT += 4;
+                    if (ctime != -1)
+                        elenEXTT += 4;
+                }
+            }
+            writeShort(os, name.length);
+            writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
+            writeBytes(os, name);
+            if (elen64 != 0) {
+                writeShort(os, EXTID_ZIP64);
+                writeShort(os, 16);
+                writeLong(os, size);
+                writeLong(os, csize);
+            }
+            if (elenNTFS != 0) {
+                writeShort(os, EXTID_NTFS);
+                writeShort(os, elenNTFS - 4);
+                writeInt(os, 0);            // reserved
+                writeShort(os, 0x0001);     // NTFS attr tag
+                writeShort(os, 24);
+                writeLong(os, javaToWinTime(mtime));
+                writeLong(os, javaToWinTime(atime));
+                writeLong(os, javaToWinTime(ctime));
+            }
+            if (elenEXTT != 0) {
+                writeShort(os, EXTID_EXTT);
+                writeShort(os, elenEXTT - 4);// size for the folowing data block
+                int fbyte = 0x1;
+                if (atime != -1)           // mtime and atime
+                    fbyte |= 0x2;
+                if (ctime != -1)           // mtime, atime and ctime
+                    fbyte |= 0x4;
+                os.write(fbyte);           // flags byte
+                writeInt(os, javaToUnixTime(mtime));
+                if (atime != -1)
+                    writeInt(os, javaToUnixTime(atime));
+                if (ctime != -1)
+                    writeInt(os, javaToUnixTime(ctime));
+            }
+            if (extra != null) {
+                writeBytes(os, extra);
+            }
+            return LOCHDR + name.length + elen + elen64 + elenNTFS + elenEXTT;
+        }
+
+        // Data Descriptior
+        int writeEXT(OutputStream os)
+            throws IOException
+        {
+            writeInt(os, EXTSIG);           // EXT header signature
+            writeInt(os, crc);              // crc-32
+            if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
+                writeLong(os, csize);
+                writeLong(os, size);
+                return 24;
+            } else {
+                writeInt(os, csize);        // compressed size
+                writeInt(os, size);         // uncompressed size
+                return 16;
+            }
+        }
+
+        // read NTFS, UNIX and ZIP64 data from cen.extra
+        void readExtra(ZipFileSystem zipfs) throws IOException {
+            if (extra == null)
+                return;
+            int elen = extra.length;
+            int off = 0;
+            int newOff = 0;
+            while (off + 4 < elen) {
+                // extra spec: HeaderID+DataSize+Data
+                int pos = off;
+                int tag = SH(extra, pos);
+                int sz = SH(extra, pos + 2);
+                pos += 4;
+                if (pos + sz > elen)         // invalid data
+                    break;
+                switch (tag) {
+                case EXTID_ZIP64 :
+                    if (size == ZIP64_MINVAL) {
+                        if (pos + 8 > elen)  // invalid zip64 extra
+                            break;           // fields, just skip
+                        size = LL(extra, pos);
+                        pos += 8;
+                    }
+                    if (csize == ZIP64_MINVAL) {
+                        if (pos + 8 > elen)
+                            break;
+                        csize = LL(extra, pos);
+                        pos += 8;
+                    }
+                    if (locoff == ZIP64_MINVAL) {
+                        if (pos + 8 > elen)
+                            break;
+                        locoff = LL(extra, pos);
+                        pos += 8;
+                    }
+                    break;
+                case EXTID_NTFS:
+                    pos += 4;    // reserved 4 bytes
+                    if (SH(extra, pos) !=  0x0001)
+                        break;
+                    if (SH(extra, pos + 2) != 24)
+                        break;
+                    // override the loc field, datatime here is
+                    // more "accurate"
+                    mtime  = winToJavaTime(LL(extra, pos + 4));
+                    atime  = winToJavaTime(LL(extra, pos + 12));
+                    ctime  = winToJavaTime(LL(extra, pos + 20));
+                    break;
+                case EXTID_EXTT:
+                    // spec says the Extened timestamp in cen only has mtime
+                    // need to read the loc to get the extra a/ctime
+                    byte[] buf = new byte[LOCHDR];
+                    if (zipfs.readFullyAt(buf, 0, buf.length , locoff)
+                        != buf.length)
+                        throw new ZipException("loc: reading failed");
+                    if (LOCSIG(buf) != LOCSIG)
+                        throw new ZipException("loc: wrong sig ->"
+                                           + Long.toString(LOCSIG(buf), 16));
+
+                    int locElen = LOCEXT(buf);
+                    if (locElen < 9)    // EXTT is at lease 9 bytes
+                        break;
+                    int locNlen = LOCNAM(buf);
+                    buf = new byte[locElen];
+                    if (zipfs.readFullyAt(buf, 0, buf.length , locoff + LOCHDR + locNlen)
+                        != buf.length)
+                        throw new ZipException("loc extra: reading failed");
+                    int locPos = 0;
+                    while (locPos + 4 < buf.length) {
+                        int locTag = SH(buf, locPos);
+                        int locSZ  = SH(buf, locPos + 2);
+                        locPos += 4;
+                        if (locTag  != EXTID_EXTT) {
+                            locPos += locSZ;
+                             continue;
+                        }
+                        int flag = CH(buf, locPos++);
+                        if ((flag & 0x1) != 0) {
+                            mtime = unixToJavaTime(LG(buf, locPos));
+                            locPos += 4;
+                        }
+                        if ((flag & 0x2) != 0) {
+                            atime = unixToJavaTime(LG(buf, locPos));
+                            locPos += 4;
+                        }
+                        if ((flag & 0x4) != 0) {
+                            ctime = unixToJavaTime(LG(buf, locPos));
+                            locPos += 4;
+                        }
+                        break;
+                    }
+                    break;
+                default:    // unknown tag
+                    System.arraycopy(extra, off, extra, newOff, sz + 4);
+                    newOff += (sz + 4);
+                }
+                off += (sz + 4);
+            }
+            if (newOff != 0 && newOff != extra.length)
+                extra = Arrays.copyOf(extra, newOff);
+            else
+                extra = null;
+        }
+    }
+
+    private static class ExChannelCloser  {
+        Path path;
+        SeekableByteChannel ch;
+        Set<InputStream> streams;
+        ExChannelCloser(Path path,
+                        SeekableByteChannel ch,
+                        Set<InputStream> streams)
+        {
+            this.path = path;
+            this.ch = ch;
+            this.streams = streams;
+        }
+    }
+
+    // ZIP directory has two issues:
+    // (1) ZIP spec does not require the ZIP file to include
+    //     directory entry
+    // (2) all entries are not stored/organized in a "tree"
+    //     structure.
+    // A possible solution is to build the node tree ourself as
+    // implemented below.
+    private IndexNode root;
+
+    private void addToTree(IndexNode inode, HashSet<IndexNode> dirs) {
+        if (dirs.contains(inode)) {
+            return;
+        }
+        IndexNode parent;
+        byte[] name = inode.name;
+        byte[] pname = getParent(name);
+        if (inodes.containsKey(LOOKUPKEY.as(pname))) {
+            parent = inodes.get(LOOKUPKEY);
+        } else {    // pseudo directory entry
+            parent = new IndexNode(pname, -1);
+            inodes.put(parent, parent);
+        }
+        addToTree(parent, dirs);
+        inode.sibling = parent.child;
+        parent.child = inode;
+        if (name[name.length -1] == '/')
+            dirs.add(inode);
+    }
+
+    private void removeFromTree(IndexNode inode) {
+        IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
+        IndexNode child = parent.child;
+        if (child.equals(inode)) {
+            parent.child = child.sibling;
+        } else {
+            IndexNode last = child;
+            while ((child = child.sibling) != null) {
+                if (child.equals(inode)) {
+                    last.sibling = child.sibling;
+                    break;
+                } else {
+                    last = child;
+                }
+            }
+        }
+    }
+
+    private void buildNodeTree() throws IOException {
+        beginWrite();
+        try {
+            HashSet<IndexNode> dirs = new HashSet<>();
+            IndexNode root = new IndexNode(ROOTPATH, -1);
+            inodes.put(root, root);
+            dirs.add(root);
+            for (IndexNode node : inodes.keySet().toArray(new IndexNode[0])) {
+                addToTree(node, dirs);
+            }
+        } finally {
+            endWrite();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.io.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.FileSystemProvider;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipError;
+import java.util.concurrent.ExecutorService;
+
+/*
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+public class ZipFileSystemProvider extends FileSystemProvider {
+
+
+    private final Map<Path, ZipFileSystem> filesystems = new HashMap<>();
+
+    public ZipFileSystemProvider() {}
+
+    @Override
+    public String getScheme() {
+        return "jar";
+    }
+
+    protected Path uriToPath(URI uri) {
+        String scheme = uri.getScheme();
+        if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
+            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
+        }
+        try {
+            // only support legacy JAR URL syntax  jar:{uri}!/{entry} for now
+            String spec = uri.getRawSchemeSpecificPart();
+            int sep = spec.indexOf("!/");
+            if (sep != -1)
+                spec = spec.substring(0, sep);
+            return Paths.get(new URI(spec)).toAbsolutePath();
+        } catch (URISyntaxException e) {
+            throw new IllegalArgumentException(e.getMessage(), e);
+        }
+    }
+
+    private boolean ensureFile(Path path) {
+        try {
+            BasicFileAttributes attrs =
+                Files.readAttributes(path, BasicFileAttributes.class);
+            if (!attrs.isRegularFile())
+                throw new UnsupportedOperationException();
+            return true;
+        } catch (IOException ioe) {
+            return false;
+        }
+    }
+
+    @Override
+    public FileSystem newFileSystem(URI uri, Map<String, ?> env)
+        throws IOException
+    {
+        Path path = uriToPath(uri);
+        synchronized(filesystems) {
+            Path realPath = null;
+            if (ensureFile(path)) {
+                realPath = path.toRealPath();
+                if (filesystems.containsKey(realPath))
+                    throw new FileSystemAlreadyExistsException();
+            }
+            ZipFileSystem zipfs = null;
+            try {
+                zipfs = new ZipFileSystem(this, path, env);
+            } catch (ZipError ze) {
+                String pname = path.toString();
+                if (pname.endsWith(".zip") || pname.endsWith(".jar"))
+                    throw ze;
+                // assume NOT a zip/jar file
+                throw new UnsupportedOperationException();
+            }
+            filesystems.put(realPath, zipfs);
+            return zipfs;
+        }
+    }
+
+    @Override
+    public FileSystem newFileSystem(Path path, Map<String, ?> env)
+        throws IOException
+    {
+        if (path.getFileSystem() != FileSystems.getDefault()) {
+            throw new UnsupportedOperationException();
+        }
+        ensureFile(path);
+        try {
+            return new ZipFileSystem(this, path, env);
+        } catch (ZipError ze) {
+            String pname = path.toString();
+            if (pname.endsWith(".zip") || pname.endsWith(".jar"))
+                throw ze;
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public Path getPath(URI uri) {
+
+        String spec = uri.getSchemeSpecificPart();
+        int sep = spec.indexOf("!/");
+        if (sep == -1)
+            throw new IllegalArgumentException("URI: "
+                + uri
+                + " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
+        return getFileSystem(uri).getPath(spec.substring(sep + 1));
+    }
+
+
+    @Override
+    public FileSystem getFileSystem(URI uri) {
+        synchronized (filesystems) {
+            ZipFileSystem zipfs = null;
+            try {
+                zipfs = filesystems.get(uriToPath(uri).toRealPath());
+            } catch (IOException x) {
+                // ignore the ioe from toRealPath(), return FSNFE
+            }
+            if (zipfs == null)
+                throw new FileSystemNotFoundException();
+            return zipfs;
+        }
+    }
+
+    // Checks that the given file is a UnixPath
+    static final ZipPath toZipPath(Path path) {
+        if (path == null)
+            throw new NullPointerException();
+        if (!(path instanceof ZipPath))
+            throw new ProviderMismatchException();
+        return (ZipPath)path;
+    }
+
+    @Override
+    public void checkAccess(Path path, AccessMode... modes) throws IOException {
+        toZipPath(path).checkAccess(modes);
+    }
+
+    @Override
+    public void copy(Path src, Path target, CopyOption... options)
+        throws IOException
+    {
+        toZipPath(src).copy(toZipPath(target), options);
+    }
+
+    @Override
+    public void createDirectory(Path path, FileAttribute<?>... attrs)
+        throws IOException
+    {
+        toZipPath(path).createDirectory(attrs);
+    }
+
+    @Override
+    public final void delete(Path path) throws IOException {
+        toZipPath(path).delete();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V
+        getFileAttributeView(Path path, Class<V> type, LinkOption... options)
+    {
+        return ZipFileAttributeView.get(toZipPath(path), type);
+    }
+
+    @Override
+    public FileStore getFileStore(Path path) throws IOException {
+        return toZipPath(path).getFileStore();
+    }
+
+    @Override
+    public boolean isHidden(Path path) {
+        return toZipPath(path).isHidden();
+    }
+
+    @Override
+    public boolean isSameFile(Path path, Path other) throws IOException {
+        return toZipPath(path).isSameFile(other);
+    }
+
+    @Override
+    public void move(Path src, Path target, CopyOption... options)
+        throws IOException
+    {
+        toZipPath(src).move(toZipPath(target), options);
+    }
+
+    @Override
+    public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
+            Set<? extends OpenOption> options,
+            ExecutorService exec,
+            FileAttribute<?>... attrs)
+            throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public SeekableByteChannel newByteChannel(Path path,
+                                              Set<? extends OpenOption> options,
+                                              FileAttribute<?>... attrs)
+        throws IOException
+    {
+        return toZipPath(path).newByteChannel(options, attrs);
+    }
+
+    @Override
+    public DirectoryStream<Path> newDirectoryStream(
+        Path path, Filter<? super Path> filter) throws IOException
+    {
+        return toZipPath(path).newDirectoryStream(filter);
+    }
+
+    @Override
+    public FileChannel newFileChannel(Path path,
+                                      Set<? extends OpenOption> options,
+                                      FileAttribute<?>... attrs)
+        throws IOException
+    {
+        return toZipPath(path).newFileChannel(options, attrs);
+    }
+
+    @Override
+    public InputStream newInputStream(Path path, OpenOption... options)
+        throws IOException
+    {
+        return toZipPath(path).newInputStream(options);
+    }
+
+    @Override
+    public OutputStream newOutputStream(Path path, OpenOption... options)
+        throws IOException
+    {
+        return toZipPath(path).newOutputStream(options);
+    }
+
+    @Override
+    public <A extends BasicFileAttributes> A
+        readAttributes(Path path, Class<A> type, LinkOption... options)
+        throws IOException
+    {
+        if (type == BasicFileAttributes.class || type == ZipFileAttributes.class)
+            return (A)toZipPath(path).getAttributes();
+        return null;
+    }
+
+    @Override
+    public Map<String, Object>
+        readAttributes(Path path, String attribute, LinkOption... options)
+        throws IOException
+    {
+        return toZipPath(path).readAttributes(attribute, options);
+    }
+
+    @Override
+    public Path readSymbolicLink(Path link) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public void setAttribute(Path path, String attribute,
+                             Object value, LinkOption... options)
+        throws IOException
+    {
+        toZipPath(path).setAttribute(attribute, value, options);
+    }
+
+    //////////////////////////////////////////////////////////////
+    void removeFileSystem(Path zfpath, ZipFileSystem zfs) throws IOException {
+        synchronized (filesystems) {
+            zfpath = zfpath.toRealPath();
+            if (filesystems.get(zfpath) == zfs)
+                filesystems.remove(zfpath);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipInfo.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+import static jdk.nio.zipfs.ZipConstants.*;
+import static jdk.nio.zipfs.ZipUtils.*;
+
+/**
+ * Print all loc and cen headers of the ZIP file
+ *
+ * @author  Xueming Shen
+ */
+
+public class ZipInfo {
+
+    public static void main(String[] args) throws Throwable {
+        if (args.length < 1) {
+            print("Usage: java ZipInfo zfname");
+        } else {
+            Map<String, ?> env = Collections.emptyMap();
+            ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider()
+                                    .newFileSystem(Paths.get(args[0]), env));
+            byte[] cen = zfs.cen;
+            if (cen == null) {
+                print("zip file is empty%n");
+                return;
+            }
+            int    pos = 0;
+            byte[] buf = new byte[1024];
+            int    no = 1;
+            while (pos + CENHDR < cen.length) {
+                print("----------------#%d--------------------%n", no++);
+                printCEN(cen, pos);
+
+                // use size CENHDR as the extra bytes to read, just in case the
+                // loc.extra is bigger than the cen.extra, try to avoid to read
+                // twice
+                long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR;
+                if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
+                    ZipFileSystem.zerror("read loc header failed");
+                if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) {
+                    // have to read the second time;
+                    len = LOCHDR + LOCNAM(buf) + LOCEXT(buf);
+                    if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
+                        ZipFileSystem.zerror("read loc header failed");
+                }
+                printLOC(buf);
+                pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos);
+            }
+            zfs.close();
+        }
+    }
+
+    static void print(String fmt, Object... objs) {
+        System.out.printf(fmt, objs);
+    }
+
+    static void printLOC(byte[] loc) {
+        print("%n");
+        print("[Local File Header]%n");
+        print("    Signature   :   %#010x%n", LOCSIG(loc));
+        if (LOCSIG(loc) != LOCSIG) {
+           print("    Wrong signature!");
+           return;
+        }
+        print("    Version     :       %#6x    [%d.%d]%n",
+                  LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10);
+        print("    Flag        :       %#6x%n", LOCFLG(loc));
+        print("    Method      :       %#6x%n", LOCHOW(loc));
+        print("    LastMTime   :   %#10x    [%tc]%n",
+              LOCTIM(loc), dosToJavaTime(LOCTIM(loc)));
+        print("    CRC         :   %#10x%n", LOCCRC(loc));
+        print("    CSize       :   %#10x%n", LOCSIZ(loc));
+        print("    Size        :   %#10x%n", LOCLEN(loc));
+        print("    NameLength  :       %#6x    [%s]%n",
+                  LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc)));
+        print("    ExtraLength :       %#6x%n", LOCEXT(loc));
+        if (LOCEXT(loc) != 0)
+            printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc));
+    }
+
+    static void printCEN(byte[] cen, int off) {
+        print("[Central Directory Header]%n");
+        print("    Signature   :   %#010x%n", CENSIG(cen, off));
+        if (CENSIG(cen, off) != CENSIG) {
+           print("    Wrong signature!");
+           return;
+        }
+        print("    VerMadeby   :       %#6x    [%d, %d.%d]%n",
+              CENVEM(cen, off), (CENVEM(cen, off) >> 8),
+              (CENVEM(cen, off) & 0xff) / 10,
+              (CENVEM(cen, off) & 0xff) % 10);
+        print("    VerExtract  :       %#6x    [%d.%d]%n",
+              CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10);
+        print("    Flag        :       %#6x%n", CENFLG(cen, off));
+        print("    Method      :       %#6x%n", CENHOW(cen, off));
+        print("    LastMTime   :   %#10x    [%tc]%n",
+              CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off)));
+        print("    CRC         :   %#10x%n", CENCRC(cen, off));
+        print("    CSize       :   %#10x%n", CENSIZ(cen, off));
+        print("    Size        :   %#10x%n", CENLEN(cen, off));
+        print("    NameLen     :       %#6x    [%s]%n",
+              CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off)));
+        print("    ExtraLen    :       %#6x%n", CENEXT(cen, off));
+        if (CENEXT(cen, off) != 0)
+            printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off));
+        print("    CommentLen  :       %#6x%n", CENCOM(cen, off));
+        print("    DiskStart   :       %#6x%n", CENDSK(cen, off));
+        print("    Attrs       :       %#6x%n", CENATT(cen, off));
+        print("    AttrsEx     :   %#10x%n", CENATX(cen, off));
+        print("    LocOff      :   %#10x%n", CENOFF(cen, off));
+
+    }
+
+    static long locoff(byte[] cen, int pos) {
+        long locoff = CENOFF(cen, pos);
+        if (locoff == ZIP64_MINVAL) {    //ZIP64
+            int off = pos + CENHDR + CENNAM(cen, pos);
+            int end = off + CENEXT(cen, pos);
+            while (off + 4 < end) {
+                int tag = SH(cen, off);
+                int sz = SH(cen, off + 2);
+                if (tag != EXTID_ZIP64) {
+                    off += 4 + sz;
+                    continue;
+                }
+                off += 4;
+                if (CENLEN(cen, pos) == ZIP64_MINVAL)
+                    off += 8;
+                if (CENSIZ(cen, pos) == ZIP64_MINVAL)
+                    off += 8;
+                return LL(cen, off);
+            }
+            // should never be here
+        }
+        return locoff;
+    }
+
+    static void printExtra(byte[] extra, int off, int len) {
+        int end = off + len;
+        while (off + 4 <= end) {
+            int tag = SH(extra, off);
+            int sz = SH(extra, off + 2);
+            print("        [tag=0x%04x, sz=%d, data= ", tag, sz);
+            if (off + sz > end) {
+                print("    Error: Invalid extra data, beyond extra length");
+                break;
+            }
+            off += 4;
+            for (int i = 0; i < sz; i++)
+                print("%02x ", extra[off + i]);
+            print("]%n");
+            switch (tag) {
+            case EXTID_ZIP64 :
+                print("         ->ZIP64: ");
+                int pos = off;
+                while (pos + 8 <= off + sz) {
+                    print(" *0x%x ", LL(extra, pos));
+                    pos += 8;
+                }
+                print("%n");
+                break;
+            case EXTID_NTFS:
+                print("         ->PKWare NTFS%n");
+                // 4 bytes reserved
+                if (SH(extra, off + 4) !=  0x0001 || SH(extra, off + 6) !=  24)
+                    print("    Error: Invalid NTFS sub-tag or subsz");
+                print("            mtime:%tc%n",
+                      winToJavaTime(LL(extra, off + 8)));
+                print("            atime:%tc%n",
+                      winToJavaTime(LL(extra, off + 16)));
+                print("            ctime:%tc%n",
+                      winToJavaTime(LL(extra, off + 24)));
+                break;
+            case EXTID_EXTT:
+                print("         ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]);
+                pos = off + 1 ;
+                while (pos + 4 <= off + sz) {
+                    print("            *%tc%n",
+                          unixToJavaTime(LG(extra, pos)));
+                    pos += 4;
+                }
+                break;
+            default:
+                print("         ->[tag=%x, size=%d]%n", tag, sz);
+            }
+            off += sz;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipPath.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,869 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.io.*;
+import java.net.URI;
+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.*;
+
+
+/**
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli,Jaya Hangal
+ */
+
+class ZipPath implements Path {
+
+    private final ZipFileSystem zfs;
+    private final byte[] path;
+    private volatile int[] offsets;
+    private int hashcode = 0;  // cached hashcode (created lazily)
+
+    ZipPath(ZipFileSystem zfs, byte[] path) {
+        this(zfs, path, false);
+    }
+
+    ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized)
+    {
+        this.zfs = zfs;
+        if (normalized)
+            this.path = path;
+        else
+            this.path = normalize(path);
+    }
+
+    @Override
+    public ZipPath getRoot() {
+        if (this.isAbsolute())
+            return new ZipPath(zfs, new byte[]{path[0]});
+        else
+            return null;
+    }
+
+    @Override
+    public Path 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 new ZipPath(zfs, result);
+    }
+
+    @Override
+    public ZipPath 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 new ZipPath(zfs, result);
+    }
+
+    @Override
+    public int getNameCount() {
+        initOffsets();
+        return offsets.length;
+    }
+
+    @Override
+    public ZipPath 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 new ZipPath(zfs, result);
+    }
+
+    @Override
+    public ZipPath 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 new ZipPath(zfs, result);
+    }
+
+    @Override
+    public ZipPath toRealPath(LinkOption... options) throws IOException {
+        ZipPath realPath = new ZipPath(zfs, getResolvedPath()).toAbsolutePath();
+        realPath.checkAccess();
+        return realPath;
+    }
+
+    boolean isHidden() {
+        return false;
+    }
+
+    @Override
+    public ZipPath toAbsolutePath() {
+        if (isAbsolute()) {
+            return this;
+        } else {
+            //add / bofore the existing path
+            byte[] defaultdir = zfs.getDefaultDir().path;
+            int defaultlen = defaultdir.length;
+            boolean endsWith = (defaultdir[defaultlen - 1] == '/');
+            byte[] t = null;
+            if (endsWith)
+                t = new byte[defaultlen + path.length];
+            else
+                t = new byte[defaultlen + 1 + path.length];
+            System.arraycopy(defaultdir, 0, t, 0, defaultlen);
+            if (!endsWith)
+                t[defaultlen++] = '/';
+            System.arraycopy(path, 0, t, defaultlen, path.length);
+            return new ZipPath(zfs, t, true);  // normalized
+        }
+    }
+
+    @Override
+    public URI toUri() {
+        try {
+            return new URI("jar",
+                           zfs.getZipFile().toUri() +
+                           "!" +
+                           zfs.getString(toAbsolutePath().path),
+                           null);
+        } catch (Exception ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    private boolean equalsNameAt(ZipPath other, int index) {
+        int mbegin = offsets[index];
+        int mlen = 0;
+        if (index == (offsets.length-1))
+            mlen = path.length - mbegin;
+        else
+            mlen = offsets[index + 1] - mbegin - 1;
+        int obegin = other.offsets[index];
+        int olen = 0;
+        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 Path relativize(Path other) {
+        final ZipPath o = checkPath(other);
+        if (o.equals(this))
+            return new ZipPath(getFileSystem(), 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 new ZipPath(getFileSystem(), result);
+    }
+
+    @Override
+    public ZipFileSystem getFileSystem() {
+        return zfs;
+    }
+
+    @Override
+    public boolean isAbsolute() {
+        return (this.path.length > 0 && path[0] == '/');
+    }
+
+    @Override
+    public ZipPath resolve(Path other) {
+        final ZipPath o = checkPath(other);
+        if (o.isAbsolute())
+            return o;
+        byte[] resolved = null;
+        if (this.path[path.length - 1] == '/') {
+            resolved = new byte[path.length + o.path.length];
+            System.arraycopy(path, 0, resolved, 0, path.length);
+            System.arraycopy(o.path, 0, resolved, path.length, o.path.length);
+        } else {
+            resolved = new byte[path.length + 1 + o.path.length];
+            System.arraycopy(path, 0, resolved, 0, path.length);
+            resolved[path.length] = '/';
+            System.arraycopy(o.path, 0, resolved, path.length + 1, o.path.length);
+        }
+        return new ZipPath(zfs, resolved);
+    }
+
+    @Override
+    public Path resolveSibling(Path other) {
+        if (other == null)
+            throw new NullPointerException();
+        Path parent = getParent();
+        return (parent == null) ? other : parent.resolve(other);
+    }
+
+    @Override
+    public boolean startsWith(Path other) {
+        final ZipPath 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 boolean endsWith(Path other) {
+        final ZipPath 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 ZipPath 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 Path normalize() {
+        byte[] resolved = getResolved();
+        if (resolved == path)    // no change
+            return this;
+        return new ZipPath(zfs, resolved, true);
+    }
+
+    private ZipPath checkPath(Path path) {
+        if (path == null)
+            throw new NullPointerException();
+        if (!(path instanceof ZipPath))
+            throw new ProviderMismatchException();
+        return (ZipPath) 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;
+            }
+        }
+    }
+
+    // resolved path for locating zip entry inside the zip file,
+    // the result path does not contain ./ and .. components
+    private volatile byte[] resolved = null;
+    byte[] getResolvedPath() {
+        byte[] r = resolved;
+        if (r == null) {
+            if (isAbsolute())
+                r = getResolved();
+            else
+                r = toAbsolutePath().getResolvedPath();
+            if (r[0] == '/')
+                r = Arrays.copyOfRange(r, 1, r.length);
+            resolved = r;
+        }
+        return resolved;
+    }
+
+    // removes redundant slashs, replace "\" to zip separator "/"
+    // and check for invalid characters
+    private 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(zfs.getString(path),
+                                               "Path: nul character not allowed");
+            prevC = c;
+        }
+        return path;
+    }
+
+    private 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(zfs.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 String toString() {
+        return zfs.getString(path);
+    }
+
+    @Override
+    public int hashCode() {
+        int h = hashcode;
+        if (h == 0)
+            hashcode = h = Arrays.hashCode(path);
+        return h;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return obj != null &&
+               obj instanceof ZipPath &&
+               this.zfs == ((ZipPath)obj).zfs &&
+               compareTo((Path) obj) == 0;
+    }
+
+    @Override
+    public int compareTo(Path other) {
+        final ZipPath 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;
+    }
+
+    public 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 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 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();
+            }
+        };
+    }
+
+    /////////////////////////////////////////////////////////////////////
+
+
+    void createDirectory(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        zfs.createDirectory(getResolvedPath(), attrs);
+    }
+
+    InputStream newInputStream(OpenOption... options) throws IOException
+    {
+        if (options.length > 0) {
+            for (OpenOption opt : options) {
+                if (opt != READ)
+                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
+            }
+        }
+        return zfs.newInputStream(getResolvedPath());
+    }
+
+    DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
+        throws IOException
+    {
+        return new ZipDirectoryStream(this, filter);
+    }
+
+    void delete() throws IOException {
+        zfs.deleteFile(getResolvedPath(), true);
+    }
+
+    void deleteIfExists() throws IOException {
+        zfs.deleteFile(getResolvedPath(), false);
+    }
+
+    ZipFileAttributes getAttributes() throws IOException
+    {
+        ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath());
+        if (zfas == null)
+            throw new NoSuchFileException(toString());
+        return zfas;
+    }
+
+    void setAttribute(String attribute, Object value, LinkOption... options)
+        throws IOException
+    {
+        String type = null;
+        String attr = null;
+        int colonPos = attribute.indexOf(':');
+        if (colonPos == -1) {
+            type = "basic";
+            attr = attribute;
+        } else {
+            type = attribute.substring(0, colonPos++);
+            attr = attribute.substring(colonPos);
+        }
+        ZipFileAttributeView view = ZipFileAttributeView.get(this, type);
+        if (view == null)
+            throw new UnsupportedOperationException("view <" + view + "> is not supported");
+        view.setAttribute(attr, value);
+    }
+
+    void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
+        throws IOException
+    {
+        zfs.setTimes(getResolvedPath(), mtime, atime, ctime);
+    }
+
+    Map<String, Object> readAttributes(String attributes, LinkOption... options)
+        throws IOException
+
+    {
+        String view = null;
+        String attrs = null;
+        int colonPos = attributes.indexOf(':');
+        if (colonPos == -1) {
+            view = "basic";
+            attrs = attributes;
+        } else {
+            view = attributes.substring(0, colonPos++);
+            attrs = attributes.substring(colonPos);
+        }
+        ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view);
+        if (zfv == null) {
+            throw new UnsupportedOperationException("view not supported");
+        }
+        return zfv.readAttributes(attrs);
+    }
+
+    FileStore getFileStore() throws IOException {
+        // each ZipFileSystem only has one root (as requested for now)
+        if (exists())
+            return zfs.getFileStore(this);
+        throw new NoSuchFileException(zfs.getString(path));
+    }
+
+    boolean isSameFile(Path other) throws IOException {
+        if (this.equals(other))
+            return true;
+        if (other == null ||
+            this.getFileSystem() != other.getFileSystem())
+            return false;
+        this.checkAccess();
+        ((ZipPath)other).checkAccess();
+        return Arrays.equals(this.getResolvedPath(),
+                             ((ZipPath)other).getResolvedPath());
+    }
+
+    SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+                                       FileAttribute<?>... attrs)
+        throws IOException
+    {
+        return zfs.newByteChannel(getResolvedPath(), options, attrs);
+    }
+
+
+    FileChannel newFileChannel(Set<? extends OpenOption> options,
+                               FileAttribute<?>... attrs)
+        throws IOException
+    {
+        return zfs.newFileChannel(getResolvedPath(), options, attrs);
+    }
+
+    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();
+            }
+        }
+        ZipFileAttributes attrs = zfs.getFileAttributes(getResolvedPath());
+        if (attrs == null && (path.length != 1 || path[0] != '/'))
+            throw new NoSuchFileException(toString());
+        if (w) {
+            if (zfs.isReadOnly())
+                throw new AccessDeniedException(toString());
+        }
+        if (x)
+            throw new AccessDeniedException(toString());
+    }
+
+    boolean exists() {
+        if (path.length == 1 && path[0] == '/')
+            return true;
+        try {
+            return zfs.exists(getResolvedPath());
+        } catch (IOException x) {}
+        return false;
+    }
+
+    OutputStream newOutputStream(OpenOption... options) throws IOException
+    {
+        if (options.length == 0)
+            return zfs.newOutputStream(getResolvedPath(),
+                                       CREATE_NEW, WRITE);
+        return zfs.newOutputStream(getResolvedPath(), options);
+    }
+
+    void move(ZipPath target, CopyOption... options)
+        throws IOException
+    {
+        if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
+        {
+            zfs.copyFile(true,
+                         getResolvedPath(), target.getResolvedPath(),
+                         options);
+        } else {
+            copyToTarget(target, options);
+            delete();
+        }
+    }
+
+    void copy(ZipPath target, CopyOption... options)
+        throws IOException
+    {
+        if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
+            zfs.copyFile(false,
+                         getResolvedPath(), target.getResolvedPath(),
+                         options);
+        else
+            copyToTarget(target, options);
+    }
+
+    private void copyToTarget(ZipPath 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
+        ZipFileAttributes zfas = 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 (zfas.isDirectory()) {
+            // create directory or file
+            target.createDirectory();
+        } else {
+            InputStream is = zfs.newInputStream(getResolvedPath());
+            try {
+                OutputStream os = target.newOutputStream();
+                try {
+                    byte[] buf = new byte[8192];
+                    int n = 0;
+                    while ((n = is.read(buf)) != -1) {
+                        os.write(buf, 0, n);
+                    }
+                } finally {
+                    os.close();
+                }
+            } finally {
+                is.close();
+            }
+        }
+        if (copyAttrs) {
+            BasicFileAttributeView view =
+                ZipFileAttributeView.get(target, BasicFileAttributeView.class);
+            try {
+                view.setTimes(zfas.lastModifiedTime(),
+                              zfas.lastAccessTime(),
+                              zfas.creationTime());
+            } catch (IOException x) {
+                // rollback?
+                try {
+                    target.delete();
+                } catch (IOException ignore) { }
+                throw x;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/jdk/nio/zipfs/ZipUtils.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2009, 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.nio.zipfs;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.regex.PatternSyntaxException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * @author Xueming Shen
+ */
+
+class ZipUtils {
+
+    /*
+     * Writes a 16-bit short to the output stream in little-endian byte order.
+     */
+    public static void writeShort(OutputStream os, int v) throws IOException {
+        os.write(v & 0xff);
+        os.write((v >>> 8) & 0xff);
+    }
+
+    /*
+     * Writes a 32-bit int to the output stream in little-endian byte order.
+     */
+    public static void writeInt(OutputStream os, long v) throws IOException {
+        os.write((int)(v & 0xff));
+        os.write((int)((v >>>  8) & 0xff));
+        os.write((int)((v >>> 16) & 0xff));
+        os.write((int)((v >>> 24) & 0xff));
+    }
+
+    /*
+     * Writes a 64-bit int to the output stream in little-endian byte order.
+     */
+    public static void writeLong(OutputStream os, long v) throws IOException {
+        os.write((int)(v & 0xff));
+        os.write((int)((v >>>  8) & 0xff));
+        os.write((int)((v >>> 16) & 0xff));
+        os.write((int)((v >>> 24) & 0xff));
+        os.write((int)((v >>> 32) & 0xff));
+        os.write((int)((v >>> 40) & 0xff));
+        os.write((int)((v >>> 48) & 0xff));
+        os.write((int)((v >>> 56) & 0xff));
+    }
+
+    /*
+     * Writes an array of bytes to the output stream.
+     */
+    public static void writeBytes(OutputStream os, byte[] b)
+        throws IOException
+    {
+        os.write(b, 0, b.length);
+    }
+
+    /*
+     * Writes an array of bytes to the output stream.
+     */
+    public static void writeBytes(OutputStream os, byte[] b, int off, int len)
+        throws IOException
+    {
+        os.write(b, off, len);
+    }
+
+    /*
+     * Append a slash at the end, if it does not have one yet
+     */
+    public static byte[] toDirectoryPath(byte[] dir) {
+        if (dir.length != 0 && dir[dir.length - 1] != '/') {
+            dir = Arrays.copyOf(dir, dir.length + 1);
+            dir[dir.length - 1] = '/';
+        }
+        return dir;
+    }
+
+    /*
+     * Converts DOS time to Java time (number of milliseconds since epoch).
+     */
+    public static long dosToJavaTime(long dtime) {
+        Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
+                          (int)(((dtime >> 21) & 0x0f) - 1),
+                          (int)((dtime >> 16) & 0x1f),
+                          (int)((dtime >> 11) & 0x1f),
+                          (int)((dtime >> 5) & 0x3f),
+                          (int)((dtime << 1) & 0x3e));
+        return d.getTime();
+    }
+
+    /*
+     * Converts Java time to DOS time.
+     */
+    public static long javaToDosTime(long time) {
+        Date d = new Date(time);
+        int year = d.getYear() + 1900;
+        if (year < 1980) {
+            return (1 << 21) | (1 << 16);
+        }
+        return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
+               d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
+               d.getSeconds() >> 1;
+    }
+
+
+    // used to adjust values between Windows and java epoch
+    private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
+    public static final long winToJavaTime(long wtime) {
+        return TimeUnit.MILLISECONDS.convert(
+               wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS);
+    }
+
+    public static final long javaToWinTime(long time) {
+        return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS)
+               - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
+    }
+
+    public static final long unixToJavaTime(long utime) {
+        return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS);
+    }
+
+    public static final long javaToUnixTime(long time) {
+        return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS);
+    }
+
+    private static final String regexMetaChars = ".^$+{[]|()";
+    private static final String globMetaChars = "\\*?[{";
+    private static boolean isRegexMeta(char c) {
+        return regexMetaChars.indexOf(c) != -1;
+    }
+    private static boolean isGlobMeta(char c) {
+        return globMetaChars.indexOf(c) != -1;
+    }
+    private static char EOL = 0;  //TBD
+    private static char next(String glob, int i) {
+        if (i < glob.length()) {
+            return glob.charAt(i);
+        }
+        return EOL;
+    }
+
+    /*
+     * Creates a regex pattern from the given glob expression.
+     *
+     * @throws  PatternSyntaxException
+     */
+    public static String toRegexPattern(String globPattern) {
+        boolean inGroup = false;
+        StringBuilder regex = new StringBuilder("^");
+
+        int i = 0;
+        while (i < globPattern.length()) {
+            char c = globPattern.charAt(i++);
+            switch (c) {
+                case '\\':
+                    // escape special characters
+                    if (i == globPattern.length()) {
+                        throw new PatternSyntaxException("No character to escape",
+                                globPattern, i - 1);
+                    }
+                    char next = globPattern.charAt(i++);
+                    if (isGlobMeta(next) || isRegexMeta(next)) {
+                        regex.append('\\');
+                    }
+                    regex.append(next);
+                    break;
+                case '/':
+                    regex.append(c);
+                    break;
+                case '[':
+                    // don't match name separator in class
+                    regex.append("[[^/]&&[");
+                    if (next(globPattern, i) == '^') {
+                        // escape the regex negation char if it appears
+                        regex.append("\\^");
+                        i++;
+                    } else {
+                        // negation
+                        if (next(globPattern, i) == '!') {
+                            regex.append('^');
+                            i++;
+                        }
+                        // hyphen allowed at start
+                        if (next(globPattern, i) == '-') {
+                            regex.append('-');
+                            i++;
+                        }
+                    }
+                    boolean hasRangeStart = false;
+                    char last = 0;
+                    while (i < globPattern.length()) {
+                        c = globPattern.charAt(i++);
+                        if (c == ']') {
+                            break;
+                        }
+                        if (c == '/') {
+                            throw new PatternSyntaxException("Explicit 'name separator' in class",
+                                    globPattern, i - 1);
+                        }
+                        // TBD: how to specify ']' in a class?
+                        if (c == '\\' || c == '[' ||
+                                c == '&' && next(globPattern, i) == '&') {
+                            // escape '\', '[' or "&&" for regex class
+                            regex.append('\\');
+                        }
+                        regex.append(c);
+
+                        if (c == '-') {
+                            if (!hasRangeStart) {
+                                throw new PatternSyntaxException("Invalid range",
+                                        globPattern, i - 1);
+                            }
+                            if ((c = next(globPattern, i++)) == EOL || c == ']') {
+                                break;
+                            }
+                            if (c < last) {
+                                throw new PatternSyntaxException("Invalid range",
+                                        globPattern, i - 3);
+                            }
+                            regex.append(c);
+                            hasRangeStart = false;
+                        } else {
+                            hasRangeStart = true;
+                            last = c;
+                        }
+                    }
+                    if (c != ']') {
+                        throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
+                    }
+                    regex.append("]]");
+                    break;
+                case '{':
+                    if (inGroup) {
+                        throw new PatternSyntaxException("Cannot nest groups",
+                                globPattern, i - 1);
+                    }
+                    regex.append("(?:(?:");
+                    inGroup = true;
+                    break;
+                case '}':
+                    if (inGroup) {
+                        regex.append("))");
+                        inGroup = false;
+                    } else {
+                        regex.append('}');
+                    }
+                    break;
+                case ',':
+                    if (inGroup) {
+                        regex.append(")|(?:");
+                    } else {
+                        regex.append(',');
+                    }
+                    break;
+                case '*':
+                    if (next(globPattern, i) == '*') {
+                        // crosses directory boundaries
+                        regex.append(".*");
+                        i++;
+                    } else {
+                        // within directory boundary
+                        regex.append("[^/]*");
+                    }
+                    break;
+                case '?':
+                   regex.append("[^/]");
+                   break;
+                default:
+                    if (isRegexMeta(c)) {
+                        regex.append('\\');
+                    }
+                    regex.append(c);
+            }
+        }
+        if (inGroup) {
+            throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
+        }
+        return regex.append('$').toString();
+    }
+}
--- a/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/AWTAutoShutdown.java	Wed Jul 05 19:37:28 2017 +0200
@@ -27,13 +27,15 @@
 
 import java.awt.AWTEvent;
 
-import java.util.Collections;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
 
 import sun.util.logging.PlatformLogger;
+import sun.misc.ThreadGroupUtils;
 
 /**
  * This class is to let AWT shutdown automatically when a user is done
@@ -215,7 +217,10 @@
         synchronized (activationLock) {
             synchronized (mainLock) {
                 if (!isReadyToShutdown() && blockerThread == null) {
-                    activateBlockerThread();
+                    AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                        activateBlockerThread();
+                        return null;
+                    });
                 } else {
                     mainLock.notifyAll();
                     timeoutPassed = false;
@@ -331,9 +336,12 @@
     /**
      * Creates and starts a new blocker thread. Doesn't return until
      * the new blocker thread starts.
+     *
+     * Must be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION}
      */
     private void activateBlockerThread() {
-        Thread thread = new Thread(this, "AWT-Shutdown");
+        Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), this, "AWT-Shutdown");
+        thread.setContextClassLoader(null);
         thread.setDaemon(false);
         blockerThread = thread;
         thread.start();
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java	Wed Jul 05 19:37:28 2017 +0200
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.security.PrivilegedAction;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
--- a/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/datatransfer/ClipboardTransferable.java	Wed Jul 05 19:37:28 2017 +0200
@@ -85,7 +85,7 @@
                 // read it.
                 Map<Long, Object> cached_data = new HashMap<>(formats.length, 1.0f);
                 DataTransferer.getInstance()
-                        .getFlavorsForFormats(formats, SunClipboard.flavorMap)
+                        .getFlavorsForFormats(formats, SunClipboard.getDefaultFlavorTable())
                         .entrySet()
                         .forEach(entry -> fetchOneFlavor(clipboard, entry.getKey(), entry.getValue(), cached_data));
                 flavors = DataTransferer.setToSortedDataFlavorArray(flavorsToData.keySet());
--- a/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/datatransfer/SunClipboard.java	Wed Jul 05 19:37:28 2017 +0200
@@ -64,9 +64,6 @@
 public abstract class SunClipboard extends Clipboard
     implements PropertyChangeListener {
 
-    public static final FlavorTable flavorMap =
-        (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();
-
     private AppContext contentsContext = null;
 
     private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
@@ -172,7 +169,7 @@
         long[] formats = getClipboardFormatsOpenClose();
 
         return DataTransferer.getInstance().
-            getFlavorsForFormatsAsArray(formats, flavorMap);
+            getFlavorsForFormatsAsArray(formats, getDefaultFlavorTable());
     }
 
     /**
@@ -218,7 +215,7 @@
 
             long[] formats = getClipboardFormats();
             Long lFormat = DataTransferer.getInstance().
-                    getFlavorsForFormats(formats, flavorMap).get(flavor);
+                    getFlavorsForFormats(formats, getDefaultFlavorTable()).get(flavor);
 
             if (lFormat == null) {
                 throw new UnsupportedFlavorException(flavor);
@@ -349,7 +346,7 @@
     private static Set formatArrayAsDataFlavorSet(long[] formats) {
         return (formats == null) ? null :
                 DataTransferer.getInstance().
-                getFlavorsForFormatsAsSet(formats, flavorMap);
+                getFlavorsForFormatsAsSet(formats, getDefaultFlavorTable());
     }
 
 
@@ -469,4 +466,7 @@
         }
     }
 
+    public static FlavorTable getDefaultFlavorTable() {
+        return (FlavorTable) SystemFlavorMap.getDefaultFlavorMap();
+    }
 }
--- a/jdk/src/share/classes/sun/font/CreatedFontTracker.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/font/CreatedFontTracker.java	Wed Jul 05 19:37:28 2017 +0200
@@ -27,12 +27,15 @@
 
 import java.io.File;
 import java.io.OutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import sun.awt.AppContext;
+import sun.misc.ThreadGroupUtils;
 
 public class CreatedFontTracker {
 
@@ -112,28 +115,18 @@
         static void init() {
             if (t == null) {
                 // Add a shutdown hook to remove the temp file.
-                java.security.AccessController.doPrivileged(
-                   new java.security.PrivilegedAction<Object>() {
-                      public Object run() {
-                          /* The thread must be a member of a thread group
-                           * which will not get GCed before VM exit.
-                           * Make its parent the top-level thread group.
-                           */
-                          ThreadGroup tg =
-                              Thread.currentThread().getThreadGroup();
-                          for (ThreadGroup tgn = tg;
-                               tgn != null;
-                               tg = tgn, tgn = tg.getParent());
-                          t = new Thread(tg, new Runnable() {
-                              public void run() {
-                                  runHooks();
-                              }
-                          });
-                          t.setContextClassLoader(null);
-                          Runtime.getRuntime().addShutdownHook(t);
-                          return null;
-                      }
-                   });
+                AccessController.doPrivileged(
+                        (PrivilegedAction<Void>) () -> {
+                            /* The thread must be a member of a thread group
+                             * which will not get GCed before VM exit.
+                             * Make its parent the top-level thread group.
+                             */
+                            ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                            t = new Thread(rootTG, TempFileDeletionHook::runHooks);
+                            t.setContextClassLoader(null);
+                            Runtime.getRuntime().addShutdownHook(t);
+                            return null;
+                        });
             }
         }
 
--- a/jdk/src/share/classes/sun/font/SunFontManager.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/font/SunFontManager.java	Wed Jul 05 19:37:28 2017 +0200
@@ -52,6 +52,7 @@
 import sun.awt.AppContext;
 import sun.awt.FontConfiguration;
 import sun.awt.SunToolkit;
+import sun.misc.ThreadGroupUtils;
 import sun.java2d.FontSupport;
 import sun.util.logging.PlatformLogger;
 
@@ -2527,24 +2528,18 @@
                           });
                       }
                     };
-                    java.security.AccessController.doPrivileged(
-                       new java.security.PrivilegedAction<Object>() {
-                          public Object run() {
-                              /* The thread must be a member of a thread group
-                               * which will not get GCed before VM exit.
-                               * Make its parent the top-level thread group.
-                               */
-                              ThreadGroup tg =
-                                  Thread.currentThread().getThreadGroup();
-                              for (ThreadGroup tgn = tg;
-                                   tgn != null;
-                                   tg = tgn, tgn = tg.getParent());
-                              fileCloser = new Thread(tg, fileCloserRunnable);
-                              fileCloser.setContextClassLoader(null);
-                              Runtime.getRuntime().addShutdownHook(fileCloser);
-                              return null;
-                          }
-                    });
+                    AccessController.doPrivileged(
+                            (PrivilegedAction<Void>) () -> {
+                                /* The thread must be a member of a thread group
+                                 * which will not get GCed before VM exit.
+                                 * Make its parent the top-level thread group.
+                                 */
+                                ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                                fileCloser = new Thread(rootTG, fileCloserRunnable);
+                                fileCloser.setContextClassLoader(null);
+                                Runtime.getRuntime().addShutdownHook(fileCloser);
+                                return null;
+                            });
                 }
             }
         }
--- a/jdk/src/share/classes/sun/java2d/Disposer.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/java2d/Disposer.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,10 +25,14 @@
 
 package sun.java2d;
 
+import sun.misc.ThreadGroupUtils;
+
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.PhantomReference;
 import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Hashtable;
 
@@ -77,27 +81,21 @@
             }
         }
         disposerInstance = new Disposer();
-        java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Object>() {
-                public Object run() {
-                    /* The thread must be a member of a thread group
-                     * which will not get GCed before VM exit.
-                     * Make its parent the top-level thread group.
-                     */
-                    ThreadGroup tg = Thread.currentThread().getThreadGroup();
-                    for (ThreadGroup tgn = tg;
-                         tgn != null;
-                         tg = tgn, tgn = tg.getParent());
-                    Thread t =
-                        new Thread(tg, disposerInstance, "Java2D Disposer");
-                    t.setContextClassLoader(null);
-                    t.setDaemon(true);
-                    t.setPriority(Thread.MAX_PRIORITY);
-                    t.start();
-                    return null;
-                }
-            }
-        );
+        AccessController.doPrivileged(
+                (PrivilegedAction<Void>) () -> {
+                     /* The thread must be a member of a thread group
+                      * which will not get GCed before VM exit.
+                      * Make its parent the top-level thread group.
+                      */
+                     ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                     Thread t = new Thread(rootTG, disposerInstance, "Java2D Disposer");
+                     t.setContextClassLoader(null);
+                     t.setDaemon(true);
+                     t.setPriority(Thread.MAX_PRIORITY);
+                     t.start();
+                     return null;
+                 }
+         );
     }
 
     /**
--- a/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,6 +25,7 @@
 
 package sun.java2d.opengl;
 
+import sun.misc.ThreadGroupUtils;
 import sun.java2d.pipe.RenderBuffer;
 import sun.java2d.pipe.RenderQueue;
 import static sun.java2d.pipe.BufferedOpCodes.*;
@@ -47,14 +48,8 @@
          * The thread must be a member of a thread group
          * which will not get GCed before VM exit.
          */
-        flusher = AccessController.doPrivileged(new PrivilegedAction<QueueFlusher>() {
-            public QueueFlusher run() {
-                ThreadGroup rootThreadGroup = Thread.currentThread().getThreadGroup();
-                while (rootThreadGroup.getParent() != null) {
-                    rootThreadGroup = rootThreadGroup.getParent();
-                }
-                return new QueueFlusher(rootThreadGroup);
-            }
+        flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) () -> {
+            return new QueueFlusher(ThreadGroupUtils.getRootThreadGroup());
         });
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/InnocuousThread.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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 sun.misc;
+
+import java.security.AccessControlContext;
+import java.security.ProtectionDomain;
+
+/**
+ * A thread that has no permissions, is not a member of any user-defined
+ * ThreadGroup and supports the ability to erase ThreadLocals.
+ *
+ * @implNote Based on the implementation of InnocuousForkJoinWorkerThread.
+ */
+public final class InnocuousThread extends Thread {
+    private static final Unsafe UNSAFE;
+    private static final ThreadGroup THREADGROUP;
+    private static final AccessControlContext ACC;
+    private static final long THREADLOCALS;
+    private static final long INHERITABLETHREADLOCALS;
+    private static final long INHERITEDACCESSCONTROLCONTEXT;
+
+    public InnocuousThread(Runnable target) {
+        super(THREADGROUP, target, "anInnocuousThread");
+        UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
+        eraseThreadLocals();
+    }
+
+    @Override
+    public ClassLoader getContextClassLoader() {
+        // always report system class loader
+        return ClassLoader.getSystemClassLoader();
+    }
+
+    @Override
+    public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {
+        // silently fail
+    }
+
+    @Override
+    public void setContextClassLoader(ClassLoader cl) {
+        throw new SecurityException("setContextClassLoader");
+    }
+
+    // ensure run method is run only once
+    private volatile boolean hasRun;
+
+    @Override
+    public void run() {
+        if (Thread.currentThread() == this && !hasRun) {
+            hasRun = true;
+            super.run();
+        }
+    }
+
+    /**
+     * Drops all thread locals (and inherited thread locals).
+     */
+    public void eraseThreadLocals() {
+        UNSAFE.putObject(this, THREADLOCALS, null);
+        UNSAFE.putObject(this, INHERITABLETHREADLOCALS, null);
+    }
+
+    // Use Unsafe to access Thread group and ThreadGroup parent fields
+    static {
+        try {
+            ACC = new AccessControlContext(new ProtectionDomain[] {
+                new ProtectionDomain(null, null)
+            });
+
+            // Find and use topmost ThreadGroup as parent of new group
+            UNSAFE = Unsafe.getUnsafe();
+            Class<?> tk = Thread.class;
+            Class<?> gk = ThreadGroup.class;
+
+            THREADLOCALS = UNSAFE.objectFieldOffset
+                (tk.getDeclaredField("threadLocals"));
+            INHERITABLETHREADLOCALS = UNSAFE.objectFieldOffset
+                (tk.getDeclaredField("inheritableThreadLocals"));
+            INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
+                (tk.getDeclaredField("inheritedAccessControlContext"));
+
+            long tg = UNSAFE.objectFieldOffset(tk.getDeclaredField("group"));
+            long gp = UNSAFE.objectFieldOffset(gk.getDeclaredField("parent"));
+            ThreadGroup group = (ThreadGroup)
+                UNSAFE.getObject(Thread.currentThread(), tg);
+
+            while (group != null) {
+                ThreadGroup parent = (ThreadGroup)UNSAFE.getObject(group, gp);
+                if (parent == null)
+                    break;
+                group = parent;
+            }
+            THREADGROUP = new ThreadGroup(group, "InnocuousThreadGroup");
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/misc/JavaNetHttpCookieAccess.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/misc/JavaNetHttpCookieAccess.java	Wed Jul 05 19:37:28 2017 +0200
@@ -36,7 +36,7 @@
     public List<HttpCookie> parse(String header);
 
     /*
-     * Returns the original header this cookie was consructed from, if it was
+     * Returns the original header this cookie was constructed from, if it was
      * constructed by parsing a header, otherwise null.
      */
     public String header(HttpCookie cookie);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/ThreadGroupUtils.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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 sun.misc;
+
+/**
+ * A utility class needed to access the root {@code ThreadGroup}
+ *
+ * The class should not depend on any others, because it' called from JNI_OnLoad of the AWT
+ * native library. Triggering class loading could could lead to a deadlock.
+ */
+public final class ThreadGroupUtils {
+
+    private ThreadGroupUtils() {
+        // Avoid instantiation
+    }
+
+    /**
+     * Returns a root thread group.
+     * Should be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION}
+     *
+     * @return a root {@code ThreadGroup}
+     */
+    public static ThreadGroup getRootThreadGroup() {
+        ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
+        ThreadGroup parentTG = currentTG.getParent();
+        while (parentTG != null) {
+            currentTG = parentTG;
+            parentTG = currentTG.getParent();
+        }
+        return currentTG;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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 sun.net;
+
+import java.net.*;
+import jdk.net.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.lang.reflect.Field;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Collections;
+
+/**
+ * Contains the native implementation for extended socket options
+ * together with some other static utilities
+ */
+public class ExtendedOptionsImpl {
+
+    static {
+        AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+            System.loadLibrary("net");
+            return null;
+        });
+        init();
+    }
+
+    private ExtendedOptionsImpl() {}
+
+    public static void checkSetOptionPermission(SocketOption<?> option) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null) {
+            return;
+        }
+        String check = "setOption." + option.name();
+        sm.checkPermission(new NetworkPermission(check));
+    }
+
+    public static void checkGetOptionPermission(SocketOption<?> option) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null) {
+            return;
+        }
+        String check = "getOption." + option.name();
+        sm.checkPermission(new NetworkPermission(check));
+    }
+
+    public static void checkValueType(Object value, Class<?> type) {
+        if (!type.isAssignableFrom(value.getClass())) {
+            String s = "Found: " + value.getClass().toString() + " Expected: "
+                        + type.toString();
+            throw new IllegalArgumentException(s);
+        }
+    }
+
+    private static native void init();
+
+    /*
+     * Extension native implementations
+     *
+     * SO_FLOW_SLA
+     */
+    public static native void setFlowOption(FileDescriptor fd, SocketFlow f);
+    public static native void getFlowOption(FileDescriptor fd, SocketFlow f);
+    public static native boolean flowSupported();
+}
--- a/jdk/src/share/classes/sun/net/www/MimeTable.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/net/www/MimeTable.java	Wed Jul 05 19:37:28 2017 +0200
@@ -225,39 +225,28 @@
     public synchronized void load() {
         Properties entries = new Properties();
         File file = null;
-        try {
-            InputStream is;
-            // First try to load the user-specific table, if it exists
-            String userTablePath =
-                System.getProperty("content.types.user.table");
-            if (userTablePath != null) {
-                file = new File(userTablePath);
-                if (!file.exists()) {
-                    // No user-table, try to load the default built-in table.
-                    file = new File(System.getProperty("java.home") +
-                                    File.separator +
-                                    "lib" +
-                                    File.separator +
-                                    "content-types.properties");
-                }
+        InputStream in;
+
+        // First try to load the user-specific table, if it exists
+        String userTablePath = System.getProperty("content.types.user.table");
+        if (userTablePath != null && (file = new File(userTablePath)).exists()) {
+            try {
+                in = new FileInputStream(file);
+            } catch (FileNotFoundException e) {
+                System.err.println("Warning: " + file.getPath()
+                                   + " mime table not found.");
+                return;
             }
-            else {
-                // No user table, try to load the default built-in table.
-                file = new File(System.getProperty("java.home") +
-                                File.separator +
-                                "lib" +
-                                File.separator +
-                                "content-types.properties");
-            }
+        } else {
+            in = MimeTable.class.getResourceAsStream("content-types.properties");
+            if (in == null)
+                throw new InternalError("default mime table not found");
+        }
 
-            is = new BufferedInputStream(new FileInputStream(file));
-            entries.load(is);
-            is.close();
-        }
-        catch (IOException e) {
-            System.err.println("Warning: default mime table not found: " +
-                               file.getPath());
-            return;
+        try (BufferedInputStream bin = new BufferedInputStream(in)) {
+            entries.load(bin);
+        } catch (IOException e) {
+            System.err.println("Warning: " + e.getMessage());
         }
         parse(entries);
     }
@@ -380,18 +369,6 @@
         return MimeEntry.UNKNOWN;
     }
 
-    public synchronized boolean save(String filename) {
-        if (filename == null) {
-            filename = System.getProperty("user.home" +
-                                          File.separator +
-                                          "lib" +
-                                          File.separator +
-                                          "content-types.properties");
-        }
-
-        return saveAsProperties(new File(filename));
-    }
-
     public Properties getAsProperties() {
         Properties properties = new Properties();
         Enumeration<MimeEntry> e = elements();
--- a/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -39,6 +39,7 @@
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
 import sun.net.NetHooks;
+import sun.net.ExtendedOptionsImpl;
 
 /**
  * Base implementation of AsynchronousSocketChannel
@@ -508,6 +509,9 @@
             set.add(StandardSocketOptions.SO_KEEPALIVE);
             set.add(StandardSocketOptions.SO_REUSEADDR);
             set.add(StandardSocketOptions.TCP_NODELAY);
+            if (ExtendedOptionsImpl.flowSupported()) {
+                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+            }
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -33,6 +33,7 @@
 import java.nio.channels.spi.*;
 import java.util.*;
 import sun.net.ResourceManager;
+import sun.net.ExtendedOptionsImpl;
 
 /**
  * An implementation of DatagramChannels.
@@ -317,6 +318,9 @@
             set.add(StandardSocketOptions.IP_MULTICAST_IF);
             set.add(StandardSocketOptions.IP_MULTICAST_TTL);
             set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+            if (ExtendedOptionsImpl.flowSupported()) {
+                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+            }
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/share/classes/sun/nio/ch/Invoker.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Invoker.java	Wed Jul 05 19:37:28 2017 +0200
@@ -130,6 +130,18 @@
 
         // clear interrupt
         Thread.interrupted();
+
+        // clear thread locals when in default thread pool
+        if (System.getSecurityManager() != null) {
+            Thread me = Thread.currentThread();
+            if (me instanceof sun.misc.InnocuousThread) {
+                GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+                ((sun.misc.InnocuousThread)me).eraseThreadLocals();
+                if (thisGroupAndInvokeCount != null) {
+                    myGroupAndInvokeCount.set(thisGroupAndInvokeCount);
+                }
+            }
+        }
     }
 
     /**
--- a/jdk/src/share/classes/sun/nio/ch/Net.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Net.java	Wed Jul 05 19:37:28 2017 +0200
@@ -27,11 +27,13 @@
 
 import java.io.*;
 import java.net.*;
+import jdk.net.*;
 import java.nio.channels.*;
 import java.util.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
+import sun.net.ExtendedOptionsImpl;
 
 
 public class Net {
@@ -297,6 +299,16 @@
 
         // only simple values supported by this method
         Class<?> type = name.type();
+
+        if (type == SocketFlow.class) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
+            }
+            ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
+            return;
+        }
+
         if (type != Integer.class && type != Boolean.class)
             throw new AssertionError("Should not reach here");
 
@@ -349,6 +361,16 @@
     {
         Class<?> type = name.type();
 
+        if (type == SocketFlow.class) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA"));
+            }
+            SocketFlow flow = SocketFlow.create();
+            ExtendedOptionsImpl.getFlowOption(fd, flow);
+            return flow;
+        }
+
         // only simple values supported by this method
         if (type != Integer.class && type != Boolean.class)
             throw new AssertionError("Should not reach here");
--- a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -33,6 +33,7 @@
 import java.nio.channels.spi.*;
 import java.util.*;
 import sun.net.NetHooks;
+import sun.net.ExtendedOptionsImpl;
 
 
 /**
@@ -237,6 +238,9 @@
             // additional options required by socket adaptor
             set.add(StandardSocketOptions.IP_TOS);
             set.add(ExtendedSocketOption.SO_OOBINLINE);
+            if (ExtendedOptionsImpl.flowSupported()) {
+                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+            }
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/share/classes/sun/nio/ch/ThreadPool.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/ThreadPool.java	Wed Jul 05 19:37:28 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.util.concurrent.*;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import sun.security.action.GetPropertyAction;
 import sun.security.action.GetIntegerAction;
 
@@ -39,14 +40,6 @@
         "java.nio.channels.DefaultThreadPool.threadFactory";
     private static final String DEFAULT_THREAD_POOL_INITIAL_SIZE =
         "java.nio.channels.DefaultThreadPool.initialSize";
-    private static final ThreadFactory defaultThreadFactory = new ThreadFactory() {
-         @Override
-         public Thread newThread(Runnable r) {
-             Thread t = new Thread(r);
-             t.setDaemon(true);
-             return t;
-        }
-     };
 
     private final ExecutorService executor;
 
@@ -79,7 +72,22 @@
     }
 
     static ThreadFactory defaultThreadFactory() {
-        return defaultThreadFactory;
+        if (System.getSecurityManager() == null) {
+            return (Runnable r) -> {
+                Thread t = new Thread(r);
+                t.setDaemon(true);
+                return t;
+            };
+        } else {
+            return (Runnable r) -> {
+                PrivilegedAction<Thread> action = () -> {
+                    Thread t = new sun.misc.InnocuousThread(r);
+                    t.setDaemon(true);
+                    return t;
+               };
+               return AccessController.doPrivileged(action);
+           };
+        }
     }
 
     private static class DefaultThreadPoolHolder {
@@ -100,7 +108,7 @@
         // default to thread factory that creates daemon threads
         ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory();
         if (threadFactory == null)
-            threadFactory = defaultThreadFactory;
+            threadFactory = defaultThreadFactory();
         // create thread pool
         ExecutorService executor = Executors.newCachedThreadPool(threadFactory);
         return new ThreadPool(executor, false, initialSize);
--- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Wed Jul 05 19:37:28 2017 +0200
@@ -111,12 +111,18 @@
                    (b4 & 0xc0) != 0x80;
         }
 
-        // only used when there is less than 4 bytes left in src buffer
+        // only used when there is less than 4 bytes left in src buffer.
+        // both b1 and b2 should be "& 0xff" before passed in.
         private static boolean isMalformed4_2(int b1, int b2) {
-            return (b1 == 0xf0 && b2 == 0x90) ||
+            return (b1 == 0xf0 && (b2  < 0x90 || b2 > 0xbf)) ||
+                   (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
                    (b2 & 0xc0) != 0x80;
         }
 
+        // tests if b1 and b2 are malformed as the first 2 bytes of a
+        // legal`4-byte utf-8 byte sequence.
+        // only used when there is less than 4 bytes left in src buffer,
+        // after isMalformed4_2 has been invoked.
         private static boolean isMalformed4_3(int b3) {
             return (b3 & 0xc0) != 0x80;
         }
@@ -280,7 +286,9 @@
                     // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                     int srcRemaining = sl - sp;
                     if (srcRemaining < 4 || dl - dp < 2) {
-                        if (srcRemaining > 1 && isMalformed4_2(b1, sa[sp + 1]))
+                        b1 &= 0xff;
+                        if (b1 > 0xf4 ||
+                            srcRemaining > 1 && isMalformed4_2(b1, sa[sp + 1] & 0xff))
                             return malformedForLength(src, sp, dst, dp, 1);
                         if (srcRemaining > 2 && isMalformed4_3(sa[sp + 2]))
                             return malformedForLength(src, sp, dst, dp, 2);
@@ -363,7 +371,9 @@
                     // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                     int srcRemaining = limit - mark;
                     if (srcRemaining < 4 || dst.remaining() < 2) {
-                        if (srcRemaining > 1 && isMalformed4_2(b1, src.get()))
+                        b1 &= 0xff;
+                        if (b1 > 0xf4 ||
+                            srcRemaining > 1 && isMalformed4_2(b1, src.get() & 0xff))
                             return malformedForLength(src, mark, 1);
                         if (srcRemaining > 2 && isMalformed4_3(src.get()))
                             return malformedForLength(src, mark, 2);
@@ -518,8 +528,9 @@
                     }
                     if (malformedInputAction() != CodingErrorAction.REPLACE)
                         return -1;
-
-                    if (sp  < sl && isMalformed4_2(b1, sa[sp])) {
+                    b1 &= 0xff;
+                    if (b1 > 0xf4 ||
+                        sp  < sl && isMalformed4_2(b1, sa[sp] & 0xff)) {
                         da[dp++] = replacement().charAt(0);
                         continue;
                     }
--- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -179,8 +179,8 @@
                             md.update(p.getProperty(s).getBytes());
                         }
 
-                        md.update
-                            (InetAddress.getLocalHost().toString().getBytes());
+                        // Include network adapter names (and a Mac address)
+                        addNetworkAdapterInfo(md);
 
                         // The temporary dir
                         File f = new File(p.getProperty("java.io.tmpdir"));
@@ -221,6 +221,31 @@
         return md.digest();
     }
 
+    /*
+     * Include network adapter names and, if available, a Mac address
+     *
+     * See also java.util.concurrent.ThreadLocalRandom.initialSeed()
+     */
+    private static void addNetworkAdapterInfo(MessageDigest md) {
+
+        try {
+            Enumeration<NetworkInterface> ifcs =
+                NetworkInterface.getNetworkInterfaces();
+            while (ifcs.hasMoreElements()) {
+                NetworkInterface ifc = ifcs.nextElement();
+                md.update(ifc.toString().getBytes());
+                if (!ifc.isVirtual()) { // skip fake addresses
+                    byte[] bs = ifc.getHardwareAddress();
+                    if (bs != null) {
+                        md.update(bs);
+                        break;
+                    }
+                }
+            }
+        } catch (Exception ignore) {
+        }
+    }
+
     /**
      * Helper function to convert a long into a byte array (least significant
      * byte first).
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Wed Jul 05 19:37:28 2017 +0200
@@ -75,7 +75,7 @@
     private PublicKey prevPubKey;
 
     private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
-                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
+        Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
 
     private final static DisabledAlgorithmConstraints
         certPathDefaultConstraints = new DisabledAlgorithmConstraints(
--- a/jdk/src/share/classes/sun/security/rsa/RSAPadding.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/rsa/RSAPadding.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,11 +25,9 @@
 
 package sun.security.rsa;
 
-import java.math.BigInteger;
 import java.util.*;
 
 import java.security.*;
-import java.security.interfaces.*;
 import java.security.spec.*;
 
 import javax.crypto.BadPaddingException;
@@ -41,21 +39,41 @@
 /**
  * RSA padding and unpadding.
  *
- * Format of PKCS#1 v1.5 padding is:
+ * The various PKCS#1 versions can be found in the EMC/RSA Labs
+ * web site, which is currently:
+ *
+ *     http://www.emc.com/emc-plus/rsa-labs/index.htm
+ *
+ * or in the IETF RFCs derived from the above PKCS#1 standards.
+ *
+ *     RFC 2313: v1.5
+ *     RFC 2437: v2.0
+ *     RFC 3447: v2.1
+ *
+ * The format of PKCS#1 v1.5 padding is:
+ *
  *   0x00 | BT | PS...PS | 0x00 | data...data
+ *
  * where BT is the blocktype (1 or 2). The length of the entire string
  * must be the same as the size of the modulus (i.e. 128 byte for a 1024 bit
  * key). Per spec, the padding string must be at least 8 bytes long. That
  * leaves up to (length of key in bytes) - 11 bytes for the data.
  *
- * OAEP padding is a bit more complicated and has a number of options.
- * We support:
+ * OAEP padding was introduced in PKCS#1 v2.0 and is a bit more complicated
+ * and has a number of options. We support:
+ *
  *   . arbitrary hash functions ('Hash' in the specification), MessageDigest
  *     implementation must be available
  *   . MGF1 as the mask generation function
  *   . the empty string as the default value for label L and whatever
  *     specified in javax.crypto.spec.OAEPParameterSpec
  *
+ * The algorithms (representations) are forwards-compatible: that is,
+ * the algorithm described in previous releases are in later releases.
+ * However, additional comments/checks/clarifications were added to the
+ * later versions based on real-world experience (e.g. stricter v1.5
+ * format checking.)
+ *
  * Note: RSA keys should be at least 512 bits long
  *
  * @since   1.5
@@ -156,7 +174,8 @@
                         throw new InvalidAlgorithmParameterException
                             ("Unsupported MGF algo: " + mgfName);
                     }
-                    mgfMdName = ((MGF1ParameterSpec)spec.getMGFParameters()).getDigestAlgorithm();
+                    mgfMdName = ((MGF1ParameterSpec)spec.getMGFParameters())
+                            .getDigestAlgorithm();
                     PSource pSrc = spec.getPSource();
                     String pSrcAlgo = pSrc.getAlgorithm();
                     if (!pSrcAlgo.equalsIgnoreCase("PSpecified")) {
@@ -198,7 +217,7 @@
      */
     private static byte[] getInitialHash(MessageDigest md,
         byte[] digestInput) {
-        byte[] result = null;
+        byte[] result;
         if ((digestInput == null) || (digestInput.length == 0)) {
             String digestName = md.getAlgorithm();
             result = emptyHashes.get(digestName);
@@ -213,8 +232,8 @@
     }
 
     /**
-     * Return the maximum size of the plaintext data that can be processed using
-     * this object.
+     * Return the maximum size of the plaintext data that can be processed
+     * using this object.
      */
     public int getMaxDataSize() {
         return maxDataSize;
@@ -262,7 +281,7 @@
      */
     public byte[] unpad(byte[] padded) throws BadPaddingException {
         if (padded.length != paddedSize) {
-            throw new BadPaddingException("Padded length must be " + paddedSize);
+            throw new BadPaddingException("Decryption error");
         }
         switch (type) {
         case PAD_NONE:
@@ -282,7 +301,8 @@
      */
     private byte[] padV15(byte[] data) throws BadPaddingException {
         byte[] padded = new byte[paddedSize];
-        System.arraycopy(data, 0, padded, paddedSize - data.length, data.length);
+        System.arraycopy(data, 0, padded, paddedSize - data.length,
+            data.length);
         int psSize = paddedSize - 3 - data.length;
         int k = 0;
         padded[k++] = 0;
@@ -317,55 +337,53 @@
     }
 
     /**
-     * PKCS#1 v1.5 unpadding (blocktype 1 and 2).
+     * PKCS#1 v1.5 unpadding (blocktype 1 (signature) and 2 (encryption)).
      *
      * Note that we want to make it a constant-time operation
      */
     private byte[] unpadV15(byte[] padded) throws BadPaddingException {
         int k = 0;
-        BadPaddingException bpe = null;
+        boolean bp = false;
 
         if (padded[k++] != 0) {
-            bpe = new BadPaddingException("Data must start with zero");
+            bp = true;
         }
-        if (padded[k++] != type && bpe == null) {
-            bpe = new BadPaddingException("Blocktype mismatch: " + padded[1]);
+        if (padded[k++] != type) {
+            bp = true;
         }
         int p = 0;
         while (k < padded.length) {
             int b = padded[k++] & 0xff;
-            if (b == 0 && p == 0) {
+            if ((b == 0) && (p == 0)) {
                 p = k;
             }
-            if (k == padded.length && p == 0 && bpe == null) {
-                bpe = new BadPaddingException("Padding string not terminated");
+            if ((k == padded.length) && (p == 0)) {
+                bp = true;
             }
             if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) &&
-                    p == 0 && bpe == null) {
-                bpe = new BadPaddingException("Padding byte not 0xff: " + b);
+                    (p == 0)) {
+                bp = true;
             }
         }
         int n = padded.length - p;
-        if (n > maxDataSize && bpe == null) {
-            bpe = new BadPaddingException("Padding string too short");
+        if (n > maxDataSize) {
+            bp = true;
         }
 
         // copy useless padding array for a constant-time method
-        //
-        // Is it necessary?
         byte[] padding = new byte[p];
         System.arraycopy(padded, 0, padding, 0, p);
 
         byte[] data = new byte[n];
         System.arraycopy(padded, p, data, 0, n);
 
-        if (bpe == null) {
-            bpe = new BadPaddingException("Unused exception");
-        } else {
+        BadPaddingException bpe = new BadPaddingException("Decryption error");
+
+        if (bp) {
             throw bpe;
+        } else {
+            return data;
         }
-
-        return data;
     }
 
     /**
@@ -424,10 +442,11 @@
      */
     private byte[] unpadOAEP(byte[] padded) throws BadPaddingException {
         byte[] EM = padded;
+        boolean bp = false;
         int hLen = lHash.length;
 
         if (EM[0] != 0) {
-            throw new BadPaddingException("Data must start with zero");
+            bp = true;
         }
 
         int seedStart = 1;
@@ -442,29 +461,48 @@
         // verify lHash == lHash'
         for (int i = 0; i < hLen; i++) {
             if (lHash[i] != EM[dbStart + i]) {
-                throw new BadPaddingException("lHash mismatch");
+                bp = true;
+            }
+        }
+
+        int padStart = dbStart + hLen;
+        int onePos = -1;
+
+        for (int i = padStart; i < EM.length; i++) {
+            int value = EM[i];
+            if (onePos == -1) {
+                if (value == 0x00) {
+                    // continue;
+                } else if (value == 0x01) {
+                    onePos = i;
+                } else {  // Anything other than {0,1} is bad.
+                    bp = true;
+                }
             }
         }
 
-        // skip over padding (0x00 bytes)
-        int i = dbStart + hLen;
-        while (EM[i] == 0) {
-            i++;
-            if (i >= EM.length) {
-                throw new BadPaddingException("Padding string not terminated");
-            }
+        // We either ran off the rails or found something other than 0/1.
+        if (onePos == -1) {
+            bp = true;
+            onePos = EM.length - 1;  // Don't inadvertently return any data.
         }
 
-        if (EM[i++] != 1) {
-            throw new BadPaddingException
-                ("Padding string not terminated by 0x01 byte");
-        }
+        int mStart = onePos + 1;
+
+        // copy useless padding array for a constant-time method
+        byte [] tmp = new byte[mStart - padStart];
+        System.arraycopy(EM, padStart, tmp, 0, tmp.length);
 
-        int mLen = EM.length - i;
-        byte[] m = new byte[mLen];
-        System.arraycopy(EM, i, m, 0, mLen);
+        byte [] m = new byte[EM.length - mStart];
+        System.arraycopy(EM, mStart, m, 0, m.length);
+
+        BadPaddingException bpe = new BadPaddingException("Decryption error");
 
-        return m;
+        if (bp) {
+            throw bpe;
+        } else {
+            return m;
+        }
     }
 
     /**
@@ -499,5 +537,4 @@
             }
         }
     }
-
 }
--- a/jdk/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/BaseSSLSocketImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.nio.channels.SocketChannel;
 import java.net.*;
+import java.util.Set;
 
 import javax.net.ssl.*;
 
@@ -634,6 +635,34 @@
         }
     }
 
+    @Override
+    public <T> Socket setOption(SocketOption<T> name,
+            T value) throws IOException {
+        if (self == this) {
+            return super.setOption(name, value);
+        } else {
+            return self.setOption(name, value);
+        }
+    }
+
+    @Override
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        if (self == this) {
+            return super.getOption(name);
+        } else {
+            return self.getOption(name);
+        }
+    }
+
+    @Override
+    public Set<SocketOption<?>> supportedOptions() {
+        if (self == this) {
+            return super.supportedOptions();
+        } else {
+            return self.supportedOptions();
+        }
+    }
+
     boolean isLayered() {
         return (self != this);
     }
--- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java	Wed Jul 05 19:37:28 2017 +0200
@@ -68,7 +68,7 @@
 
     // performance optimization
     private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
-                                    EnumSet.of(CryptoPrimitive.SIGNATURE);
+        Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
 
     // supported pairs of signature and hash algorithm
     private final static Map<Integer, SignatureAndHashAlgorithm> supportedMap;
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java	Wed Jul 05 19:37:28 2017 +0200
@@ -90,9 +90,6 @@
 
     private static final String META_INF = "META-INF/";
 
-    // prefix for new signature-related files in META-INF directory
-    private static final String SIG_PREFIX = META_INF + "SIG-";
-
     private static final Class<?>[] PARAM_STRING = { String.class };
 
     private static final String NONE = "NONE";
@@ -1522,22 +1519,7 @@
      * . META-INF/*.EC
      */
     private boolean signatureRelated(String name) {
-        String ucName = name.toUpperCase(Locale.ENGLISH);
-        if (ucName.equals(JarFile.MANIFEST_NAME) ||
-            ucName.equals(META_INF) ||
-            (ucName.startsWith(SIG_PREFIX) &&
-                ucName.indexOf("/") == ucName.lastIndexOf("/"))) {
-            return true;
-        }
-
-        if (ucName.startsWith(META_INF) &&
-            SignatureFileVerifier.isBlockOrSF(ucName)) {
-            // .SF/.DSA/.RSA/.EC files in META-INF subdirs
-            // are not considered signature-related
-            return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
-        }
-
-        return false;
+        return SignatureFileVerifier.isSigningRelated(name);
     }
 
     Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
--- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java	Wed Jul 05 19:37:28 2017 +0200
@@ -152,6 +152,52 @@
         return false;
     }
 
+    /**
+     * Yet another utility method used by JarVerifier and JarSigner
+     * to determine what files are signature related, which includes
+     * the MANIFEST, SF files, known signature block files, and other
+     * unknown signature related files (those starting with SIG- with
+     * an optional [A-Z0-9]{1,3} extension right inside META-INF).
+     *
+     * @param s file name
+     * @return true if the input file name is signature related
+     */
+    public static boolean isSigningRelated(String name) {
+        name = name.toUpperCase(Locale.ENGLISH);
+        if (!name.startsWith("META-INF/")) {
+            return false;
+        }
+        name = name.substring(9);
+        if (name.indexOf('/') != -1) {
+            return false;
+        }
+        if (isBlockOrSF(name) || name.equals("MANIFEST.MF")) {
+            return true;
+        } else if (name.startsWith("SIG-")) {
+            // check filename extension
+            // see http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures
+            // for what filename extensions are legal
+            int extIndex = name.lastIndexOf('.');
+            if (extIndex != -1) {
+                String ext = name.substring(extIndex + 1);
+                // validate length first
+                if (ext.length() > 3 || ext.length() < 1) {
+                    return false;
+                }
+                // then check chars, must be in [a-zA-Z0-9] per the jar spec
+                for (int index = 0; index < ext.length(); index++) {
+                    char cc = ext.charAt(index);
+                    // chars are promoted to uppercase so skip lowercase checks
+                    if ((cc < 'A' || cc > 'Z') && (cc < '0' || cc > '9')) {
+                        return false;
+                    }
+                }
+            }
+            return true; // no extension is OK
+        }
+        return false;
+    }
+
     /** get digest from cache */
 
     private MessageDigest getDigest(String algorithm)
--- a/jdk/src/share/classes/sun/tools/jinfo/JInfo.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/classes/sun/tools/jinfo/JInfo.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -39,42 +39,73 @@
  * and decides if the command should be satisfied using the VM attach mechanism
  * or an SA tool.
  */
-public class JInfo {
+final public class JInfo {
+    private boolean useSA = false;
+    private String[] args = null;
 
-    @SuppressWarnings("fallthrough")
-    public static void main(String[] args) throws Exception {
+    private JInfo(String[] args) throws IllegalArgumentException {
         if (args.length == 0) {
-            usage(1); // no arguments
+            throw new IllegalArgumentException();
         }
 
+        int argCopyIndex = 0;
         // First determine if we should launch SA or not
-        boolean useSA = false;
         if (args[0].equals("-F")) {
             // delete the -F
-            args = Arrays.copyOfRange(args, 1, args.length);
+            argCopyIndex = 1;
             useSA = true;
         } else if (args[0].equals("-flags")
-            || args[0].equals("-sysprops"))
+                   || args[0].equals("-sysprops"))
         {
             if (args.length == 2) {
-                if (!args[1].matches("[0-9]+")) {
+                if (!isPid(args[1])) {
                     // If args[1] doesn't parse to a number then
                     // it must be the SA debug server
                     // (otherwise it is the pid)
                     useSA = true;
                 }
-            }
-            if (args.length == 3) {
+            } else if (args.length == 3) {
                 // arguments include an executable and a core file
                 useSA = true;
+            } else {
+                throw new IllegalArgumentException();
             }
         } else if (!args[0].startsWith("-")) {
             if (args.length == 2) {
                 // the only arguments are an executable and a core file
                 useSA = true;
+            } else if (args.length == 1) {
+                if (!isPid(args[0])) {
+                    // The only argument is not a PID; it must be SA debug
+                    // server
+                    useSA = true;
+                }
+            } else {
+                throw new IllegalArgumentException();
             }
-        } else if (args[0].equals("-h")
-                || args[0].equals("-help")) {
+        } else if (args[0].equals("-h") || args[0].equals("-help")) {
+            if (args.length > 1) {
+                throw new IllegalArgumentException();
+            }
+        } else if (args[0].equals("-flag")) {
+            if (args.length == 3) {
+                if (!isPid(args[2])) {
+                    throw new IllegalArgumentException();
+                }
+            } else {
+                throw new IllegalArgumentException();
+            }
+        } else {
+            throw new IllegalArgumentException();
+        }
+
+        this.args = Arrays.copyOfRange(args, argCopyIndex, args.length);
+    }
+
+    @SuppressWarnings("fallthrough")
+    private void execute() throws Exception {
+        if (args[0].equals("-h")
+            || args[0].equals("-help")) {
             usage(0);
         }
 
@@ -87,55 +118,69 @@
             }
 
             // invoke SA which does it's own argument parsing
-            runTool(args);
+            runTool();
 
         } else {
             // Now we can parse arguments for the non-SA case
             String pid = null;
 
             switch(args[0]) {
-            case "-flag":
-                if (args.length != 3) {
-                    usage(1);
-                }
-                String option = args[1];
-                pid = args[2];
-                flag(pid, option);
-                break;
-            case "-flags":
-                if (args.length != 2) {
-                    usage(1);
-                }
-                pid = args[1];
-                flags(pid);
-                break;
-            case "-sysprops":
-                if (args.length != 2) {
-                    usage(1);
-                }
-                pid = args[1];
-                sysprops(pid);
-                break;
-            case "-help":
-            case "-h":
-                usage(0);
-                // Fall through
-            default:
-               if (args.length == 1) {
-                   // no flags specified, we do -sysprops and -flags
-                   pid = args[0];
-                   sysprops(pid);
-                   System.out.println();
-                   flags(pid);
-               } else {
-                   usage(1);
-               }
+                case "-flag":
+                    if (args.length != 3) {
+                        usage(1);
+                    }
+                    String option = args[1];
+                    pid = args[2];
+                    flag(pid, option);
+                    break;
+                case "-flags":
+                    if (args.length != 2) {
+                        usage(1);
+                    }
+                    pid = args[1];
+                    flags(pid);
+                    break;
+                case "-sysprops":
+                    if (args.length != 2) {
+                        usage(1);
+                    }
+                    pid = args[1];
+                    sysprops(pid);
+                    break;
+                case "-help":
+                case "-h":
+                    usage(0);
+                    // Fall through
+                default:
+                    if (args.length == 1) {
+                        // no flags specified, we do -sysprops and -flags
+                        pid = args[0];
+                        sysprops(pid);
+                        System.out.println();
+                        flags(pid);
+                    } else {
+                        usage(1);
+                    }
             }
         }
     }
 
+    public static void main(String[] args) throws Exception {
+        JInfo jinfo = null;
+        try {
+            jinfo = new JInfo(args);
+            jinfo.execute();
+        } catch (IllegalArgumentException e) {
+            usage(1);
+        }
+    }
+
+    private static boolean isPid(String arg) {
+        return arg.matches("[0-9]+");
+    }
+
     // Invoke SA tool with the given arguments
-    private static void runTool(String args[]) throws Exception {
+    private void runTool() throws Exception {
         String tool = "sun.jvm.hotspot.tools.JInfo";
         // Tool not available on this platform.
         Class<?> c = loadClass(tool);
--- a/jdk/src/share/demo/nio/zipfs/Demo.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,709 +0,0 @@
-/*
- * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.spi.*;
-import java.nio.file.attribute.*;
-import java.net.*;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
-/*
- * ZipFileSystem usage demo
- *
- * java Demo action ZipfileName [...]
- *
- * @author Xueming Shen
- */
-
-public class Demo {
-
-    static enum Action {
-        rename,          // <java Demo rename zipfile src dst>
-                         // rename entry src to dst inside zipfile
-
-        movein,          // <java Demo movein zipfile src dst>
-                         // move an external src file into zipfile
-                         // as entry dst
-
-        moveout,         // <java Demo moveout zipfile src dst>
-                         // move a zipfile entry src out to dst
-
-        copy,            // <java Demo copy zipfile src dst>
-                         // copy entry src to dst inside zipfile
-
-        copyin,          // <java Demo copyin zipfile src dst>
-                         // copy an external src file into zipfile
-                         // as entry dst
-
-        copyin_attrs,    // <java Demo copyin_attrs zipfile src dst>
-                         // copy an external src file into zipfile
-                         // as entry dst, with attributes (timestamp)
-
-        copyout,         // <java Demo copyout zipfile src dst>
-                         // copy zipfile entry src" out to file dst
-
-        copyout_attrs,   // <java Demo copyout_attrs zipfile src dst>
-
-        zzmove,          // <java Demo zzmove zfsrc zfdst path>
-                         // move entry path/dir from zfsrc to zfdst
-
-        zzcopy,          // <java Demo zzcopy zfsrc zfdst path>
-                         // copy path from zipfile zfsrc to zipfile
-                         // zfdst
-
-        attrs,           // <java Demo attrs zipfile path>
-                         // printout the attributes of entry path
-
-        attrsspace,      // <java Demo attrsspace zipfile path>
-                         // printout the storespace attrs of entry path
-
-        setmtime,        // <java Demo setmtime zipfile "MM/dd/yy-HH:mm:ss" path...>
-                         // set the lastModifiedTime of entry path
-
-        setatime,        // <java Demo setatime zipfile "MM/dd/yy-HH:mm:ss" path...>
-        setctime,        // <java Demo setctime zipfile "MM/dd/yy-HH:mm:ss" path...>
-
-        lsdir,           // <java Demo lsdir zipfile dir>
-                         // list dir's direct child files/dirs
-
-        mkdir,           // <java Demo mkdir zipfile dir>
-
-        mkdirs,          // <java Demo mkdirs zipfile dir>
-
-        rmdirs,          // <java Demo rmdirs zipfile dir>
-
-        list,            // <java Demo list zipfile [dir]>
-                         // recursively list all entries of dir
-                         // via DirectoryStream
-
-        tlist,           // <java Demo tlist zipfile [dir]>
-                         // list with buildDirTree=true
-
-        vlist,           // <java Demo vlist zipfile [dir]>
-                         // recursively verbose list all entries of
-                         // dir via DirectoryStream
-
-        walk,            // <java Demo walk zipfile [dir]>
-                         // recursively walk all entries of dir
-                         // via Files.walkFileTree
-
-        twalk,           // <java Demo twalk zipfile [dir]>
-                         // walk with buildDirTree=true
-
-        extract,         // <java Demo extract zipfile file [...]>
-
-        update,          // <java Demo extract zipfile file [...]>
-
-        delete,          // <java Demo delete zipfile file [...]>
-
-        add,             // <java Demo add zipfile file [...]>
-
-        create,          // <java Demo create zipfile file [...]>
-                         // create a new zipfile if it doesn't exit
-                         // and then add the file(s) into it.
-
-        attrs2,          // <java Demo attrs2 zipfile file [...]>
-                         // test different ways to print attrs
-
-        prof,
-    }
-
-    public static void main(String[] args) throws Throwable {
-        FileSystemProvider provider = getZipFSProvider();
-        if (provider == null) {
-            System.err.println("ZIP filesystem provider is not installed");
-            System.exit(1);
-        }
-
-        Action action = Action.valueOf(args[0]);
-        Map<String, Object> env = env = new HashMap<>();
-        if (action == Action.create)
-            env.put("create", "true");
-        try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) {
-            Path path, src, dst;
-            switch (action) {
-            case rename:
-                src = fs.getPath(args[2]);
-                dst = fs.getPath(args[3]);
-                Files.move(src, dst);
-                break;
-            case moveout:
-                src = fs.getPath(args[2]);
-                dst = Paths.get(args[3]);
-                Files.move(src, dst);
-                break;
-            case movein:
-                src = Paths.get(args[2]);
-                dst = fs.getPath(args[3]);
-                Files.move(src, dst);
-                break;
-            case copy:
-                src = fs.getPath(args[2]);
-                dst = fs.getPath(args[3]);
-                Files.copy(src, dst);
-                break;
-            case copyout:
-                src = fs.getPath(args[2]);
-                dst = Paths.get(args[3]);
-                Files.copy(src, dst);
-                break;
-            case copyin:
-                src = Paths.get(args[2]);
-                dst = fs.getPath(args[3]);
-                Files.copy(src, dst);
-                break;
-            case copyin_attrs:
-                src = Paths.get(args[2]);
-                dst = fs.getPath(args[3]);
-                Files.copy(src, dst, COPY_ATTRIBUTES);
-                break;
-            case copyout_attrs:
-                src = fs.getPath(args[2]);
-                dst = Paths.get(args[3]);
-                Files.copy(src, dst, COPY_ATTRIBUTES);
-                break;
-            case zzmove:
-                try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
-                    z2zmove(fs, fs2, args[3]);
-                }
-                break;
-            case zzcopy:
-                try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
-                    z2zcopy(fs, fs2, args[3]);
-                }
-                break;
-            case attrs:
-                for (int i = 2; i < args.length; i++) {
-                    path = fs.getPath(args[i]);
-                    System.out.println(path);
-                    System.out.println(
-                        Files.readAttributes(path, BasicFileAttributes.class).toString());
-                }
-                break;
-            case setmtime:
-                DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
-                Date newDatetime = df.parse(args[2]);
-                for (int i = 3; i < args.length; i++) {
-                    path = fs.getPath(args[i]);
-                    Files.setAttribute(path, "lastModifiedTime",
-                                       FileTime.fromMillis(newDatetime.getTime()));
-                    System.out.println(
-                        Files.readAttributes(path, BasicFileAttributes.class).toString());
-                }
-                break;
-            case setctime:
-                df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
-                newDatetime = df.parse(args[2]);
-                for (int i = 3; i < args.length; i++) {
-                    path = fs.getPath(args[i]);
-                    Files.setAttribute(path, "creationTime",
-                                       FileTime.fromMillis(newDatetime.getTime()));
-                    System.out.println(
-                        Files.readAttributes(path, BasicFileAttributes.class).toString());
-                }
-                break;
-            case setatime:
-                df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
-                newDatetime = df.parse(args[2]);
-                for (int i = 3; i < args.length; i++) {
-                    path = fs.getPath(args[i]);
-                    Files.setAttribute(path, "lastAccessTime",
-                                       FileTime.fromMillis(newDatetime.getTime()));
-                    System.out.println(
-                        Files.readAttributes(path, BasicFileAttributes.class).toString());
-                }
-                break;
-            case attrsspace:
-                path = fs.getPath("/");
-                FileStore fstore = Files.getFileStore(path);
-                System.out.printf("filestore[%s]%n", fstore.name());
-                System.out.printf("    totalSpace: %d%n",
-                                  (Long)fstore.getAttribute("totalSpace"));
-                System.out.printf("   usableSpace: %d%n",
-                                  (Long)fstore.getAttribute("usableSpace"));
-                System.out.printf("  unallocSpace: %d%n",
-                                  (Long)fstore.getAttribute("unallocatedSpace"));
-                break;
-            case list:
-            case tlist:
-                if (args.length < 3)
-                    list(fs.getPath("/"), false);
-                else
-                    list(fs.getPath(args[2]), false);
-                break;
-            case vlist:
-                if (args.length < 3)
-                    list(fs.getPath("/"), true);
-                else
-                    list(fs.getPath(args[2]), true);
-                break;
-            case twalk:
-            case walk:
-                walk(fs.getPath((args.length > 2)? args[2] : "/"));
-                break;
-            case extract:
-                if (args.length == 2) {
-                     extract(fs, "/");
-                } else {
-                    for (int i = 2; i < args.length; i++) {
-                        extract(fs, args[i]);
-                    }
-                }
-                break;
-            case delete:
-                for (int i = 2; i < args.length; i++)
-                    Files.delete(fs.getPath(args[i]));
-                break;
-            case create:
-            case add:
-            case update:
-                for (int i = 2; i < args.length; i++) {
-                    update(fs, args[i]);
-                }
-                break;
-            case lsdir:
-                path = fs.getPath(args[2]);
-                final String fStr = (args.length > 3)?args[3]:"";
-                try (DirectoryStream<Path> ds = Files.newDirectoryStream(path,
-                    new DirectoryStream.Filter<Path>() {
-                        @Override
-                        public boolean accept(Path path) {
-                            return path.toString().contains(fStr);
-                        }
-                    }))
-                {
-                    for (Path p : ds)
-                        System.out.println(p);
-                }
-                break;
-            case mkdir:
-                Files.createDirectory(fs.getPath(args[2]));
-                break;
-            case mkdirs:
-                mkdirs(fs.getPath(args[2]));
-                break;
-            case attrs2:
-                for (int i = 2; i < args.length; i++) {
-                    path = fs.getPath(args[i]);
-                    System.out.printf("%n%s%n", path);
-                    System.out.println("-------(1)---------");
-                    System.out.println(
-                        Files.readAttributes(path, BasicFileAttributes.class).toString());
-                    System.out.println("-------(2)---------");
-                    Map<String, Object> map = Files.readAttributes(path, "zip:*");
-                    for (Map.Entry<String, Object> e : map.entrySet()) {
-                        System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
-                    }
-                    System.out.println("-------(3)---------");
-                    map = Files.readAttributes(path, "size,lastModifiedTime,isDirectory");
-                    for (Map.Entry<String, ?> e : map.entrySet()) {
-                        System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
-                    }
-                }
-                break;
-            case prof:
-                list(fs.getPath("/"), false);
-                while (true) {
-                    Thread.sleep(10000);
-                    //list(fs.getPath("/"), true);
-                    System.out.println("sleeping...");
-                }
-            }
-        } catch (Exception x) {
-            x.printStackTrace();
-        }
-    }
-
-    private static FileSystemProvider getZipFSProvider() {
-        for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
-            if ("jar".equals(provider.getScheme()))
-                return provider;
-        }
-        return null;
-    }
-
-    @SuppressWarnings("unused")
-    /**
-     * Not used in demo, but included for demonstrational purposes.
-     */
-    private static byte[] getBytes(String name) {
-        return name.getBytes();
-    }
-
-    @SuppressWarnings("unused")
-    /**
-     * Not used in demo, but included for demonstrational purposes.
-     */
-    private static String getString(byte[] name) {
-        return new String(name);
-    }
-
-    private static void walk(Path path) throws IOException
-    {
-        Files.walkFileTree(
-            path,
-            new SimpleFileVisitor<Path>() {
-                private int indent = 0;
-                private void indent() {
-                    int n = 0;
-                    while (n++ < indent)
-                        System.out.printf(" ");
-                }
-
-                @Override
-                public FileVisitResult visitFile(Path file,
-                                                 BasicFileAttributes attrs)
-                {
-                    indent();
-                    System.out.printf("%s%n", file.getFileName().toString());
-                    return FileVisitResult.CONTINUE;
-                }
-
-                @Override
-                public FileVisitResult preVisitDirectory(Path dir,
-                                                         BasicFileAttributes attrs)
-                {
-                    indent();
-                    System.out.printf("[%s]%n", dir.toString());
-                    indent += 2;
-                    return FileVisitResult.CONTINUE;
-                }
-
-                @Override
-                public FileVisitResult postVisitDirectory(Path dir,
-                                                          IOException ioe)
-                {
-                    indent -= 2;
-                    return FileVisitResult.CONTINUE;
-                }
-        });
-    }
-
-    private static void update(FileSystem fs, String path) throws Throwable{
-        Path src = FileSystems.getDefault().getPath(path);
-        if (Files.isDirectory(src)) {
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
-                for (Path child : ds)
-                    update(fs, child.toString());
-            }
-        } else {
-            Path dst = fs.getPath(path);
-            Path parent = dst.getParent();
-            if (parent != null && Files.notExists(parent))
-                mkdirs(parent);
-            Files.copy(src, dst, REPLACE_EXISTING);
-        }
-    }
-
-    private static void extract(FileSystem fs, String path) throws Throwable{
-        Path src = fs.getPath(path);
-        if (Files.isDirectory(src)) {
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
-                for (Path child : ds)
-                    extract(fs, child.toString());
-            }
-        } else {
-            if (path.startsWith("/"))
-                path = path.substring(1);
-            Path dst = FileSystems.getDefault().getPath(path);
-            Path parent = dst.getParent();
-            if (Files.notExists(parent))
-                mkdirs(parent);
-            Files.copy(src, dst, REPLACE_EXISTING);
-        }
-    }
-
-    // use DirectoryStream
-    private static void z2zcopy(FileSystem src, FileSystem dst, String path)
-        throws IOException
-    {
-        Path srcPath = src.getPath(path);
-        Path dstPath = dst.getPath(path);
-
-        if (Files.isDirectory(srcPath)) {
-            if (!Files.exists(dstPath)) {
-                try {
-                    mkdirs(dstPath);
-                } catch (FileAlreadyExistsException x) {}
-            }
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
-                for (Path child : ds) {
-                    z2zcopy(src, dst,
-                            path + (path.endsWith("/")?"":"/") + child.getFileName());
-                }
-            }
-        } else {
-            //System.out.println("copying..." + path);
-            Files.copy(srcPath, dstPath);
-        }
-    }
-
-    // use TreeWalk to move
-    private static void z2zmove(FileSystem src, FileSystem dst, String path)
-        throws IOException
-    {
-        final Path srcPath = src.getPath(path).toAbsolutePath();
-        final Path dstPath = dst.getPath(path).toAbsolutePath();
-
-        Files.walkFileTree(srcPath, new SimpleFileVisitor<Path>() {
-
-            @Override
-            public FileVisitResult visitFile(Path file,
-                                            BasicFileAttributes attrs)
-            {
-                Path dst = srcPath.relativize(file);
-                dst = dstPath.resolve(dst);
-                try {
-                    Path parent = dstPath.getParent();
-                    if (parent != null && Files.notExists(parent))
-                        mkdirs(parent);
-                    Files.move(file, dst);
-                } catch (IOException x) {
-                    x.printStackTrace();
-                }
-                return FileVisitResult.CONTINUE;
-            }
-
-            @Override
-            public FileVisitResult preVisitDirectory(Path dir,
-                                                     BasicFileAttributes attrs)
-            {
-                Path dst = srcPath.relativize(dir);
-                dst = dstPath.resolve(dst);
-                try {
-
-                    if (Files.notExists(dst))
-                        mkdirs(dst);
-                } catch (IOException x) {
-                    x.printStackTrace();
-                }
-                return FileVisitResult.CONTINUE;
-            }
-
-            @Override
-            public FileVisitResult postVisitDirectory(Path dir,
-                                                      IOException ioe)
-                throws IOException
-            {
-                try {
-                    Files.delete(dir);
-                } catch (IOException x) {
-                    //x.printStackTrace();
-                }
-                return FileVisitResult.CONTINUE;
-            }
-        });
-
-    }
-
-    private static void mkdirs(Path path) throws IOException {
-        path = path.toAbsolutePath();
-        Path parent = path.getParent();
-        if (parent != null) {
-            if (Files.notExists(parent))
-                mkdirs(parent);
-        }
-        Files.createDirectory(path);
-    }
-
-    @SuppressWarnings("unused")
-    /**
-     * Not used in demo, but included for demonstrational purposes.
-     */
-    private static void rmdirs(Path path) throws IOException {
-        while (path != null && path.getNameCount() != 0) {
-            Files.delete(path);
-            path = path.getParent();
-        }
-    }
-
-    private static void list(Path path, boolean verbose ) throws IOException {
-        if (!"/".equals(path.toString())) {
-           System.out.printf("  %s%n", path.toString());
-           if (verbose)
-                System.out.println(Files.readAttributes(path, BasicFileAttributes.class).toString());
-        }
-        if (Files.notExists(path))
-            return;
-        if (Files.isDirectory(path)) {
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
-                for (Path child : ds)
-                    list(child, verbose);
-            }
-        }
-    }
-
-    @SuppressWarnings("unused")
-    /**
-     * Checks that the content of two paths are equal.
-     * Not used in demo, but included for demonstrational purposes.
-     */
-    private static void checkEqual(Path src, Path dst) throws IOException
-    {
-        //System.out.printf("checking <%s> vs <%s>...%n",
-        //                  src.toString(), dst.toString());
-
-        //streams
-        byte[] bufSrc = new byte[8192];
-        byte[] bufDst = new byte[8192];
-        try (InputStream isSrc = Files.newInputStream(src);
-             InputStream isDst = Files.newInputStream(dst))
-        {
-            int nSrc = 0;
-            while ((nSrc = isSrc.read(bufSrc)) != -1) {
-                int nDst = 0;
-                while (nDst < nSrc) {
-                    int n = isDst.read(bufDst, nDst, nSrc - nDst);
-                    if (n == -1) {
-                        System.out.printf("checking <%s> vs <%s>...%n",
-                                          src.toString(), dst.toString());
-                        throw new RuntimeException("CHECK FAILED!");
-                    }
-                    nDst += n;
-                }
-                while (--nSrc >= 0) {
-                    if (bufSrc[nSrc] != bufDst[nSrc]) {
-                        System.out.printf("checking <%s> vs <%s>...%n",
-                                          src.toString(), dst.toString());
-                        throw new RuntimeException("CHECK FAILED!");
-                    }
-                    nSrc--;
-                }
-            }
-        }
-
-        // channels
-
-        try (SeekableByteChannel chSrc = Files.newByteChannel(src);
-             SeekableByteChannel chDst = Files.newByteChannel(dst))
-        {
-            if (chSrc.size() != chDst.size()) {
-                System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
-                                  chSrc.toString(), chSrc.size(),
-                                  chDst.toString(), chDst.size());
-                throw new RuntimeException("CHECK FAILED!");
-            }
-            ByteBuffer bbSrc = ByteBuffer.allocate(8192);
-            ByteBuffer bbDst = ByteBuffer.allocate(8192);
-
-            int nSrc = 0;
-            while ((nSrc = chSrc.read(bbSrc)) != -1) {
-                int nDst = chDst.read(bbDst);
-                if (nSrc != nDst) {
-                    System.out.printf("checking <%s> vs <%s>...%n",
-                                      src.toString(), dst.toString());
-                    throw new RuntimeException("CHECK FAILED!");
-                }
-                while (--nSrc >= 0) {
-                    if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
-                        System.out.printf("checking <%s> vs <%s>...%n",
-                                          src.toString(), dst.toString());
-                        throw new RuntimeException("CHECK FAILED!");
-                    }
-                    nSrc--;
-                }
-                bbSrc.flip();
-                bbDst.flip();
-            }
-        } catch (IOException x) {
-            x.printStackTrace();
-        }
-    }
-
-    private static void fchCopy(Path src, Path dst) throws IOException
-    {
-        Set<OpenOption> read = new HashSet<>();
-        read.add(READ);
-        Set<OpenOption> openwrite = new HashSet<>();
-        openwrite.add(CREATE_NEW);
-        openwrite.add(WRITE);
-
-        try (FileChannel srcFc = src.getFileSystem().provider().newFileChannel(src, read);
-             FileChannel dstFc = dst.getFileSystem().provider().newFileChannel(dst, openwrite))
-        {
-            ByteBuffer bb = ByteBuffer.allocate(8192);
-            while (srcFc.read(bb) >= 0) {
-                bb.flip();
-                dstFc.write(bb);
-                bb.clear();
-            }
-        }
-    }
-
-    private static void chCopy(Path src, Path dst) throws IOException
-    {
-        Set<OpenOption> read = new HashSet<>();
-        read.add(READ);
-        Set<OpenOption> openwrite = new HashSet<>();
-        openwrite.add(CREATE_NEW);
-        openwrite.add(WRITE);
-
-        try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
-             SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
-        {
-            ByteBuffer bb = ByteBuffer.allocate(8192);
-            while (srcCh.read(bb) >= 0) {
-                bb.flip();
-                dstCh.write(bb);
-                bb.clear();
-            }
-        }
-    }
-
-    private static void streamCopy(Path src, Path dst) throws IOException
-    {
-        byte[] buf = new byte[8192];
-        try (InputStream isSrc = Files.newInputStream(src);
-             OutputStream osDst = Files.newOutputStream(dst))
-        {
-            int n = 0;
-            while ((n = isSrc.read(buf)) != -1) {
-                osDst.write(buf, 0, n);
-            }
-        }
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/README.txt	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-ZipFileSystem is a file system provider that treats the contents of a zip or
-JAR file as a java.nio.file.FileSystem.
-
-The factory methods defined by the java.nio.file.FileSystems class can be
-used to create a FileSystem, eg:
-
-   // use file type detection
-   Path jarfile = Paths.get("foo.jar");
-   FileSystem fs = FileSystems.newFileSystem(jarfile, null);
-
--or
-
-   // locate file system by the legacy JAR URL syntax
-   Map<String,?> env = Collections.emptyMap();
-   URI uri = URI.create("jar:file:/mydir/foo.jar");
-   FileSystem fs = FileSystems.newFileSystem(uri, env);
-
-Once a FileSystem is created then classes in the java.nio.file package
-can be used to access files in the zip/JAR file, eg:
-
-   Path mf = fs.getPath("/META-INF/MANIFEST.MF");
-   InputStream in = mf.newInputStream();
-
-See Demo.java for more interesting usages.
-
-
--- a/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-com.sun.nio.zipfs.ZipFileSystemProvider
-
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/JarFileSystemProvider.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.*;
-import java.nio.file.spi.*;
-import java.nio.file.attribute.*;
-import java.nio.file.spi.FileSystemProvider;
-
-import java.net.URI;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.nio.channels.FileChannel;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-public class JarFileSystemProvider extends ZipFileSystemProvider
-{
-
-    @Override
-    public String getScheme() {
-        return "jar";
-    }
-
-    @Override
-    protected Path uriToPath(URI uri) {
-        String scheme = uri.getScheme();
-        if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
-            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
-        }
-        try {
-            String uristr = uri.toString();
-            int end = uristr.indexOf("!/");
-            uristr = uristr.substring(4, (end == -1) ? uristr.length() : end);
-            uri = new URI(uristr);
-            return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
-                        .toAbsolutePath();
-        } catch (URISyntaxException e) {
-            throw new AssertionError(e); //never thrown
-        }
-    }
-
-    @Override
-    public Path getPath(URI uri) {
-        FileSystem fs = getFileSystem(uri);
-        String path = uri.getFragment();
-        if (path == null) {
-            String uristr = uri.toString();
-            int off = uristr.indexOf("!/");
-            if (off != -1)
-                path = uristr.substring(off + 2);
-        }
-        if (path != null)
-            return fs.getPath(path);
-        throw new IllegalArgumentException("URI: "
-            + uri
-            + " does not contain path fragment ex. jar:///c:/foo.zip!/BAR");
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipCoder.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.util.Arrays;
-
-/**
- * Utility class for zipfile name and comment decoding and encoding
- *
- * @author  Xueming Shen
- */
-
-final class ZipCoder {
-
-    String toString(byte[] ba, int length) {
-        CharsetDecoder cd = decoder().reset();
-        int len = (int)(length * cd.maxCharsPerByte());
-        char[] ca = new char[len];
-        if (len == 0)
-            return new String(ca);
-        ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
-        CharBuffer cb = CharBuffer.wrap(ca);
-        CoderResult cr = cd.decode(bb, cb, true);
-        if (!cr.isUnderflow())
-            throw new IllegalArgumentException(cr.toString());
-        cr = cd.flush(cb);
-        if (!cr.isUnderflow())
-            throw new IllegalArgumentException(cr.toString());
-        return new String(ca, 0, cb.position());
-    }
-
-    String toString(byte[] ba) {
-        return toString(ba, ba.length);
-    }
-
-    byte[] getBytes(String s) {
-        CharsetEncoder ce = encoder().reset();
-        char[] ca = s.toCharArray();
-        int len = (int)(ca.length * ce.maxBytesPerChar());
-        byte[] ba = new byte[len];
-        if (len == 0)
-            return ba;
-        ByteBuffer bb = ByteBuffer.wrap(ba);
-        CharBuffer cb = CharBuffer.wrap(ca);
-        CoderResult cr = ce.encode(cb, bb, true);
-        if (!cr.isUnderflow())
-            throw new IllegalArgumentException(cr.toString());
-        cr = ce.flush(bb);
-        if (!cr.isUnderflow())
-            throw new IllegalArgumentException(cr.toString());
-        if (bb.position() == ba.length)  // defensive copy?
-            return ba;
-        else
-            return Arrays.copyOf(ba, bb.position());
-    }
-
-    // assume invoked only if "this" is not utf8
-    byte[] getBytesUTF8(String s) {
-        if (isutf8)
-            return getBytes(s);
-        if (utf8 == null)
-            utf8 = new ZipCoder(Charset.forName("UTF-8"));
-        return utf8.getBytes(s);
-    }
-
-    String toStringUTF8(byte[] ba, int len) {
-        if (isutf8)
-            return toString(ba, len);
-        if (utf8 == null)
-            utf8 = new ZipCoder(Charset.forName("UTF-8"));
-        return utf8.toString(ba, len);
-    }
-
-    boolean isUTF8() {
-        return isutf8;
-    }
-
-    private Charset cs;
-    private boolean isutf8;
-    private ZipCoder utf8;
-
-    private ZipCoder(Charset cs) {
-        this.cs = cs;
-        this.isutf8 = cs.name().equals("UTF-8");
-    }
-
-    static ZipCoder get(Charset charset) {
-        return new ZipCoder(charset);
-    }
-
-    static ZipCoder get(String csn) {
-        try {
-            return new ZipCoder(Charset.forName(csn));
-        } catch (Throwable t) {
-            t.printStackTrace();
-        }
-        return new ZipCoder(Charset.defaultCharset());
-    }
-
-    private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>();
-    private final ThreadLocal<CharsetEncoder> encTL = new ThreadLocal<>();
-
-    private CharsetDecoder decoder() {
-        CharsetDecoder dec = decTL.get();
-        if (dec == null) {
-            dec = cs.newDecoder()
-              .onMalformedInput(CodingErrorAction.REPORT)
-              .onUnmappableCharacter(CodingErrorAction.REPORT);
-            decTL.set(dec);
-        }
-        return dec;
-    }
-
-    private CharsetEncoder encoder() {
-        CharsetEncoder enc = encTL.get();
-        if (enc == null) {
-            enc = cs.newEncoder()
-              .onMalformedInput(CodingErrorAction.REPORT)
-              .onUnmappableCharacter(CodingErrorAction.REPORT);
-            encTL.set(enc);
-        }
-        return enc;
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipConstants.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-
-/**
- *
- * @author Xueming Shen
- */
-
-class ZipConstants {
-    /*
-     * Compression methods
-     */
-    static final int METHOD_STORED     = 0;
-    static final int METHOD_DEFLATED   = 8;
-    static final int METHOD_DEFLATED64 = 9;
-    static final int METHOD_BZIP2      = 12;
-    static final int METHOD_LZMA       = 14;
-    static final int METHOD_LZ77       = 19;
-    static final int METHOD_AES        = 99;
-
-    /*
-     * General purpose big flag
-     */
-    static final int FLAG_ENCRYPTED  = 0x01;
-    static final int FLAG_DATADESCR  = 0x08;    // crc, size and csize in dd
-    static final int FLAG_EFS        = 0x800;   // If this bit is set the filename and
-                                                // comment fields for this file must be
-                                                // encoded using UTF-8.
-    /*
-     * Header signatures
-     */
-    static long LOCSIG = 0x04034b50L;   // "PK\003\004"
-    static long EXTSIG = 0x08074b50L;   // "PK\007\008"
-    static long CENSIG = 0x02014b50L;   // "PK\001\002"
-    static long ENDSIG = 0x06054b50L;   // "PK\005\006"
-
-    /*
-     * Header sizes in bytes (including signatures)
-     */
-    static final int LOCHDR = 30;       // LOC header size
-    static final int EXTHDR = 16;       // EXT header size
-    static final int CENHDR = 46;       // CEN header size
-    static final int ENDHDR = 22;       // END header size
-
-    /*
-     * Local file (LOC) header field offsets
-     */
-    static final int LOCVER = 4;        // version needed to extract
-    static final int LOCFLG = 6;        // general purpose bit flag
-    static final int LOCHOW = 8;        // compression method
-    static final int LOCTIM = 10;       // modification time
-    static final int LOCCRC = 14;       // uncompressed file crc-32 value
-    static final int LOCSIZ = 18;       // compressed size
-    static final int LOCLEN = 22;       // uncompressed size
-    static final int LOCNAM = 26;       // filename length
-    static final int LOCEXT = 28;       // extra field length
-
-    /*
-     * Extra local (EXT) header field offsets
-     */
-    static final int EXTCRC = 4;        // uncompressed file crc-32 value
-    static final int EXTSIZ = 8;        // compressed size
-    static final int EXTLEN = 12;       // uncompressed size
-
-    /*
-     * Central directory (CEN) header field offsets
-     */
-    static final int CENVEM = 4;        // version made by
-    static final int CENVER = 6;        // version needed to extract
-    static final int CENFLG = 8;        // encrypt, decrypt flags
-    static final int CENHOW = 10;       // compression method
-    static final int CENTIM = 12;       // modification time
-    static final int CENCRC = 16;       // uncompressed file crc-32 value
-    static final int CENSIZ = 20;       // compressed size
-    static final int CENLEN = 24;       // uncompressed size
-    static final int CENNAM = 28;       // filename length
-    static final int CENEXT = 30;       // extra field length
-    static final int CENCOM = 32;       // comment length
-    static final int CENDSK = 34;       // disk number start
-    static final int CENATT = 36;       // internal file attributes
-    static final int CENATX = 38;       // external file attributes
-    static final int CENOFF = 42;       // LOC header offset
-
-    /*
-     * End of central directory (END) header field offsets
-     */
-    static final int ENDSUB = 8;        // number of entries on this disk
-    static final int ENDTOT = 10;       // total number of entries
-    static final int ENDSIZ = 12;       // central directory size in bytes
-    static final int ENDOFF = 16;       // offset of first CEN header
-    static final int ENDCOM = 20;       // zip file comment length
-
-    /*
-     * ZIP64 constants
-     */
-    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
-    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
-    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
-    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
-    static final int  ZIP64_EXTHDR = 24;           // EXT header size
-    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
-
-    static final int  ZIP64_MINVAL32 = 0xFFFF;
-    static final long ZIP64_MINVAL = 0xFFFFFFFFL;
-
-    /*
-     * Zip64 End of central directory (END) header field offsets
-     */
-    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
-    static final int  ZIP64_ENDVEM = 12;      // version made by
-    static final int  ZIP64_ENDVER = 14;      // version needed to extract
-    static final int  ZIP64_ENDNMD = 16;      // number of this disk
-    static final int  ZIP64_ENDDSK = 20;      // disk number of start
-    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
-    static final int  ZIP64_ENDTOT = 32;      // total number of entries
-    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
-    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
-    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
-
-    /*
-     * Zip64 End of central directory locator field offsets
-     */
-    static final int  ZIP64_LOCDSK = 4;       // disk number start
-    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
-    static final int  ZIP64_LOCTOT = 16;      // total number of disks
-
-    /*
-     * Zip64 Extra local (EXT) header field offsets
-     */
-    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
-    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
-    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
-
-    /*
-     * Extra field header ID
-     */
-    static final int  EXTID_ZIP64 = 0x0001;      // ZIP64
-    static final int  EXTID_NTFS  = 0x000a;      // NTFS
-    static final int  EXTID_UNIX  = 0x000d;      // UNIX
-    static final int  EXTID_EFS   = 0x0017;      // Strong Encryption
-    static final int  EXTID_EXTT  = 0x5455;      // Info-ZIP Extended Timestamp
-
-    /*
-     * fields access methods
-     */
-    ///////////////////////////////////////////////////////
-    static final int CH(byte[] b, int n) {
-        return Byte.toUnsignedInt(b[n]);
-    }
-
-    static final int SH(byte[] b, int n) {
-        return Byte.toUnsignedInt(b[n]) | (Byte.toUnsignedInt(b[n + 1]) << 8);
-    }
-
-    static final long LG(byte[] b, int n) {
-        return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
-    }
-
-    static final long LL(byte[] b, int n) {
-        return (LG(b, n)) | (LG(b, n + 4) << 32);
-    }
-
-    static final long GETSIG(byte[] b) {
-        return LG(b, 0);
-    }
-
-    // local file (LOC) header fields
-    static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
-    static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
-    static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
-    static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
-    static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
-    static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
-    static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
-    static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
-    static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
-    static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
-
-    // extra local (EXT) header fields
-    static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
-    static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
-    static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
-
-    // end of central directory header (END) fields
-    static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
-    static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
-    static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
-    static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
-    static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
-    static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
-
-    // zip64 end of central directory recoder fields
-    static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
-    static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
-    static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
-    static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
-    static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
-
-    // central directory header (CEN) fields
-    static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
-    static final int  CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
-    static final int  CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
-    static final int  CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
-    static final int  CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
-    static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
-    static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
-    static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
-    static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
-    static final int  CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
-    static final int  CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
-    static final int  CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
-    static final int  CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
-    static final int  CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
-    static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
-    static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);}
-
-    /* The END header is followed by a variable length comment of size < 64k. */
-    static final long END_MAXLEN = 0xFFFF + ENDHDR;
-    static final int READBLOCKSZ = 128;
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipDirectoryStream.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.DirectoryStream;
-import java.nio.file.ClosedDirectoryStreamException;
-import java.nio.file.NotDirectoryException;
-import java.nio.file.Path;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import java.io.IOException;
-
-/**
- *
- * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
- */
-
-public class ZipDirectoryStream implements DirectoryStream<Path> {
-
-    private final ZipFileSystem zipfs;
-    private final byte[] path;
-    private final DirectoryStream.Filter<? super Path> filter;
-    private volatile boolean isClosed;
-    private volatile Iterator<Path> itr;
-
-    ZipDirectoryStream(ZipPath zipPath,
-                       DirectoryStream.Filter<? super java.nio.file.Path> filter)
-        throws IOException
-    {
-        this.zipfs = zipPath.getFileSystem();
-        this.path = zipPath.getResolvedPath();
-        this.filter = filter;
-        // sanity check
-        if (!zipfs.isDirectory(path))
-            throw new NotDirectoryException(zipPath.toString());
-    }
-
-    @Override
-    public synchronized Iterator<Path> iterator() {
-        if (isClosed)
-            throw new ClosedDirectoryStreamException();
-        if (itr != null)
-            throw new IllegalStateException("Iterator has already been returned");
-
-        try {
-            itr = zipfs.iteratorOf(path, filter);
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        }
-        return new Iterator<Path>() {
-            private Path next;
-            @Override
-            public boolean hasNext() {
-                if (isClosed)
-                    return false;
-                return itr.hasNext();
-            }
-
-            @Override
-            public synchronized Path next() {
-                if (isClosed)
-                    throw new NoSuchElementException();
-                return itr.next();
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
-
-    @Override
-    public synchronized void close() throws IOException {
-        isClosed = true;
-    }
-
-
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.attribute.*;
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/*
- * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
- */
-
-public class ZipFileAttributeView implements BasicFileAttributeView
-{
-    private static enum AttrID {
-        size,
-        creationTime,
-        lastAccessTime,
-        lastModifiedTime,
-        isDirectory,
-        isRegularFile,
-        isSymbolicLink,
-        isOther,
-        fileKey,
-        compressedSize,
-        crc,
-        method
-    };
-
-    private final ZipPath path;
-    private final boolean isZipView;
-
-    private ZipFileAttributeView(ZipPath path, boolean isZipView) {
-        this.path = path;
-        this.isZipView = isZipView;
-    }
-
-    static <V extends FileAttributeView> V get(ZipPath path, Class<V> type) {
-        if (type == null)
-            throw new NullPointerException();
-        if (type == BasicFileAttributeView.class)
-            return (V)new ZipFileAttributeView(path, false);
-        if (type == ZipFileAttributeView.class)
-            return (V)new ZipFileAttributeView(path, true);
-        return null;
-    }
-
-    static ZipFileAttributeView get(ZipPath path, String type) {
-        if (type == null)
-            throw new NullPointerException();
-        if (type.equals("basic"))
-            return new ZipFileAttributeView(path, false);
-        if (type.equals("zip"))
-            return new ZipFileAttributeView(path, true);
-        return null;
-    }
-
-    @Override
-    public String name() {
-        return isZipView ? "zip" : "basic";
-    }
-
-    public ZipFileAttributes readAttributes() throws IOException
-    {
-        return path.getAttributes();
-    }
-
-    @Override
-    public void setTimes(FileTime lastModifiedTime,
-                         FileTime lastAccessTime,
-                         FileTime createTime)
-        throws IOException
-    {
-        path.setTimes(lastModifiedTime, lastAccessTime, createTime);
-    }
-
-    void setAttribute(String attribute, Object value)
-        throws IOException
-    {
-        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);
-            return;
-        } catch (IllegalArgumentException x) {}
-        throw new UnsupportedOperationException("'" + attribute +
-            "' is unknown or read-only attribute");
-    }
-
-    Map<String, Object> readAttributes(String attributes)
-        throws IOException
-    {
-        ZipFileAttributes zfas = readAttributes();
-        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
-        if ("*".equals(attributes)) {
-            for (AttrID id : AttrID.values()) {
-                try {
-                    map.put(id.name(), attribute(id, zfas));
-                } catch (IllegalArgumentException x) {}
-            }
-        } else {
-            String[] as = attributes.split(",");
-            for (String a : as) {
-                try {
-                    map.put(a, attribute(AttrID.valueOf(a), zfas));
-                } catch (IllegalArgumentException x) {}
-            }
-        }
-        return map;
-    }
-
-    Object attribute(AttrID id, ZipFileAttributes zfas) {
-        switch (id) {
-        case size:
-            return zfas.size();
-        case creationTime:
-            return zfas.creationTime();
-        case lastAccessTime:
-            return zfas.lastAccessTime();
-        case lastModifiedTime:
-            return zfas.lastModifiedTime();
-        case isDirectory:
-            return zfas.isDirectory();
-        case isRegularFile:
-            return zfas.isRegularFile();
-        case isSymbolicLink:
-            return zfas.isSymbolicLink();
-        case isOther:
-            return zfas.isOther();
-        case fileKey:
-            return zfas.fileKey();
-        case compressedSize:
-            if (isZipView)
-                return zfas.compressedSize();
-            break;
-        case crc:
-            if (isZipView)
-                return zfas.crc();
-            break;
-        case method:
-            if (isZipView)
-                return zfas.method();
-            break;
-        }
-        return null;
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributes.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.FileTime;
-import java.util.Arrays;
-import java.util.Formatter;
-import static com.sun.nio.zipfs.ZipUtils.*;
-
-/**
- *
- * @author  Xueming Shen, Rajendra Gutupalli,Jaya Hangal
- */
-
-public class ZipFileAttributes implements BasicFileAttributes
-
-{
-    private final ZipFileSystem.Entry e;
-
-    ZipFileAttributes(ZipFileSystem.Entry e) {
-        this.e = e;
-    }
-
-    ///////// basic attributes ///////////
-    @Override
-    public FileTime creationTime() {
-        if (e.ctime != -1)
-            return FileTime.fromMillis(e.ctime);
-        return null;
-    }
-
-    @Override
-    public boolean isDirectory() {
-        return e.isDir();
-    }
-
-    @Override
-    public boolean isOther() {
-        return false;
-    }
-
-    @Override
-    public boolean isRegularFile() {
-        return !e.isDir();
-    }
-
-    @Override
-    public FileTime lastAccessTime() {
-        if (e.atime != -1)
-            return FileTime.fromMillis(e.atime);
-        return null;
-    }
-
-    @Override
-    public FileTime lastModifiedTime() {
-        return FileTime.fromMillis(e.mtime);
-    }
-
-    @Override
-    public long size() {
-        return e.size;
-    }
-
-    @Override
-    public boolean isSymbolicLink() {
-        return false;
-    }
-
-    @Override
-    public Object fileKey() {
-        return null;
-    }
-
-    ///////// zip entry attributes ///////////
-    public long compressedSize() {
-        return e.csize;
-    }
-
-    public long crc() {
-        return e.crc;
-    }
-
-    public int method() {
-        return e.method;
-    }
-
-    public byte[] extra() {
-        if (e.extra != null)
-            return Arrays.copyOf(e.extra, e.extra.length);
-        return null;
-    }
-
-    public byte[] comment() {
-        if (e.comment != null)
-            return Arrays.copyOf(e.comment, e.comment.length);
-        return null;
-    }
-
-    public String toString() {
-        StringBuilder sb = new StringBuilder(1024);
-        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("    crc             : %x%n", crc());
-        fm.format("    method          : %d%n", method());
-        fm.close();
-        return sb.toString();
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.FileStore;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.FileAttributeView;
-import java.nio.file.attribute.FileStoreAttributeView;
-import java.nio.file.attribute.BasicFileAttributeView;
-import java.util.Formatter;
-
-/*
- *
- * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
- */
-
-public class ZipFileStore extends FileStore {
-
-    private final ZipFileSystem zfs;
-
-    ZipFileStore(ZipPath zpath) {
-        this.zfs = zpath.getFileSystem();
-    }
-
-    @Override
-    public String name() {
-        return zfs.toString() + "/";
-    }
-
-    @Override
-    public String type() {
-        return "zipfs";
-    }
-
-    @Override
-    public boolean isReadOnly() {
-        return zfs.isReadOnly();
-    }
-
-    @Override
-    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
-        return (type == BasicFileAttributeView.class ||
-                type == ZipFileAttributeView.class);
-    }
-
-    @Override
-    public boolean supportsFileAttributeView(String name) {
-        return name.equals("basic") || name.equals("zip");
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
-        if (type == null)
-            throw new NullPointerException();
-        return (V)null;
-    }
-
-    @Override
-    public long getTotalSpace() throws IOException {
-         return new ZipFileStoreAttributes(this).totalSpace();
-    }
-
-    @Override
-    public long getUsableSpace() throws IOException {
-         return new ZipFileStoreAttributes(this).usableSpace();
-    }
-
-    @Override
-    public long getUnallocatedSpace() throws IOException {
-         return new ZipFileStoreAttributes(this).unallocatedSpace();
-    }
-
-    @Override
-    public Object getAttribute(String attribute) throws IOException {
-         if (attribute.equals("totalSpace"))
-               return getTotalSpace();
-         if (attribute.equals("usableSpace"))
-               return getUsableSpace();
-         if (attribute.equals("unallocatedSpace"))
-               return getUnallocatedSpace();
-         throw new UnsupportedOperationException("does not support the given attribute");
-    }
-
-    private static class ZipFileStoreAttributes {
-        final FileStore fstore;
-        final long size;
-
-        public ZipFileStoreAttributes(ZipFileStore fileStore)
-            throws IOException
-        {
-            Path path = FileSystems.getDefault().getPath(fileStore.name());
-            this.size = Files.size(path);
-            this.fstore = Files.getFileStore(path);
-        }
-
-        public long totalSpace() {
-            return size;
-        }
-
-        public long usableSpace() throws IOException {
-            if (!fstore.isReadOnly())
-                return fstore.getUsableSpace();
-            return 0;
-        }
-
-        public long unallocatedSpace()  throws IOException {
-            if (!fstore.isReadOnly())
-                return fstore.getUnallocatedSpace();
-            return 0;
-        }
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2398 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.nio.file.spi.*;
-import java.util.*;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.regex.Pattern;
-import java.util.zip.CRC32;
-import java.util.zip.Inflater;
-import java.util.zip.Deflater;
-import java.util.zip.InflaterInputStream;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.ZipException;
-import java.util.zip.ZipError;
-import static java.lang.Boolean.*;
-import static com.sun.nio.zipfs.ZipConstants.*;
-import static com.sun.nio.zipfs.ZipUtils.*;
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
-
-/**
- * A FileSystem built on a zip file
- *
- * @author Xueming Shen
- */
-
-public class ZipFileSystem extends FileSystem {
-
-    private final ZipFileSystemProvider provider;
-    private final ZipPath defaultdir;
-    private boolean readOnly = false;
-    private final Path zfpath;
-    private final ZipCoder zc;
-
-    // configurable by env map
-    private final String  defaultDir;    // default dir for the file system
-    private final String  nameEncoding;  // default encoding for name/comment
-    private final boolean useTempFile;   // use a temp file for newOS, default
-                                         // is to use BAOS for better performance
-    private final boolean createNew;     // create a new zip if not exists
-    private static final boolean isWindows =
-        System.getProperty("os.name").startsWith("Windows");
-
-    ZipFileSystem(ZipFileSystemProvider provider,
-                  Path zfpath,
-                  Map<String, ?> env)
-        throws IOException
-    {
-        // configurable env setup
-        this.createNew    = "true".equals(env.get("create"));
-        this.nameEncoding = env.containsKey("encoding") ?
-                            (String)env.get("encoding") : "UTF-8";
-        this.useTempFile  = TRUE.equals(env.get("useTempFile"));
-        this.defaultDir   = env.containsKey("default.dir") ?
-                            (String)env.get("default.dir") : "/";
-        if (this.defaultDir.charAt(0) != '/')
-            throw new IllegalArgumentException("default dir should be absolute");
-
-        this.provider = provider;
-        this.zfpath = zfpath;
-        if (Files.notExists(zfpath)) {
-            if (createNew) {
-                try (OutputStream os = Files.newOutputStream(zfpath, CREATE_NEW, WRITE)) {
-                    new END().write(os, 0);
-                }
-            } else {
-                throw new FileSystemNotFoundException(zfpath.toString());
-            }
-        }
-        // sm and existence check
-        zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
-        if (!Files.isWritable(zfpath))
-            this.readOnly = true;
-        this.zc = ZipCoder.get(nameEncoding);
-        this.defaultdir = new ZipPath(this, getBytes(defaultDir));
-        this.ch = Files.newByteChannel(zfpath, READ);
-        this.cen = initCEN();
-    }
-
-    @Override
-    public FileSystemProvider provider() {
-        return provider;
-    }
-
-    @Override
-    public String getSeparator() {
-        return "/";
-    }
-
-    @Override
-    public boolean isOpen() {
-        return isOpen;
-    }
-
-    @Override
-    public boolean isReadOnly() {
-        return readOnly;
-    }
-
-    private void checkWritable() throws IOException {
-        if (readOnly)
-            throw new ReadOnlyFileSystemException();
-    }
-
-    @Override
-    public Iterable<Path> getRootDirectories() {
-        ArrayList<Path> pathArr = new ArrayList<>();
-        pathArr.add(new ZipPath(this, new byte[]{'/'}));
-        return pathArr;
-    }
-
-    ZipPath getDefaultDir() {  // package private
-        return defaultdir;
-    }
-
-    @Override
-    public ZipPath 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 new ZipPath(this, getBytes(path));
-    }
-
-    @Override
-    public UserPrincipalLookupService getUserPrincipalLookupService() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public WatchService newWatchService() {
-        throw new UnsupportedOperationException();
-    }
-
-    FileStore getFileStore(ZipPath path) {
-        return new ZipFileStore(path);
-    }
-
-    @Override
-    public Iterable<FileStore> getFileStores() {
-        ArrayList<FileStore> list = new ArrayList<>(1);
-        list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'})));
-        return list;
-    }
-
-    private static final Set<String> supportedFileAttributeViews =
-            Collections.unmodifiableSet(
-                new HashSet<String>(Arrays.asList("basic", "zip")));
-
-    @Override
-    public Set<String> supportedFileAttributeViews() {
-        return supportedFileAttributeViews;
-    }
-
-    @Override
-    public String toString() {
-        return zfpath.toString();
-    }
-
-    Path getZipFile() {
-        return zfpath;
-    }
-
-    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.equals(GLOB_SYNTAX)) {
-            expr = toRegexPattern(input);
-        } else {
-            if (syntax.equals(REGEX_SYNTAX)) {
-                expr = input;
-            } else {
-                throw new UnsupportedOperationException("Syntax '" + syntax +
-                    "' not recognized");
-            }
-        }
-        // return matcher
-        final Pattern pattern = Pattern.compile(expr);
-        return new PathMatcher() {
-            @Override
-            public boolean matches(Path path) {
-                return pattern.matcher(path.toString()).matches();
-            }
-        };
-    }
-
-    @Override
-    public void close() throws IOException {
-        beginWrite();
-        try {
-            if (!isOpen)
-                return;
-            isOpen = false;             // set closed
-        } finally {
-            endWrite();
-        }
-        if (!streams.isEmpty()) {       // unlock and close all remaining streams
-            Set<InputStream> copy = new HashSet<>(streams);
-            for (InputStream is: copy)
-                is.close();
-        }
-        beginWrite();                   // lock and sync
-        try {
-            sync();
-            ch.close();                 // close the ch just in case no update
-        } finally {                     // and sync dose not close the ch
-            endWrite();
-        }
-
-        synchronized (inflaters) {
-            for (Inflater inf : inflaters)
-                inf.end();
-        }
-        synchronized (deflaters) {
-            for (Deflater def : deflaters)
-                def.end();
-        }
-
-        IOException ioe = null;
-        synchronized (tmppaths) {
-            for (Path p: tmppaths) {
-                try {
-                    Files.deleteIfExists(p);
-                } catch (IOException x) {
-                    if (ioe == null)
-                        ioe = x;
-                    else
-                        ioe.addSuppressed(x);
-                }
-            }
-        }
-        provider.removeFileSystem(zfpath, this);
-        if (ioe != null)
-           throw ioe;
-    }
-
-    ZipFileAttributes getFileAttributes(byte[] path)
-        throws IOException
-    {
-        Entry e;
-        beginRead();
-        try {
-            ensureOpen();
-            e = getEntry0(path);
-            if (e == null) {
-                IndexNode inode = getInode(path);
-                if (inode == null)
-                    return null;
-                e = new Entry(inode.name);       // pseudo directory
-                e.method = METHOD_STORED;        // STORED for dir
-                e.mtime = e.atime = e.ctime = -1;// -1 for all times
-            }
-        } finally {
-            endRead();
-        }
-        return new ZipFileAttributes(e);
-    }
-
-    void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
-        throws IOException
-    {
-        checkWritable();
-        beginWrite();
-        try {
-            ensureOpen();
-            Entry e = getEntry0(path);    // ensureOpen checked
-            if (e == null)
-                throw new NoSuchFileException(getString(path));
-            if (e.type == Entry.CEN)
-                e.type = Entry.COPY;      // copy e
-            if (mtime != null)
-                e.mtime = mtime.toMillis();
-            if (atime != null)
-                e.atime = atime.toMillis();
-            if (ctime != null)
-                e.ctime = ctime.toMillis();
-            update(e);
-        } finally {
-            endWrite();
-        }
-    }
-
-    boolean exists(byte[] path)
-        throws IOException
-    {
-        beginRead();
-        try {
-            ensureOpen();
-            return getInode(path) != null;
-        } finally {
-            endRead();
-        }
-    }
-
-    boolean isDirectory(byte[] path)
-        throws IOException
-    {
-        beginRead();
-        try {
-            IndexNode n = getInode(path);
-            return n != null && n.isDir();
-        } finally {
-            endRead();
-        }
-    }
-
-    private ZipPath toZipPath(byte[] path) {
-        // make it absolute
-        byte[] p = new byte[path.length + 1];
-        p[0] = '/';
-        System.arraycopy(path, 0, p, 1, path.length);
-        return new ZipPath(this, p);
-    }
-
-    // returns the list of child paths of "path"
-    Iterator<Path> iteratorOf(byte[] path,
-                              DirectoryStream.Filter<? super Path> filter)
-        throws IOException
-    {
-        beginWrite();    // iteration of inodes needs exclusive lock
-        try {
-            ensureOpen();
-            IndexNode inode = getInode(path);
-            if (inode == null)
-                throw new NotDirectoryException(getString(path));
-            List<Path> list = new ArrayList<>();
-            IndexNode child = inode.child;
-            while (child != null) {
-                ZipPath zp = toZipPath(child.name);
-                if (filter == null || filter.accept(zp))
-                    list.add(zp);
-                child = child.sibling;
-            }
-            return list.iterator();
-        } finally {
-            endWrite();
-        }
-    }
-
-    void createDirectory(byte[] dir, FileAttribute<?>... attrs)
-        throws IOException
-    {
-        checkWritable();
-        dir = toDirectoryPath(dir);
-        beginWrite();
-        try {
-            ensureOpen();
-            if (dir.length == 0 || exists(dir))  // root dir, or exiting dir
-                throw new FileAlreadyExistsException(getString(dir));
-            checkParents(dir);
-            Entry e = new Entry(dir, Entry.NEW);
-            e.method = METHOD_STORED;            // STORED for dir
-            update(e);
-        } finally {
-            endWrite();
-        }
-    }
-
-    void copyFile(boolean deletesrc, byte[]src, byte[] dst, CopyOption... options)
-        throws IOException
-    {
-        checkWritable();
-        if (Arrays.equals(src, dst))
-            return;    // do nothing, src and dst are the same
-
-        beginWrite();
-        try {
-            ensureOpen();
-            Entry eSrc = getEntry0(src);  // ensureOpen checked
-            if (eSrc == null)
-                throw new NoSuchFileException(getString(src));
-            if (eSrc.isDir()) {    // spec says to create dst dir
-                createDirectory(dst);
-                return;
-            }
-            boolean hasReplace = false;
-            boolean hasCopyAttrs = false;
-            for (CopyOption opt : options) {
-                if (opt == REPLACE_EXISTING)
-                    hasReplace = true;
-                else if (opt == COPY_ATTRIBUTES)
-                    hasCopyAttrs = true;
-            }
-            Entry eDst = getEntry0(dst);
-            if (eDst != null) {
-                if (!hasReplace)
-                    throw new FileAlreadyExistsException(getString(dst));
-            } else {
-                checkParents(dst);
-            }
-            Entry u = new Entry(eSrc, Entry.COPY);    // copy eSrc entry
-            u.name(dst);                              // change name
-            if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
-            {
-                u.type = eSrc.type;    // make it the same type
-                if (deletesrc) {       // if it's a "rename", take the data
-                    u.bytes = eSrc.bytes;
-                    u.file = eSrc.file;
-                } else {               // if it's not "rename", copy the data
-                    if (eSrc.bytes != null)
-                        u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
-                    else if (eSrc.file != null) {
-                        u.file = getTempPathForEntry(null);
-                        Files.copy(eSrc.file, u.file, REPLACE_EXISTING);
-                    }
-                }
-            }
-            if (!hasCopyAttrs)
-                u.mtime = u.atime= u.ctime = System.currentTimeMillis();
-            update(u);
-            if (deletesrc)
-                updateDelete(eSrc);
-        } finally {
-            endWrite();
-        }
-    }
-
-    // Returns an output stream for writing the contents into the specified
-    // entry.
-    OutputStream newOutputStream(byte[] path, OpenOption... options)
-        throws IOException
-    {
-        checkWritable();
-        boolean hasCreateNew = false;
-        boolean hasCreate = false;
-        boolean hasAppend = false;
-        for (OpenOption opt: options) {
-            if (opt == READ)
-                throw new IllegalArgumentException("READ not allowed");
-            if (opt == CREATE_NEW)
-                hasCreateNew = true;
-            if (opt == CREATE)
-                hasCreate = true;
-            if (opt == APPEND)
-                hasAppend = true;
-        }
-        beginRead();                 // only need a readlock, the "update()" will
-        try {                        // try to obtain a writelock when the os is
-            ensureOpen();            // being closed.
-            Entry e = getEntry0(path);
-            if (e != null) {
-                if (e.isDir() || hasCreateNew)
-                    throw new FileAlreadyExistsException(getString(path));
-                if (hasAppend) {
-                    InputStream is = getInputStream(e);
-                    OutputStream os = getOutputStream(new Entry(e, Entry.NEW));
-                    copyStream(is, os);
-                    is.close();
-                    return os;
-                }
-                return getOutputStream(new Entry(e, Entry.NEW));
-            } else {
-                if (!hasCreate && !hasCreateNew)
-                    throw new NoSuchFileException(getString(path));
-                checkParents(path);
-                return getOutputStream(new Entry(path, Entry.NEW));
-            }
-        } finally {
-            endRead();
-        }
-    }
-
-    // Returns an input stream for reading the contents of the specified
-    // file entry.
-    InputStream newInputStream(byte[] path) throws IOException {
-        beginRead();
-        try {
-            ensureOpen();
-            Entry e = getEntry0(path);
-            if (e == null)
-                throw new NoSuchFileException(getString(path));
-            if (e.isDir())
-                throw new FileSystemException(getString(path), "is a directory", null);
-            return getInputStream(e);
-        } finally {
-            endRead();
-        }
-    }
-
-    private 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();
-        }
-    }
-
-    // Returns a Writable/ReadByteChannel for now. Might consdier to use
-    // newFileChannel() instead, which dump the entry data into a regular
-    // file on the default file system and create a FileChannel on top of
-    // it.
-    SeekableByteChannel newByteChannel(byte[] path,
-                                       Set<? extends OpenOption> options,
-                                       FileAttribute<?>... attrs)
-        throws IOException
-    {
-        checkOptions(options);
-        if (options.contains(StandardOpenOption.WRITE) ||
-            options.contains(StandardOpenOption.APPEND)) {
-            checkWritable();
-            beginRead();
-            try {
-                final WritableByteChannel wbc = Channels.newChannel(
-                    newOutputStream(path, options.toArray(new OpenOption[0])));
-                long leftover = 0;
-                if (options.contains(StandardOpenOption.APPEND)) {
-                    Entry e = getEntry0(path);
-                    if (e != null && e.size >= 0)
-                        leftover = e.size;
-                }
-                final long offset = leftover;
-                return new SeekableByteChannel() {
-                    long written = offset;
-                    public boolean isOpen() {
-                        return wbc.isOpen();
-                    }
-
-                    public long position() throws IOException {
-                        return written;
-                    }
-
-                    public SeekableByteChannel position(long pos)
-                        throws IOException
-                    {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    public int read(ByteBuffer dst) throws IOException {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    public SeekableByteChannel truncate(long size)
-                        throws IOException
-                    {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    public int write(ByteBuffer src) throws IOException {
-                        int n = wbc.write(src);
-                        written += n;
-                        return n;
-                    }
-
-                    public long size() throws IOException {
-                        return written;
-                    }
-
-                    public void close() throws IOException {
-                        wbc.close();
-                    }
-                };
-            } finally {
-                endRead();
-            }
-        } else {
-            beginRead();
-            try {
-                ensureOpen();
-                Entry e = getEntry0(path);
-                if (e == null || e.isDir())
-                    throw new NoSuchFileException(getString(path));
-                final ReadableByteChannel rbc =
-                    Channels.newChannel(getInputStream(e));
-                final long size = e.size;
-                return new SeekableByteChannel() {
-                    long read = 0;
-                    public boolean isOpen() {
-                        return rbc.isOpen();
-                    }
-
-                    public long position() throws IOException {
-                        return read;
-                    }
-
-                    public SeekableByteChannel position(long pos)
-                        throws IOException
-                    {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    public int read(ByteBuffer dst) throws IOException {
-                        int n = rbc.read(dst);
-                        if (n > 0) {
-                            read += n;
-                        }
-                        return n;
-                    }
-
-                    public SeekableByteChannel truncate(long size)
-                    throws IOException
-                    {
-                        throw new NonWritableChannelException();
-                    }
-
-                    public int write (ByteBuffer src) throws IOException {
-                        throw new NonWritableChannelException();
-                    }
-
-                    public long size() throws IOException {
-                        return size;
-                    }
-
-                    public void close() throws IOException {
-                        rbc.close();
-                    }
-                };
-            } finally {
-                endRead();
-            }
-        }
-    }
-
-    // Returns a FileChannel of the specified entry.
-    //
-    // This implementation creates a temporary file on the default file system,
-    // copy the entry data into it if the entry exists, and then create a
-    // FileChannel on top of it.
-    FileChannel newFileChannel(byte[] path,
-                               Set<? extends OpenOption> options,
-                               FileAttribute<?>... attrs)
-        throws IOException
-    {
-        checkOptions(options);
-        final  boolean forWrite = (options.contains(StandardOpenOption.WRITE) ||
-                                   options.contains(StandardOpenOption.APPEND));
-        beginRead();
-        try {
-            ensureOpen();
-            Entry e = getEntry0(path);
-            if (forWrite) {
-                checkWritable();
-                if (e == null) {
-                if (!options.contains(StandardOpenOption.CREATE_NEW))
-                    throw new NoSuchFileException(getString(path));
-                } else {
-                    if (options.contains(StandardOpenOption.CREATE_NEW))
-                        throw new FileAlreadyExistsException(getString(path));
-                    if (e.isDir())
-                        throw new FileAlreadyExistsException("directory <"
-                            + getString(path) + "> exists");
-                }
-                options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile
-            } else if (e == null || e.isDir()) {
-                throw new NoSuchFileException(getString(path));
-            }
-
-            final boolean isFCH = (e != null && e.type == Entry.FILECH);
-            final Path tmpfile = isFCH ? e.file : getTempPathForEntry(path);
-            final FileChannel fch = tmpfile.getFileSystem()
-                                           .provider()
-                                           .newFileChannel(tmpfile, options, attrs);
-            final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH);
-            if (forWrite) {
-                u.flag = FLAG_DATADESCR;
-                u.method = METHOD_DEFLATED;
-            }
-            // is there a better way to hook into the FileChannel's close method?
-            return new FileChannel() {
-                public int write(ByteBuffer src) throws IOException {
-                    return fch.write(src);
-                }
-                public long write(ByteBuffer[] srcs, int offset, int length)
-                    throws IOException
-                {
-                    return fch.write(srcs, offset, length);
-                }
-                public long position() throws IOException {
-                    return fch.position();
-                }
-                public FileChannel position(long newPosition)
-                    throws IOException
-                {
-                    fch.position(newPosition);
-                    return this;
-                }
-                public long size() throws IOException {
-                    return fch.size();
-                }
-                public FileChannel truncate(long size)
-                    throws IOException
-                {
-                    fch.truncate(size);
-                    return this;
-                }
-                public void force(boolean metaData)
-                    throws IOException
-                {
-                    fch.force(metaData);
-                }
-                public long transferTo(long position, long count,
-                                       WritableByteChannel target)
-                    throws IOException
-                {
-                    return fch.transferTo(position, count, target);
-                }
-                public long transferFrom(ReadableByteChannel src,
-                                         long position, long count)
-                    throws IOException
-                {
-                    return fch.transferFrom(src, position, count);
-                }
-                public int read(ByteBuffer dst) throws IOException {
-                    return fch.read(dst);
-                }
-                public int read(ByteBuffer dst, long position)
-                    throws IOException
-                {
-                    return fch.read(dst, position);
-                }
-                public long read(ByteBuffer[] dsts, int offset, int length)
-                    throws IOException
-                {
-                    return fch.read(dsts, offset, length);
-                }
-                public int write(ByteBuffer src, long position)
-                    throws IOException
-                    {
-                   return fch.write(src, position);
-                }
-                public MappedByteBuffer map(MapMode mode,
-                                            long position, long size)
-                    throws IOException
-                {
-                    throw new UnsupportedOperationException();
-                }
-                public FileLock lock(long position, long size, boolean shared)
-                    throws IOException
-                {
-                    return fch.lock(position, size, shared);
-                }
-                public FileLock tryLock(long position, long size, boolean shared)
-                    throws IOException
-                {
-                    return fch.tryLock(position, size, shared);
-                }
-                protected void implCloseChannel() throws IOException {
-                    fch.close();
-                    if (forWrite) {
-                        u.mtime = System.currentTimeMillis();
-                        u.size = Files.size(u.file);
-
-                        update(u);
-                    } else {
-                        if (!isFCH)    // if this is a new fch for reading
-                            removeTempPathForEntry(tmpfile);
-                    }
-               }
-            };
-        } finally {
-            endRead();
-        }
-    }
-
-    // the outstanding input streams that need to be closed
-    private Set<InputStream> streams =
-        Collections.synchronizedSet(new HashSet<InputStream>());
-
-    // the ex-channel and ex-path that need to close when their outstanding
-    // input streams are all closed by the obtainers.
-    private Set<ExChannelCloser> exChClosers = new HashSet<>();
-
-    private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>());
-    private Path getTempPathForEntry(byte[] path) throws IOException {
-        Path tmpPath = createTempFileInSameDirectoryAs(zfpath);
-        if (path != null) {
-            Entry e = getEntry0(path);
-            if (e != null) {
-                try (InputStream is = newInputStream(path)) {
-                    Files.copy(is, tmpPath, REPLACE_EXISTING);
-                }
-            }
-        }
-        return tmpPath;
-    }
-
-    private void removeTempPathForEntry(Path path) throws IOException {
-        Files.delete(path);
-        tmppaths.remove(path);
-    }
-
-    // check if all parents really exit. ZIP spec does not require
-    // the existence of any "parent directory".
-    private void checkParents(byte[] path) throws IOException {
-        beginRead();
-        try {
-            while ((path = getParent(path)) != null && path.length != 0) {
-                if (!inodes.containsKey(IndexNode.keyOf(path))) {
-                    throw new NoSuchFileException(getString(path));
-                }
-            }
-        } finally {
-            endRead();
-        }
-    }
-
-    private static byte[] ROOTPATH = new byte[0];
-    private static byte[] getParent(byte[] path) {
-        int off = path.length - 1;
-        if (off > 0 && path[off] == '/')  // isDirectory
-            off--;
-        while (off > 0 && path[off] != '/') { off--; }
-        if (off <= 0)
-            return ROOTPATH;
-        return Arrays.copyOf(path, off + 1);
-    }
-
-    private final void beginWrite() {
-        rwlock.writeLock().lock();
-    }
-
-    private final void endWrite() {
-        rwlock.writeLock().unlock();
-    }
-
-    private final void beginRead() {
-        rwlock.readLock().lock();
-    }
-
-    private final void endRead() {
-        rwlock.readLock().unlock();
-    }
-
-    ///////////////////////////////////////////////////////////////////
-
-    private volatile boolean isOpen = true;
-    private final SeekableByteChannel ch; // channel to the zipfile
-    final byte[]  cen;     // CEN & ENDHDR
-    private END  end;
-    private long locpos;   // position of first LOC header (usually 0)
-
-    private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
-
-    // name -> pos (in cen), IndexNode itself can be used as a "key"
-    private LinkedHashMap<IndexNode, IndexNode> inodes;
-
-    final byte[] getBytes(String name) {
-        return zc.getBytes(name);
-    }
-
-    final String getString(byte[] name) {
-        return zc.toString(name);
-    }
-
-    protected void finalize() throws IOException {
-        close();
-    }
-
-    private long getDataPos(Entry e) throws IOException {
-        if (e.locoff == -1) {
-            Entry e2 = getEntry0(e.name);
-            if (e2 == null)
-                throw new ZipException("invalid loc for entry <" + e.name + ">");
-            e.locoff = e2.locoff;
-        }
-        byte[] buf = new byte[LOCHDR];
-        if (readFullyAt(buf, 0, buf.length, e.locoff) != buf.length)
-            throw new ZipException("invalid loc for entry <" + e.name + ">");
-        return locpos + e.locoff + LOCHDR + LOCNAM(buf) + LOCEXT(buf);
-    }
-
-    // Reads len bytes of data from the specified offset into buf.
-    // Returns the total number of bytes read.
-    // Each/every byte read from here (except the cen, which is mapped).
-    final long readFullyAt(byte[] buf, int off, long len, long pos)
-        throws IOException
-    {
-        ByteBuffer bb = ByteBuffer.wrap(buf);
-        bb.position(off);
-        bb.limit((int)(off + len));
-        return readFullyAt(bb, pos);
-    }
-
-    private final long readFullyAt(ByteBuffer bb, long pos)
-        throws IOException
-    {
-        synchronized(ch) {
-            return ch.position(pos).read(bb);
-        }
-    }
-
-    // Searches for end of central directory (END) header. The contents of
-    // the END header will be read and placed in endbuf. Returns the file
-    // position of the END header, otherwise returns -1 if the END header
-    // was not found or an error occurred.
-    private END findEND() throws IOException
-    {
-        byte[] buf = new byte[READBLOCKSZ];
-        long ziplen = ch.size();
-        long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
-        long minPos = minHDR - (buf.length - ENDHDR);
-
-        for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR))
-        {
-            int off = 0;
-            if (pos < 0) {
-                // Pretend there are some NUL bytes before start of file
-                off = (int)-pos;
-                Arrays.fill(buf, 0, off, (byte)0);
-            }
-            int len = buf.length - off;
-            if (readFullyAt(buf, off, len, pos + off) != len)
-                zerror("zip END header not found");
-
-            // Now scan the block backwards for END header signature
-            for (int i = buf.length - ENDHDR; i >= 0; i--) {
-                if (buf[i+0] == (byte)'P'    &&
-                    buf[i+1] == (byte)'K'    &&
-                    buf[i+2] == (byte)'\005' &&
-                    buf[i+3] == (byte)'\006' &&
-                    (pos + i + ENDHDR + ENDCOM(buf, i) == ziplen)) {
-                    // Found END header
-                    buf = Arrays.copyOfRange(buf, i, i + ENDHDR);
-                    END end = new END();
-                    end.endsub = ENDSUB(buf);
-                    end.centot = ENDTOT(buf);
-                    end.cenlen = ENDSIZ(buf);
-                    end.cenoff = ENDOFF(buf);
-                    end.comlen = ENDCOM(buf);
-                    end.endpos = pos + i;
-                    if (end.cenlen == ZIP64_MINVAL ||
-                        end.cenoff == ZIP64_MINVAL ||
-                        end.centot == ZIP64_MINVAL32)
-                    {
-                        // need to find the zip64 end;
-                        byte[] loc64 = new byte[ZIP64_LOCHDR];
-                        if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
-                            != loc64.length) {
-                            return end;
-                        }
-                        long end64pos = ZIP64_LOCOFF(loc64);
-                        byte[] end64buf = new byte[ZIP64_ENDHDR];
-                        if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
-                            != end64buf.length) {
-                            return end;
-                        }
-                        // end64 found, re-calcualte everything.
-                        end.cenlen = ZIP64_ENDSIZ(end64buf);
-                        end.cenoff = ZIP64_ENDOFF(end64buf);
-                        end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
-                        end.endpos = end64pos;
-                    }
-                    return end;
-                }
-            }
-        }
-        zerror("zip END header not found");
-        return null; //make compiler happy
-    }
-
-    // Reads zip file central directory. Returns the file position of first
-    // CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
-    // then the error was a zip format error and zip->msg has the error text.
-    // Always pass in -1 for knownTotal; it's used for a recursive call.
-    private byte[] initCEN() throws IOException {
-        end = findEND();
-        if (end.endpos == 0) {
-            inodes = new LinkedHashMap<>(10);
-            locpos = 0;
-            buildNodeTree();
-            return null;         // only END header present
-        }
-        if (end.cenlen > end.endpos)
-            zerror("invalid END header (bad central directory size)");
-        long cenpos = end.endpos - end.cenlen;     // position of CEN table
-
-        // Get position of first local file (LOC) header, taking into
-        // account that there may be a stub prefixed to the zip file.
-        locpos = cenpos - end.cenoff;
-        if (locpos < 0)
-            zerror("invalid END header (bad central directory offset)");
-
-        // read in the CEN and END
-        byte[] cen = new byte[(int)(end.cenlen + ENDHDR)];
-        if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
-            zerror("read CEN tables failed");
-        }
-        // Iterate through the entries in the central directory
-        inodes = new LinkedHashMap<>(end.centot + 1);
-        int pos = 0;
-        int limit = cen.length - ENDHDR;
-        while (pos < limit) {
-            if (CENSIG(cen, pos) != CENSIG)
-                zerror("invalid CEN header (bad signature)");
-            int method = CENHOW(cen, pos);
-            int nlen   = CENNAM(cen, pos);
-            int elen   = CENEXT(cen, pos);
-            int clen   = CENCOM(cen, pos);
-            if ((CENFLG(cen, pos) & 1) != 0)
-                zerror("invalid CEN header (encrypted entry)");
-            if (method != METHOD_STORED && method != METHOD_DEFLATED)
-                zerror("invalid CEN header (unsupported compression method: " + method + ")");
-            if (pos + CENHDR + nlen > limit)
-                zerror("invalid CEN header (bad header size)");
-            byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen);
-            IndexNode inode = new IndexNode(name, pos);
-            inodes.put(inode, inode);
-            // skip ext and comment
-            pos += (CENHDR + nlen + elen + clen);
-        }
-        if (pos + ENDHDR != cen.length) {
-            zerror("invalid CEN header (bad header size)");
-        }
-        buildNodeTree();
-        return cen;
-    }
-
-    private void ensureOpen() throws IOException {
-        if (!isOpen)
-            throw new ClosedFileSystemException();
-    }
-
-    // Creates a new empty temporary file in the same directory as the
-    // specified file.  A variant of Files.createTempFile.
-    private Path createTempFileInSameDirectoryAs(Path path)
-        throws IOException
-    {
-        Path parent = path.toAbsolutePath().getParent();
-        Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
-        Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
-        tmppaths.add(tmpPath);
-        return tmpPath;
-    }
-
-    ////////////////////update & sync //////////////////////////////////////
-
-    private boolean hasUpdate = false;
-
-    // shared key. consumer guarantees the "writeLock" before use it.
-    private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
-
-    private void updateDelete(IndexNode inode) {
-        beginWrite();
-        try {
-            removeFromTree(inode);
-            inodes.remove(inode);
-            hasUpdate = true;
-        } finally {
-             endWrite();
-        }
-    }
-
-    private void update(Entry e) {
-        beginWrite();
-        try {
-            IndexNode old = inodes.put(e, e);
-            if (old != null) {
-                removeFromTree(old);
-            }
-            if (e.type == Entry.NEW || e.type == Entry.FILECH || e.type == Entry.COPY) {
-                IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
-                e.sibling = parent.child;
-                parent.child = e;
-            }
-            hasUpdate = true;
-        } finally {
-            endWrite();
-        }
-    }
-
-    // copy over the whole LOC entry (header if necessary, data and ext) from
-    // old zip to the new one.
-    private long copyLOCEntry(Entry e, boolean updateHeader,
-                              OutputStream os,
-                              long written, byte[] buf)
-        throws IOException
-    {
-        long locoff = e.locoff;  // where to read
-        e.locoff = written;      // update the e.locoff with new value
-
-        // calculate the size need to write out
-        long size = 0;
-        //  if there is A ext
-        if ((e.flag & FLAG_DATADESCR) != 0) {
-            if (e.size >= ZIP64_MINVAL || e.csize >= ZIP64_MINVAL)
-                size = 24;
-            else
-                size = 16;
-        }
-        // read loc, use the original loc.elen/nlen
-        if (readFullyAt(buf, 0, LOCHDR , locoff) != LOCHDR)
-            throw new ZipException("loc: reading failed");
-        if (updateHeader) {
-            locoff += LOCHDR + LOCNAM(buf) + LOCEXT(buf);  // skip header
-            size += e.csize;
-            written = e.writeLOC(os) + size;
-        } else {
-            os.write(buf, 0, LOCHDR);    // write out the loc header
-            locoff += LOCHDR;
-            // use e.csize,  LOCSIZ(buf) is zero if FLAG_DATADESCR is on
-            // size += LOCNAM(buf) + LOCEXT(buf) + LOCSIZ(buf);
-            size += LOCNAM(buf) + LOCEXT(buf) + e.csize;
-            written = LOCHDR + size;
-        }
-        int n;
-        while (size > 0 &&
-            (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
-        {
-            if (size < n)
-                n = (int)size;
-            os.write(buf, 0, n);
-            size -= n;
-            locoff += n;
-        }
-        return written;
-    }
-
-    // sync the zip file system, if there is any udpate
-    private void sync() throws IOException {
-        //System.out.printf("->sync(%s) starting....!%n", toString());
-        // check ex-closer
-        if (!exChClosers.isEmpty()) {
-            for (ExChannelCloser ecc : exChClosers) {
-                if (ecc.streams.isEmpty()) {
-                    ecc.ch.close();
-                    Files.delete(ecc.path);
-                    exChClosers.remove(ecc);
-                }
-            }
-        }
-        if (!hasUpdate)
-            return;
-        Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
-        try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(tmpFile, WRITE)))
-        {
-            ArrayList<Entry> elist = new ArrayList<>(inodes.size());
-            long written = 0;
-            byte[] buf = new byte[8192];
-            Entry e = null;
-
-            // write loc
-            for (IndexNode inode : inodes.values()) {
-                if (inode instanceof Entry) {    // an updated inode
-                    e = (Entry)inode;
-                    try {
-                        if (e.type == Entry.COPY) {
-                            // entry copy: the only thing changed is the "name"
-                            // and "nlen" in LOC header, so we udpate/rewrite the
-                            // LOC in new file and simply copy the rest (data and
-                            // ext) without enflating/deflating from the old zip
-                            // file LOC entry.
-                            written += copyLOCEntry(e, true, os, written, buf);
-                        } else {                          // NEW, FILECH or CEN
-                            e.locoff = written;
-                            written += e.writeLOC(os);    // write loc header
-                            if (e.bytes != null) {        // in-memory, deflated
-                                os.write(e.bytes);        // already
-                                written += e.bytes.length;
-                            } else if (e.file != null) {  // tmp file
-                                try (InputStream is = Files.newInputStream(e.file)) {
-                                    int n;
-                                    if (e.type == Entry.NEW) {  // deflated already
-                                        while ((n = is.read(buf)) != -1) {
-                                            os.write(buf, 0, n);
-                                            written += n;
-                                        }
-                                    } else if (e.type == Entry.FILECH) {
-                                        // the data are not deflated, use ZEOS
-                                        try (OutputStream os2 = new EntryOutputStream(e, os)) {
-                                            while ((n = is.read(buf)) != -1) {
-                                                os2.write(buf, 0, n);
-                                            }
-                                        }
-                                        written += e.csize;
-                                        if ((e.flag & FLAG_DATADESCR) != 0)
-                                            written += e.writeEXT(os);
-                                    }
-                                }
-                                Files.delete(e.file);
-                                tmppaths.remove(e.file);
-                            } else {
-                                // dir, 0-length data
-                            }
-                        }
-                        elist.add(e);
-                    } catch (IOException x) {
-                        x.printStackTrace();    // skip any in-accurate entry
-                    }
-                } else {                        // unchanged inode
-                    if (inode.pos == -1) {
-                        continue;               // pseudo directory node
-                    }
-                    e = Entry.readCEN(this, inode.pos);
-                    try {
-                        written += copyLOCEntry(e, false, os, written, buf);
-                        elist.add(e);
-                    } catch (IOException x) {
-                        x.printStackTrace();    // skip any wrong entry
-                    }
-                }
-            }
-
-            // now write back the cen and end table
-            end.cenoff = written;
-            for (Entry entry : elist) {
-                written += entry.writeCEN(os);
-            }
-            end.centot = elist.size();
-            end.cenlen = written - end.cenoff;
-            end.write(os, written);
-        }
-        if (!streams.isEmpty()) {
-            //
-            // TBD: ExChannelCloser should not be necessary if we only
-            // sync when being closed, all streams should have been
-            // closed already. Keep the logic here for now.
-            //
-            // There are outstanding input streams open on existing "ch",
-            // so, don't close the "cha" and delete the "file for now, let
-            // the "ex-channel-closer" to handle them
-            ExChannelCloser ecc = new ExChannelCloser(
-                                      createTempFileInSameDirectoryAs(zfpath),
-                                      ch,
-                                      streams);
-            Files.move(zfpath, ecc.path, REPLACE_EXISTING);
-            exChClosers.add(ecc);
-            streams = Collections.synchronizedSet(new HashSet<InputStream>());
-        } else {
-            ch.close();
-            Files.delete(zfpath);
-        }
-
-        Files.move(tmpFile, zfpath, REPLACE_EXISTING);
-        hasUpdate = false;    // clear
-        /*
-        if (isOpen) {
-            ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen"
-            cen = initCEN();
-        }
-         */
-        //System.out.printf("->sync(%s) done!%n", toString());
-    }
-
-    private IndexNode getInode(byte[] path) {
-        if (path == null)
-            throw new NullPointerException("path");
-        IndexNode key = IndexNode.keyOf(path);
-        IndexNode inode = inodes.get(key);
-        if (inode == null &&
-            (path.length == 0 || path[path.length -1] != '/')) {
-            // if does not ends with a slash
-            path = Arrays.copyOf(path, path.length + 1);
-            path[path.length - 1] = '/';
-            inode = inodes.get(key.as(path));
-        }
-        return inode;
-    }
-
-    private Entry getEntry0(byte[] path) throws IOException {
-        IndexNode inode = getInode(path);
-        if (inode instanceof Entry)
-            return (Entry)inode;
-        if (inode == null || inode.pos == -1)
-            return null;
-        return Entry.readCEN(this, inode.pos);
-    }
-
-    public void deleteFile(byte[] path, boolean failIfNotExists)
-        throws IOException
-    {
-        checkWritable();
-
-        IndexNode inode = getInode(path);
-        if (inode == null) {
-            if (path != null && path.length == 0)
-                throw new ZipException("root directory </> can't not be delete");
-            if (failIfNotExists)
-                throw new NoSuchFileException(getString(path));
-        } else {
-            if (inode.isDir() && inode.child != null)
-                throw new DirectoryNotEmptyException(getString(path));
-            updateDelete(inode);
-        }
-    }
-
-    private static void copyStream(InputStream is, OutputStream os)
-        throws IOException
-    {
-        byte[] copyBuf = new byte[8192];
-        int n;
-        while ((n = is.read(copyBuf)) != -1) {
-            os.write(copyBuf, 0, n);
-        }
-    }
-
-    // Returns an out stream for either
-    // (1) writing the contents of a new entry, if the entry exits, or
-    // (2) updating/replacing the contents of the specified existing entry.
-    private OutputStream getOutputStream(Entry e) throws IOException {
-
-        if (e.mtime == -1)
-            e.mtime = System.currentTimeMillis();
-        if (e.method == -1)
-            e.method = METHOD_DEFLATED;  // TBD:  use default method
-        // store size, compressed size, and crc-32 in LOC header
-        e.flag = 0;
-        if (zc.isUTF8())
-            e.flag |= FLAG_EFS;
-        OutputStream os;
-        if (useTempFile) {
-            e.file = getTempPathForEntry(null);
-            os = Files.newOutputStream(e.file, WRITE);
-        } else {
-            os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
-        }
-        return new EntryOutputStream(e, os);
-    }
-
-    private InputStream getInputStream(Entry e)
-        throws IOException
-    {
-        InputStream eis = null;
-
-        if (e.type == Entry.NEW) {
-            if (e.bytes != null)
-                eis = new ByteArrayInputStream(e.bytes);
-            else if (e.file != null)
-                eis = Files.newInputStream(e.file);
-            else
-                throw new ZipException("update entry data is missing");
-        } else if (e.type == Entry.FILECH) {
-            // FILECH result is un-compressed.
-            eis = Files.newInputStream(e.file);
-            // TBD: wrap to hook close()
-            // streams.add(eis);
-            return eis;
-        } else {  // untouced  CEN or COPY
-            eis = new EntryInputStream(e, ch);
-        }
-        if (e.method == METHOD_DEFLATED) {
-            // MORE: Compute good size for inflater stream:
-            long bufSize = e.size + 2; // Inflater likes a bit of slack
-            if (bufSize > 65536)
-                bufSize = 8192;
-            final long size = e.size;
-            eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) {
-
-                private boolean isClosed = false;
-                public void close() throws IOException {
-                    if (!isClosed) {
-                        releaseInflater(inf);
-                        this.in.close();
-                        isClosed = true;
-                        streams.remove(this);
-                    }
-                }
-                // Override fill() method to provide an extra "dummy" byte
-                // at the end of the input stream. This is required when
-                // using the "nowrap" Inflater option. (it appears the new
-                // zlib in 7 does not need it, but keep it for now)
-                protected void fill() throws IOException {
-                    if (eof) {
-                        throw new EOFException(
-                            "Unexpected end of ZLIB input stream");
-                    }
-                    len = this.in.read(buf, 0, buf.length);
-                    if (len == -1) {
-                        buf[0] = 0;
-                        len = 1;
-                        eof = true;
-                    }
-                    inf.setInput(buf, 0, len);
-                }
-                private boolean eof;
-
-                public int available() throws IOException {
-                    if (isClosed)
-                        return 0;
-                    long avail = size - inf.getBytesWritten();
-                    return avail > (long) Integer.MAX_VALUE ?
-                        Integer.MAX_VALUE : (int) avail;
-                }
-            };
-        } else if (e.method == METHOD_STORED) {
-            // TBD: wrap/ it does not seem necessary
-        } else {
-            throw new ZipException("invalid compression method");
-        }
-        streams.add(eis);
-        return eis;
-    }
-
-    // Inner class implementing the input stream used to read
-    // a (possibly compressed) zip file entry.
-    private class EntryInputStream extends InputStream {
-        private final SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might
-                                          // point to a new channel after sync()
-        private   long pos;               // current position within entry data
-        protected long rem;               // number of remaining bytes within entry
-        protected final long size;        // uncompressed size of this entry
-
-        EntryInputStream(Entry e, SeekableByteChannel zfch)
-            throws IOException
-        {
-            this.zfch = zfch;
-            rem = e.csize;
-            size = e.size;
-            pos = getDataPos(e);
-        }
-        public int read(byte b[], int off, int len) throws IOException {
-            ensureOpen();
-            if (rem == 0) {
-                return -1;
-            }
-            if (len <= 0) {
-                return 0;
-            }
-            if (len > rem) {
-                len = (int) rem;
-            }
-            // readFullyAt()
-            long n = 0;
-            ByteBuffer bb = ByteBuffer.wrap(b);
-            bb.position(off);
-            bb.limit(off + len);
-            synchronized(zfch) {
-                n = zfch.position(pos).read(bb);
-            }
-            if (n > 0) {
-                pos += n;
-                rem -= n;
-            }
-            if (rem == 0) {
-                close();
-            }
-            return (int)n;
-        }
-        public int read() throws IOException {
-            byte[] b = new byte[1];
-            if (read(b, 0, 1) == 1) {
-                return b[0] & 0xff;
-            } else {
-                return -1;
-            }
-        }
-        public long skip(long n) throws IOException {
-            ensureOpen();
-            if (n > rem)
-                n = rem;
-            pos += n;
-            rem -= n;
-            if (rem == 0) {
-                close();
-            }
-            return n;
-        }
-        public int available() {
-            return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem;
-        }
-        public long size() {
-            return size;
-        }
-        public void close() {
-            rem = 0;
-            streams.remove(this);
-        }
-    }
-
-    class EntryOutputStream extends DeflaterOutputStream
-    {
-        private CRC32 crc;
-        private Entry e;
-        private long written;
-
-        EntryOutputStream(Entry e, OutputStream os)
-            throws IOException
-        {
-            super(os, getDeflater());
-            if (e == null)
-                throw new NullPointerException("Zip entry is null");
-            this.e = e;
-            crc = new CRC32();
-        }
-
-        @Override
-        public void write(byte b[], int off, int len) throws IOException {
-            if (e.type != Entry.FILECH)    // only from sync
-                ensureOpen();
-            if (off < 0 || len < 0 || off > b.length - len) {
-                throw new IndexOutOfBoundsException();
-            } else if (len == 0) {
-                return;
-            }
-            switch (e.method) {
-            case METHOD_DEFLATED:
-                super.write(b, off, len);
-                break;
-            case METHOD_STORED:
-                written += len;
-                out.write(b, off, len);
-                break;
-            default:
-                throw new ZipException("invalid compression method");
-            }
-            crc.update(b, off, len);
-        }
-
-        @Override
-        public void close() throws IOException {
-            // TBD ensureOpen();
-            switch (e.method) {
-            case METHOD_DEFLATED:
-                finish();
-                e.size  = def.getBytesRead();
-                e.csize = def.getBytesWritten();
-                e.crc = crc.getValue();
-                break;
-            case METHOD_STORED:
-                // we already know that both e.size and e.csize are the same
-                e.size = e.csize = written;
-                e.crc = crc.getValue();
-                break;
-            default:
-                throw new ZipException("invalid compression method");
-            }
-            //crc.reset();
-            if (out instanceof ByteArrayOutputStream)
-                e.bytes = ((ByteArrayOutputStream)out).toByteArray();
-
-            if (e.type == Entry.FILECH) {
-                releaseDeflater(def);
-                return;
-            }
-            super.close();
-            releaseDeflater(def);
-            update(e);
-        }
-    }
-
-    static void zerror(String msg) {
-        throw new ZipError(msg);
-    }
-
-    // Maxmum number of de/inflater we cache
-    private final int MAX_FLATER = 20;
-    // List of available Inflater objects for decompression
-    private final List<Inflater> inflaters = new ArrayList<>();
-
-    // Gets an inflater from the list of available inflaters or allocates
-    // a new one.
-    private Inflater getInflater() {
-        synchronized (inflaters) {
-            int size = inflaters.size();
-            if (size > 0) {
-                Inflater inf = inflaters.remove(size - 1);
-                return inf;
-            } else {
-                return new Inflater(true);
-            }
-        }
-    }
-
-    // Releases the specified inflater to the list of available inflaters.
-    private void releaseInflater(Inflater inf) {
-        synchronized (inflaters) {
-            if (inflaters.size() < MAX_FLATER) {
-                inf.reset();
-                inflaters.add(inf);
-            } else {
-                inf.end();
-            }
-        }
-    }
-
-    // List of available Deflater objects for compression
-    private final List<Deflater> deflaters = new ArrayList<>();
-
-    // Gets an deflater from the list of available deflaters or allocates
-    // a new one.
-    private Deflater getDeflater() {
-        synchronized (deflaters) {
-            int size = deflaters.size();
-            if (size > 0) {
-                Deflater def = deflaters.remove(size - 1);
-                return def;
-            } else {
-                return new Deflater(Deflater.DEFAULT_COMPRESSION, true);
-            }
-        }
-    }
-
-    // Releases the specified inflater to the list of available inflaters.
-    private void releaseDeflater(Deflater def) {
-        synchronized (deflaters) {
-            if (inflaters.size() < MAX_FLATER) {
-               def.reset();
-               deflaters.add(def);
-            } else {
-               def.end();
-            }
-        }
-    }
-
-    // End of central directory record
-    static class END {
-        int  disknum;
-        int  sdisknum;
-        int  endsub;     // endsub
-        int  centot;     // 4 bytes
-        long cenlen;     // 4 bytes
-        long cenoff;     // 4 bytes
-        int  comlen;     // comment length
-        byte[] comment;
-
-        /* members of Zip64 end of central directory locator */
-        int diskNum;
-        long endpos;
-        int disktot;
-
-        void write(OutputStream os, long offset) throws IOException {
-            boolean hasZip64 = false;
-            long xlen = cenlen;
-            long xoff = cenoff;
-            if (xlen >= ZIP64_MINVAL) {
-                xlen = ZIP64_MINVAL;
-                hasZip64 = true;
-            }
-            if (xoff >= ZIP64_MINVAL) {
-                xoff = ZIP64_MINVAL;
-                hasZip64 = true;
-            }
-            int count = centot;
-            if (count >= ZIP64_MINVAL32) {
-                count = ZIP64_MINVAL32;
-                hasZip64 = true;
-            }
-            if (hasZip64) {
-                long off64 = offset;
-                //zip64 end of central directory record
-                writeInt(os, ZIP64_ENDSIG);       // zip64 END record signature
-                writeLong(os, ZIP64_ENDHDR - 12); // size of zip64 end
-                writeShort(os, 45);               // version made by
-                writeShort(os, 45);               // version needed to extract
-                writeInt(os, 0);                  // number of this disk
-                writeInt(os, 0);                  // central directory start disk
-                writeLong(os, centot);            // number of directory entires on disk
-                writeLong(os, centot);            // number of directory entires
-                writeLong(os, cenlen);            // length of central directory
-                writeLong(os, cenoff);            // offset of central directory
-
-                //zip64 end of central directory locator
-                writeInt(os, ZIP64_LOCSIG);       // zip64 END locator signature
-                writeInt(os, 0);                  // zip64 END start disk
-                writeLong(os, off64);             // offset of zip64 END
-                writeInt(os, 1);                  // total number of disks (?)
-            }
-            writeInt(os, ENDSIG);                 // END record signature
-            writeShort(os, 0);                    // number of this disk
-            writeShort(os, 0);                    // central directory start disk
-            writeShort(os, count);                // number of directory entries on disk
-            writeShort(os, count);                // total number of directory entries
-            writeInt(os, xlen);                   // length of central directory
-            writeInt(os, xoff);                   // offset of central directory
-            if (comment != null) {            // zip file comment
-                writeShort(os, comment.length);
-                writeBytes(os, comment);
-            } else {
-                writeShort(os, 0);
-            }
-        }
-    }
-
-    // Internal node that links a "name" to its pos in cen table.
-    // The node itself can be used as a "key" to lookup itself in
-    // the HashMap inodes.
-    static class IndexNode {
-        byte[] name;
-        int    hashcode;  // node is hashable/hashed by its name
-        int    pos = -1;  // position in cen table, -1 menas the
-                          // entry does not exists in zip file
-        IndexNode(byte[] name, int pos) {
-            name(name);
-            this.pos = pos;
-        }
-
-        final static IndexNode keyOf(byte[] name) { // get a lookup key;
-            return new IndexNode(name, -1);
-        }
-
-        final void name(byte[] name) {
-            this.name = name;
-            this.hashcode = Arrays.hashCode(name);
-        }
-
-        final IndexNode as(byte[] name) {           // reuse the node, mostly
-            name(name);                             // as a lookup "key"
-            return this;
-        }
-
-        boolean isDir() {
-            return name != null &&
-                   (name.length == 0 || name[name.length - 1] == '/');
-        }
-
-        public boolean equals(Object other) {
-            if (!(other instanceof IndexNode)) {
-                return false;
-            }
-            return Arrays.equals(name, ((IndexNode)other).name);
-        }
-
-        public int hashCode() {
-            return hashcode;
-        }
-
-        IndexNode() {}
-        IndexNode sibling;
-        IndexNode child;  // 1st child
-    }
-
-    static class Entry extends IndexNode {
-
-        static final int CEN    = 1;    // entry read from cen
-        static final int NEW    = 2;    // updated contents in bytes or file
-        static final int FILECH = 3;    // fch update in "file"
-        static final int COPY   = 4;    // copy of a CEN entry
-
-
-        byte[] bytes;      // updated content bytes
-        Path   file;       // use tmp file to store bytes;
-        int    type = CEN; // default is the entry read from cen
-
-        // entry attributes
-        int    version;
-        int    flag;
-        int    method = -1;    // compression method
-        long   mtime  = -1;    // last modification time (in DOS time)
-        long   atime  = -1;    // last access time
-        long   ctime  = -1;    // create time
-        long   crc    = -1;    // crc-32 of entry data
-        long   csize  = -1;    // compressed size of entry data
-        long   size   = -1;    // uncompressed size of entry data
-        byte[] extra;
-
-        // cen
-        int    versionMade;
-        int    disk;
-        int    attrs;
-        long   attrsEx;
-        long   locoff;
-        byte[] comment;
-
-        Entry() {}
-
-        Entry(byte[] name) {
-            name(name);
-            this.mtime  = this.ctime = this.atime = System.currentTimeMillis();
-            this.crc    = 0;
-            this.size   = 0;
-            this.csize  = 0;
-            this.method = METHOD_DEFLATED;
-        }
-
-        Entry(byte[] name, int type) {
-            this(name);
-            this.type = type;
-        }
-
-        Entry (Entry e, int type) {
-            name(e.name);
-            this.version   = e.version;
-            this.ctime     = e.ctime;
-            this.atime     = e.atime;
-            this.mtime     = e.mtime;
-            this.crc       = e.crc;
-            this.size      = e.size;
-            this.csize     = e.csize;
-            this.method    = e.method;
-            this.extra     = e.extra;
-            this.versionMade = e.versionMade;
-            this.disk      = e.disk;
-            this.attrs     = e.attrs;
-            this.attrsEx   = e.attrsEx;
-            this.locoff    = e.locoff;
-            this.comment   = e.comment;
-            this.type      = type;
-        }
-
-        Entry (byte[] name, Path file, int type) {
-            this(name, type);
-            this.file = file;
-            this.method = METHOD_STORED;
-        }
-
-        int version() throws ZipException {
-            if (method == METHOD_DEFLATED)
-                return 20;
-            else if (method == METHOD_STORED)
-                return 10;
-            throw new ZipException("unsupported compression method");
-        }
-
-        ///////////////////// CEN //////////////////////
-        static Entry readCEN(ZipFileSystem zipfs, int pos)
-            throws IOException
-        {
-            return new Entry().cen(zipfs, pos);
-        }
-
-        private Entry cen(ZipFileSystem zipfs, int pos)
-            throws IOException
-        {
-            byte[] cen = zipfs.cen;
-            if (CENSIG(cen, pos) != CENSIG)
-                zerror("invalid CEN header (bad signature)");
-            versionMade = CENVEM(cen, pos);
-            version     = CENVER(cen, pos);
-            flag        = CENFLG(cen, pos);
-            method      = CENHOW(cen, pos);
-            mtime       = dosToJavaTime(CENTIM(cen, pos));
-            crc         = CENCRC(cen, pos);
-            csize       = CENSIZ(cen, pos);
-            size        = CENLEN(cen, pos);
-            int nlen    = CENNAM(cen, pos);
-            int elen    = CENEXT(cen, pos);
-            int clen    = CENCOM(cen, pos);
-            disk        = CENDSK(cen, pos);
-            attrs       = CENATT(cen, pos);
-            attrsEx     = CENATX(cen, pos);
-            locoff      = CENOFF(cen, pos);
-
-            pos += CENHDR;
-            name(Arrays.copyOfRange(cen, pos, pos + nlen));
-
-            pos += nlen;
-            if (elen > 0) {
-                extra = Arrays.copyOfRange(cen, pos, pos + elen);
-                pos += elen;
-                readExtra(zipfs);
-            }
-            if (clen > 0) {
-                comment = Arrays.copyOfRange(cen, pos, pos + clen);
-            }
-            return this;
-        }
-
-        int writeCEN(OutputStream os) throws IOException
-        {
-            int written  = CENHDR;
-            int version0 = version();
-            long csize0  = csize;
-            long size0   = size;
-            long locoff0 = locoff;
-            int elen64   = 0;                // extra for ZIP64
-            int elenNTFS = 0;                // extra for NTFS (a/c/mtime)
-            int elenEXTT = 0;                // extra for Extended Timestamp
-            boolean foundExtraTime = false;  // if time stamp NTFS, EXTT present
-
-            // confirm size/length
-            int nlen = (name != null) ? name.length : 0;
-            int elen = (extra != null) ? extra.length : 0;
-            int eoff = 0;
-            int clen = (comment != null) ? comment.length : 0;
-            if (csize >= ZIP64_MINVAL) {
-                csize0 = ZIP64_MINVAL;
-                elen64 += 8;                 // csize(8)
-            }
-            if (size >= ZIP64_MINVAL) {
-                size0 = ZIP64_MINVAL;        // size(8)
-                elen64 += 8;
-            }
-            if (locoff >= ZIP64_MINVAL) {
-                locoff0 = ZIP64_MINVAL;
-                elen64 += 8;                 // offset(8)
-            }
-            if (elen64 != 0) {
-                elen64 += 4;                 // header and data sz 4 bytes
-            }
-            while (eoff + 4 < elen) {
-                int tag = SH(extra, eoff);
-                int sz = SH(extra, eoff + 2);
-                if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
-                    foundExtraTime = true;
-                }
-                eoff += (4 + sz);
-            }
-            if (!foundExtraTime) {
-                if (isWindows) {             // use NTFS
-                    elenNTFS = 36;           // total 36 bytes
-                } else {                     // Extended Timestamp otherwise
-                    elenEXTT = 9;            // only mtime in cen
-                }
-            }
-            writeInt(os, CENSIG);            // CEN header signature
-            if (elen64 != 0) {
-                writeShort(os, 45);          // ver 4.5 for zip64
-                writeShort(os, 45);
-            } else {
-                writeShort(os, version0);    // version made by
-                writeShort(os, version0);    // version needed to extract
-            }
-            writeShort(os, flag);            // general purpose bit flag
-            writeShort(os, method);          // compression method
-                                             // last modification time
-            writeInt(os, (int)javaToDosTime(mtime));
-            writeInt(os, crc);               // crc-32
-            writeInt(os, csize0);            // compressed size
-            writeInt(os, size0);             // uncompressed size
-            writeShort(os, name.length);
-            writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
-
-            if (comment != null) {
-                writeShort(os, Math.min(clen, 0xffff));
-            } else {
-                writeShort(os, 0);
-            }
-            writeShort(os, 0);              // starting disk number
-            writeShort(os, 0);              // internal file attributes (unused)
-            writeInt(os, 0);                // external file attributes (unused)
-            writeInt(os, locoff0);          // relative offset of local header
-            writeBytes(os, name);
-            if (elen64 != 0) {
-                writeShort(os, EXTID_ZIP64);// Zip64 extra
-                writeShort(os, elen64 - 4); // size of "this" extra block
-                if (size0 == ZIP64_MINVAL)
-                    writeLong(os, size);
-                if (csize0 == ZIP64_MINVAL)
-                    writeLong(os, csize);
-                if (locoff0 == ZIP64_MINVAL)
-                    writeLong(os, locoff);
-            }
-            if (elenNTFS != 0) {
-                writeShort(os, EXTID_NTFS);
-                writeShort(os, elenNTFS - 4);
-                writeInt(os, 0);            // reserved
-                writeShort(os, 0x0001);     // NTFS attr tag
-                writeShort(os, 24);
-                writeLong(os, javaToWinTime(mtime));
-                writeLong(os, javaToWinTime(atime));
-                writeLong(os, javaToWinTime(ctime));
-            }
-            if (elenEXTT != 0) {
-                writeShort(os, EXTID_EXTT);
-                writeShort(os, elenEXTT - 4);
-                if (ctime == -1)
-                    os.write(0x3);          // mtime and atime
-                else
-                    os.write(0x7);          // mtime, atime and ctime
-                writeInt(os, javaToUnixTime(mtime));
-            }
-            if (extra != null)              // whatever not recognized
-                writeBytes(os, extra);
-            if (comment != null)            //TBD: 0, Math.min(commentBytes.length, 0xffff));
-                writeBytes(os, comment);
-            return CENHDR + nlen + elen + clen + elen64 + elenNTFS + elenEXTT;
-        }
-
-        ///////////////////// LOC //////////////////////
-        static Entry readLOC(ZipFileSystem zipfs, long pos)
-            throws IOException
-        {
-            return readLOC(zipfs, pos, new byte[1024]);
-        }
-
-        static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf)
-            throws IOException
-        {
-            return new Entry().loc(zipfs, pos, buf);
-        }
-
-        Entry loc(ZipFileSystem zipfs, long pos, byte[] buf)
-            throws IOException
-        {
-            assert (buf.length >= LOCHDR);
-            if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR)
-                throw new ZipException("loc: reading failed");
-            if (LOCSIG(buf) != LOCSIG)
-                throw new ZipException("loc: wrong sig ->"
-                                       + Long.toString(LOCSIG(buf), 16));
-            //startPos = pos;
-            version  = LOCVER(buf);
-            flag     = LOCFLG(buf);
-            method   = LOCHOW(buf);
-            mtime    = dosToJavaTime(LOCTIM(buf));
-            crc      = LOCCRC(buf);
-            csize    = LOCSIZ(buf);
-            size     = LOCLEN(buf);
-            int nlen = LOCNAM(buf);
-            int elen = LOCEXT(buf);
-
-            name = new byte[nlen];
-            if (zipfs.readFullyAt(name, 0, nlen, pos + LOCHDR) != nlen) {
-                throw new ZipException("loc: name reading failed");
-            }
-            if (elen > 0) {
-                extra = new byte[elen];
-                if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
-                    != elen) {
-                    throw new ZipException("loc: ext reading failed");
-                }
-            }
-            pos += (LOCHDR + nlen + elen);
-            if ((flag & FLAG_DATADESCR) != 0) {
-                // Data Descriptor
-                Entry e = zipfs.getEntry0(name);  // get the size/csize from cen
-                if (e == null)
-                    throw new ZipException("loc: name not found in cen");
-                size = e.size;
-                csize = e.csize;
-                pos += (method == METHOD_STORED ? size : csize);
-                if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
-                    pos += 24;
-                else
-                    pos += 16;
-            } else {
-                if (extra != null &&
-                    (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
-                    // zip64 ext: must include both size and csize
-                    int off = 0;
-                    while (off + 20 < elen) {    // HeaderID+DataSize+Data
-                        int sz = SH(extra, off + 2);
-                        if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
-                            size = LL(extra, off + 4);
-                            csize = LL(extra, off + 12);
-                            break;
-                        }
-                        off += (sz + 4);
-                    }
-                }
-                pos += (method == METHOD_STORED ? size : csize);
-            }
-            return this;
-        }
-
-        int writeLOC(OutputStream os)
-            throws IOException
-        {
-            writeInt(os, LOCSIG);               // LOC header signature
-            int version = version();
-            int nlen = (name != null) ? name.length : 0;
-            int elen = (extra != null) ? extra.length : 0;
-            boolean foundExtraTime = false;     // if extra timestamp present
-            int eoff = 0;
-            int elen64 = 0;
-            int elenEXTT = 0;
-            int elenNTFS = 0;
-            if ((flag & FLAG_DATADESCR) != 0) {
-                writeShort(os, version());      // version needed to extract
-                writeShort(os, flag);           // general purpose bit flag
-                writeShort(os, method);         // compression method
-                // last modification time
-                writeInt(os, (int)javaToDosTime(mtime));
-                // store size, uncompressed size, and crc-32 in data descriptor
-                // immediately following compressed entry data
-                writeInt(os, 0);
-                writeInt(os, 0);
-                writeInt(os, 0);
-            } else {
-                if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
-                    elen64 = 20;    //headid(2) + size(2) + size(8) + csize(8)
-                    writeShort(os, 45);         // ver 4.5 for zip64
-                } else {
-                    writeShort(os, version());  // version needed to extract
-                }
-                writeShort(os, flag);           // general purpose bit flag
-                writeShort(os, method);         // compression method
-                                                // last modification time
-                writeInt(os, (int)javaToDosTime(mtime));
-                writeInt(os, crc);              // crc-32
-                if (elen64 != 0) {
-                    writeInt(os, ZIP64_MINVAL);
-                    writeInt(os, ZIP64_MINVAL);
-                } else {
-                    writeInt(os, csize);        // compressed size
-                    writeInt(os, size);         // uncompressed size
-                }
-            }
-            while (eoff + 4 < elen) {
-                int tag = SH(extra, eoff);
-                int sz = SH(extra, eoff + 2);
-                if (tag == EXTID_EXTT || tag == EXTID_NTFS) {
-                    foundExtraTime = true;
-                }
-                eoff += (4 + sz);
-            }
-            if (!foundExtraTime) {
-                if (isWindows) {
-                    elenNTFS = 36;              // NTFS, total 36 bytes
-                } else {                        // on unix use "ext time"
-                    elenEXTT = 9;
-                    if (atime != -1)
-                        elenEXTT += 4;
-                    if (ctime != -1)
-                        elenEXTT += 4;
-                }
-            }
-            writeShort(os, name.length);
-            writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
-            writeBytes(os, name);
-            if (elen64 != 0) {
-                writeShort(os, EXTID_ZIP64);
-                writeShort(os, 16);
-                writeLong(os, size);
-                writeLong(os, csize);
-            }
-            if (elenNTFS != 0) {
-                writeShort(os, EXTID_NTFS);
-                writeShort(os, elenNTFS - 4);
-                writeInt(os, 0);            // reserved
-                writeShort(os, 0x0001);     // NTFS attr tag
-                writeShort(os, 24);
-                writeLong(os, javaToWinTime(mtime));
-                writeLong(os, javaToWinTime(atime));
-                writeLong(os, javaToWinTime(ctime));
-            }
-            if (elenEXTT != 0) {
-                writeShort(os, EXTID_EXTT);
-                writeShort(os, elenEXTT - 4);// size for the folowing data block
-                int fbyte = 0x1;
-                if (atime != -1)           // mtime and atime
-                    fbyte |= 0x2;
-                if (ctime != -1)           // mtime, atime and ctime
-                    fbyte |= 0x4;
-                os.write(fbyte);           // flags byte
-                writeInt(os, javaToUnixTime(mtime));
-                if (atime != -1)
-                    writeInt(os, javaToUnixTime(atime));
-                if (ctime != -1)
-                    writeInt(os, javaToUnixTime(ctime));
-            }
-            if (extra != null) {
-                writeBytes(os, extra);
-            }
-            return LOCHDR + name.length + elen + elen64 + elenNTFS + elenEXTT;
-        }
-
-        // Data Descriptior
-        int writeEXT(OutputStream os)
-            throws IOException
-        {
-            writeInt(os, EXTSIG);           // EXT header signature
-            writeInt(os, crc);              // crc-32
-            if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
-                writeLong(os, csize);
-                writeLong(os, size);
-                return 24;
-            } else {
-                writeInt(os, csize);        // compressed size
-                writeInt(os, size);         // uncompressed size
-                return 16;
-            }
-        }
-
-        // read NTFS, UNIX and ZIP64 data from cen.extra
-        void readExtra(ZipFileSystem zipfs) throws IOException {
-            if (extra == null)
-                return;
-            int elen = extra.length;
-            int off = 0;
-            int newOff = 0;
-            while (off + 4 < elen) {
-                // extra spec: HeaderID+DataSize+Data
-                int pos = off;
-                int tag = SH(extra, pos);
-                int sz = SH(extra, pos + 2);
-                pos += 4;
-                if (pos + sz > elen)         // invalid data
-                    break;
-                switch (tag) {
-                case EXTID_ZIP64 :
-                    if (size == ZIP64_MINVAL) {
-                        if (pos + 8 > elen)  // invalid zip64 extra
-                            break;           // fields, just skip
-                        size = LL(extra, pos);
-                        pos += 8;
-                    }
-                    if (csize == ZIP64_MINVAL) {
-                        if (pos + 8 > elen)
-                            break;
-                        csize = LL(extra, pos);
-                        pos += 8;
-                    }
-                    if (locoff == ZIP64_MINVAL) {
-                        if (pos + 8 > elen)
-                            break;
-                        locoff = LL(extra, pos);
-                        pos += 8;
-                    }
-                    break;
-                case EXTID_NTFS:
-                    pos += 4;    // reserved 4 bytes
-                    if (SH(extra, pos) !=  0x0001)
-                        break;
-                    if (SH(extra, pos + 2) != 24)
-                        break;
-                    // override the loc field, datatime here is
-                    // more "accurate"
-                    mtime  = winToJavaTime(LL(extra, pos + 4));
-                    atime  = winToJavaTime(LL(extra, pos + 12));
-                    ctime  = winToJavaTime(LL(extra, pos + 20));
-                    break;
-                case EXTID_EXTT:
-                    // spec says the Extened timestamp in cen only has mtime
-                    // need to read the loc to get the extra a/ctime
-                    byte[] buf = new byte[LOCHDR];
-                    if (zipfs.readFullyAt(buf, 0, buf.length , locoff)
-                        != buf.length)
-                        throw new ZipException("loc: reading failed");
-                    if (LOCSIG(buf) != LOCSIG)
-                        throw new ZipException("loc: wrong sig ->"
-                                           + Long.toString(LOCSIG(buf), 16));
-
-                    int locElen = LOCEXT(buf);
-                    if (locElen < 9)    // EXTT is at lease 9 bytes
-                        break;
-                    int locNlen = LOCNAM(buf);
-                    buf = new byte[locElen];
-                    if (zipfs.readFullyAt(buf, 0, buf.length , locoff + LOCHDR + locNlen)
-                        != buf.length)
-                        throw new ZipException("loc extra: reading failed");
-                    int locPos = 0;
-                    while (locPos + 4 < buf.length) {
-                        int locTag = SH(buf, locPos);
-                        int locSZ  = SH(buf, locPos + 2);
-                        locPos += 4;
-                        if (locTag  != EXTID_EXTT) {
-                            locPos += locSZ;
-                             continue;
-                        }
-                        int flag = CH(buf, locPos++);
-                        if ((flag & 0x1) != 0) {
-                            mtime = unixToJavaTime(LG(buf, locPos));
-                            locPos += 4;
-                        }
-                        if ((flag & 0x2) != 0) {
-                            atime = unixToJavaTime(LG(buf, locPos));
-                            locPos += 4;
-                        }
-                        if ((flag & 0x4) != 0) {
-                            ctime = unixToJavaTime(LG(buf, locPos));
-                            locPos += 4;
-                        }
-                        break;
-                    }
-                    break;
-                default:    // unknown tag
-                    System.arraycopy(extra, off, extra, newOff, sz + 4);
-                    newOff += (sz + 4);
-                }
-                off += (sz + 4);
-            }
-            if (newOff != 0 && newOff != extra.length)
-                extra = Arrays.copyOf(extra, newOff);
-            else
-                extra = null;
-        }
-    }
-
-    private static class ExChannelCloser  {
-        Path path;
-        SeekableByteChannel ch;
-        Set<InputStream> streams;
-        ExChannelCloser(Path path,
-                        SeekableByteChannel ch,
-                        Set<InputStream> streams)
-        {
-            this.path = path;
-            this.ch = ch;
-            this.streams = streams;
-        }
-    }
-
-    // ZIP directory has two issues:
-    // (1) ZIP spec does not require the ZIP file to include
-    //     directory entry
-    // (2) all entries are not stored/organized in a "tree"
-    //     structure.
-    // A possible solution is to build the node tree ourself as
-    // implemented below.
-    private IndexNode root;
-
-    private void addToTree(IndexNode inode, HashSet<IndexNode> dirs) {
-        if (dirs.contains(inode)) {
-            return;
-        }
-        IndexNode parent;
-        byte[] name = inode.name;
-        byte[] pname = getParent(name);
-        if (inodes.containsKey(LOOKUPKEY.as(pname))) {
-            parent = inodes.get(LOOKUPKEY);
-        } else {    // pseudo directory entry
-            parent = new IndexNode(pname, -1);
-            inodes.put(parent, parent);
-        }
-        addToTree(parent, dirs);
-        inode.sibling = parent.child;
-        parent.child = inode;
-        if (name[name.length -1] == '/')
-            dirs.add(inode);
-    }
-
-    private void removeFromTree(IndexNode inode) {
-        IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
-        IndexNode child = parent.child;
-        if (child.equals(inode)) {
-            parent.child = child.sibling;
-        } else {
-            IndexNode last = child;
-            while ((child = child.sibling) != null) {
-                if (child.equals(inode)) {
-                    last.sibling = child.sibling;
-                    break;
-                } else {
-                    last = child;
-                }
-            }
-        }
-    }
-
-    private void buildNodeTree() throws IOException {
-        beginWrite();
-        try {
-            HashSet<IndexNode> dirs = new HashSet<>();
-            IndexNode root = new IndexNode(ROOTPATH, -1);
-            inodes.put(root, root);
-            dirs.add(root);
-            for (IndexNode node : inodes.keySet().toArray(new IndexNode[0])) {
-                addToTree(node, dirs);
-            }
-        } finally {
-            endWrite();
-        }
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.*;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.DirectoryStream.Filter;
-import java.nio.file.attribute.*;
-import java.nio.file.spi.FileSystemProvider;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.zip.ZipError;
-import java.util.concurrent.ExecutorService;
-
-/*
- *
- * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
- */
-
-public class ZipFileSystemProvider extends FileSystemProvider {
-
-
-    private final Map<Path, ZipFileSystem> filesystems = new HashMap<>();
-
-    public ZipFileSystemProvider() {}
-
-    @Override
-    public String getScheme() {
-        return "jar";
-    }
-
-    protected Path uriToPath(URI uri) {
-        String scheme = uri.getScheme();
-        if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
-            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
-        }
-        try {
-            // only support legacy JAR URL syntax  jar:{uri}!/{entry} for now
-            String spec = uri.getRawSchemeSpecificPart();
-            int sep = spec.indexOf("!/");
-            if (sep != -1)
-                spec = spec.substring(0, sep);
-            return Paths.get(new URI(spec)).toAbsolutePath();
-        } catch (URISyntaxException e) {
-            throw new IllegalArgumentException(e.getMessage(), e);
-        }
-    }
-
-    private boolean ensureFile(Path path) {
-        try {
-            BasicFileAttributes attrs =
-                Files.readAttributes(path, BasicFileAttributes.class);
-            if (!attrs.isRegularFile())
-                throw new UnsupportedOperationException();
-            return true;
-        } catch (IOException ioe) {
-            return false;
-        }
-    }
-
-    @Override
-    public FileSystem newFileSystem(URI uri, Map<String, ?> env)
-        throws IOException
-    {
-        Path path = uriToPath(uri);
-        synchronized(filesystems) {
-            Path realPath = null;
-            if (ensureFile(path)) {
-                realPath = path.toRealPath();
-                if (filesystems.containsKey(realPath))
-                    throw new FileSystemAlreadyExistsException();
-            }
-            ZipFileSystem zipfs = null;
-            try {
-                zipfs = new ZipFileSystem(this, path, env);
-            } catch (ZipError ze) {
-                String pname = path.toString();
-                if (pname.endsWith(".zip") || pname.endsWith(".jar"))
-                    throw ze;
-                // assume NOT a zip/jar file
-                throw new UnsupportedOperationException();
-            }
-            filesystems.put(realPath, zipfs);
-            return zipfs;
-        }
-    }
-
-    @Override
-    public FileSystem newFileSystem(Path path, Map<String, ?> env)
-        throws IOException
-    {
-        if (path.getFileSystem() != FileSystems.getDefault()) {
-            throw new UnsupportedOperationException();
-        }
-        ensureFile(path);
-        try {
-            return new ZipFileSystem(this, path, env);
-        } catch (ZipError ze) {
-            String pname = path.toString();
-            if (pname.endsWith(".zip") || pname.endsWith(".jar"))
-                throw ze;
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @Override
-    public Path getPath(URI uri) {
-
-        String spec = uri.getSchemeSpecificPart();
-        int sep = spec.indexOf("!/");
-        if (sep == -1)
-            throw new IllegalArgumentException("URI: "
-                + uri
-                + " does not contain path info ex. jar:file:/c:/foo.zip!/BAR");
-        return getFileSystem(uri).getPath(spec.substring(sep + 1));
-    }
-
-
-    @Override
-    public FileSystem getFileSystem(URI uri) {
-        synchronized (filesystems) {
-            ZipFileSystem zipfs = null;
-            try {
-                zipfs = filesystems.get(uriToPath(uri).toRealPath());
-            } catch (IOException x) {
-                // ignore the ioe from toRealPath(), return FSNFE
-            }
-            if (zipfs == null)
-                throw new FileSystemNotFoundException();
-            return zipfs;
-        }
-    }
-
-    // Checks that the given file is a UnixPath
-    static final ZipPath toZipPath(Path path) {
-        if (path == null)
-            throw new NullPointerException();
-        if (!(path instanceof ZipPath))
-            throw new ProviderMismatchException();
-        return (ZipPath)path;
-    }
-
-    @Override
-    public void checkAccess(Path path, AccessMode... modes) throws IOException {
-        toZipPath(path).checkAccess(modes);
-    }
-
-    @Override
-    public void copy(Path src, Path target, CopyOption... options)
-        throws IOException
-    {
-        toZipPath(src).copy(toZipPath(target), options);
-    }
-
-    @Override
-    public void createDirectory(Path path, FileAttribute<?>... attrs)
-        throws IOException
-    {
-        toZipPath(path).createDirectory(attrs);
-    }
-
-    @Override
-    public final void delete(Path path) throws IOException {
-        toZipPath(path).delete();
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <V extends FileAttributeView> V
-        getFileAttributeView(Path path, Class<V> type, LinkOption... options)
-    {
-        return ZipFileAttributeView.get(toZipPath(path), type);
-    }
-
-    @Override
-    public FileStore getFileStore(Path path) throws IOException {
-        return toZipPath(path).getFileStore();
-    }
-
-    @Override
-    public boolean isHidden(Path path) {
-        return toZipPath(path).isHidden();
-    }
-
-    @Override
-    public boolean isSameFile(Path path, Path other) throws IOException {
-        return toZipPath(path).isSameFile(other);
-    }
-
-    @Override
-    public void move(Path src, Path target, CopyOption... options)
-        throws IOException
-    {
-        toZipPath(src).move(toZipPath(target), options);
-    }
-
-    @Override
-    public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
-            Set<? extends OpenOption> options,
-            ExecutorService exec,
-            FileAttribute<?>... attrs)
-            throws IOException
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public SeekableByteChannel newByteChannel(Path path,
-                                              Set<? extends OpenOption> options,
-                                              FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return toZipPath(path).newByteChannel(options, attrs);
-    }
-
-    @Override
-    public DirectoryStream<Path> newDirectoryStream(
-        Path path, Filter<? super Path> filter) throws IOException
-    {
-        return toZipPath(path).newDirectoryStream(filter);
-    }
-
-    @Override
-    public FileChannel newFileChannel(Path path,
-                                      Set<? extends OpenOption> options,
-                                      FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return toZipPath(path).newFileChannel(options, attrs);
-    }
-
-    @Override
-    public InputStream newInputStream(Path path, OpenOption... options)
-        throws IOException
-    {
-        return toZipPath(path).newInputStream(options);
-    }
-
-    @Override
-    public OutputStream newOutputStream(Path path, OpenOption... options)
-        throws IOException
-    {
-        return toZipPath(path).newOutputStream(options);
-    }
-
-    @Override
-    public <A extends BasicFileAttributes> A
-        readAttributes(Path path, Class<A> type, LinkOption... options)
-        throws IOException
-    {
-        if (type == BasicFileAttributes.class || type == ZipFileAttributes.class)
-            return (A)toZipPath(path).getAttributes();
-        return null;
-    }
-
-    @Override
-    public Map<String, Object>
-        readAttributes(Path path, String attribute, LinkOption... options)
-        throws IOException
-    {
-        return toZipPath(path).readAttributes(attribute, options);
-    }
-
-    @Override
-    public Path readSymbolicLink(Path link) throws IOException {
-        throw new UnsupportedOperationException("Not supported.");
-    }
-
-    @Override
-    public void setAttribute(Path path, String attribute,
-                             Object value, LinkOption... options)
-        throws IOException
-    {
-        toZipPath(path).setAttribute(attribute, value, options);
-    }
-
-    //////////////////////////////////////////////////////////////
-    void removeFileSystem(Path zfpath, ZipFileSystem zfs) throws IOException {
-        synchronized (filesystems) {
-            zfpath = zfpath.toRealPath();
-            if (filesystems.get(zfpath) == zfs)
-                filesystems.remove(zfpath);
-        }
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipInfo.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.Map;
-import static com.sun.nio.zipfs.ZipConstants.*;
-import static com.sun.nio.zipfs.ZipUtils.*;
-
-/**
- * Print all loc and cen headers of the ZIP file
- *
- * @author  Xueming Shen
- */
-
-public class ZipInfo {
-
-    public static void main(String[] args) throws Throwable {
-        if (args.length < 1) {
-            print("Usage: java ZipInfo zfname");
-        } else {
-            Map<String, ?> env = Collections.emptyMap();
-            ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider()
-                                    .newFileSystem(Paths.get(args[0]), env));
-            byte[] cen = zfs.cen;
-            if (cen == null) {
-                print("zip file is empty%n");
-                return;
-            }
-            int    pos = 0;
-            byte[] buf = new byte[1024];
-            int    no = 1;
-            while (pos + CENHDR < cen.length) {
-                print("----------------#%d--------------------%n", no++);
-                printCEN(cen, pos);
-
-                // use size CENHDR as the extra bytes to read, just in case the
-                // loc.extra is bigger than the cen.extra, try to avoid to read
-                // twice
-                long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR;
-                if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
-                    ZipFileSystem.zerror("read loc header failed");
-                if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) {
-                    // have to read the second time;
-                    len = LOCHDR + LOCNAM(buf) + LOCEXT(buf);
-                    if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len)
-                        ZipFileSystem.zerror("read loc header failed");
-                }
-                printLOC(buf);
-                pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos);
-            }
-            zfs.close();
-        }
-    }
-
-    static void print(String fmt, Object... objs) {
-        System.out.printf(fmt, objs);
-    }
-
-    static void printLOC(byte[] loc) {
-        print("%n");
-        print("[Local File Header]%n");
-        print("    Signature   :   %#010x%n", LOCSIG(loc));
-        if (LOCSIG(loc) != LOCSIG) {
-           print("    Wrong signature!");
-           return;
-        }
-        print("    Version     :       %#6x    [%d.%d]%n",
-                  LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10);
-        print("    Flag        :       %#6x%n", LOCFLG(loc));
-        print("    Method      :       %#6x%n", LOCHOW(loc));
-        print("    LastMTime   :   %#10x    [%tc]%n",
-              LOCTIM(loc), dosToJavaTime(LOCTIM(loc)));
-        print("    CRC         :   %#10x%n", LOCCRC(loc));
-        print("    CSize       :   %#10x%n", LOCSIZ(loc));
-        print("    Size        :   %#10x%n", LOCLEN(loc));
-        print("    NameLength  :       %#6x    [%s]%n",
-                  LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc)));
-        print("    ExtraLength :       %#6x%n", LOCEXT(loc));
-        if (LOCEXT(loc) != 0)
-            printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc));
-    }
-
-    static void printCEN(byte[] cen, int off) {
-        print("[Central Directory Header]%n");
-        print("    Signature   :   %#010x%n", CENSIG(cen, off));
-        if (CENSIG(cen, off) != CENSIG) {
-           print("    Wrong signature!");
-           return;
-        }
-        print("    VerMadeby   :       %#6x    [%d, %d.%d]%n",
-              CENVEM(cen, off), (CENVEM(cen, off) >> 8),
-              (CENVEM(cen, off) & 0xff) / 10,
-              (CENVEM(cen, off) & 0xff) % 10);
-        print("    VerExtract  :       %#6x    [%d.%d]%n",
-              CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10);
-        print("    Flag        :       %#6x%n", CENFLG(cen, off));
-        print("    Method      :       %#6x%n", CENHOW(cen, off));
-        print("    LastMTime   :   %#10x    [%tc]%n",
-              CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off)));
-        print("    CRC         :   %#10x%n", CENCRC(cen, off));
-        print("    CSize       :   %#10x%n", CENSIZ(cen, off));
-        print("    Size        :   %#10x%n", CENLEN(cen, off));
-        print("    NameLen     :       %#6x    [%s]%n",
-              CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off)));
-        print("    ExtraLen    :       %#6x%n", CENEXT(cen, off));
-        if (CENEXT(cen, off) != 0)
-            printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off));
-        print("    CommentLen  :       %#6x%n", CENCOM(cen, off));
-        print("    DiskStart   :       %#6x%n", CENDSK(cen, off));
-        print("    Attrs       :       %#6x%n", CENATT(cen, off));
-        print("    AttrsEx     :   %#10x%n", CENATX(cen, off));
-        print("    LocOff      :   %#10x%n", CENOFF(cen, off));
-
-    }
-
-    static long locoff(byte[] cen, int pos) {
-        long locoff = CENOFF(cen, pos);
-        if (locoff == ZIP64_MINVAL) {    //ZIP64
-            int off = pos + CENHDR + CENNAM(cen, pos);
-            int end = off + CENEXT(cen, pos);
-            while (off + 4 < end) {
-                int tag = SH(cen, off);
-                int sz = SH(cen, off + 2);
-                if (tag != EXTID_ZIP64) {
-                    off += 4 + sz;
-                    continue;
-                }
-                off += 4;
-                if (CENLEN(cen, pos) == ZIP64_MINVAL)
-                    off += 8;
-                if (CENSIZ(cen, pos) == ZIP64_MINVAL)
-                    off += 8;
-                return LL(cen, off);
-            }
-            // should never be here
-        }
-        return locoff;
-    }
-
-    static void printExtra(byte[] extra, int off, int len) {
-        int end = off + len;
-        while (off + 4 <= end) {
-            int tag = SH(extra, off);
-            int sz = SH(extra, off + 2);
-            print("        [tag=0x%04x, sz=%d, data= ", tag, sz);
-            if (off + sz > end) {
-                print("    Error: Invalid extra data, beyond extra length");
-                break;
-            }
-            off += 4;
-            for (int i = 0; i < sz; i++)
-                print("%02x ", extra[off + i]);
-            print("]%n");
-            switch (tag) {
-            case EXTID_ZIP64 :
-                print("         ->ZIP64: ");
-                int pos = off;
-                while (pos + 8 <= off + sz) {
-                    print(" *0x%x ", LL(extra, pos));
-                    pos += 8;
-                }
-                print("%n");
-                break;
-            case EXTID_NTFS:
-                print("         ->PKWare NTFS%n");
-                // 4 bytes reserved
-                if (SH(extra, off + 4) !=  0x0001 || SH(extra, off + 6) !=  24)
-                    print("    Error: Invalid NTFS sub-tag or subsz");
-                print("            mtime:%tc%n",
-                      winToJavaTime(LL(extra, off + 8)));
-                print("            atime:%tc%n",
-                      winToJavaTime(LL(extra, off + 16)));
-                print("            ctime:%tc%n",
-                      winToJavaTime(LL(extra, off + 24)));
-                break;
-            case EXTID_EXTT:
-                print("         ->Info-ZIP Extended Timestamp: flag=%x%n",extra[off]);
-                pos = off + 1 ;
-                while (pos + 4 <= off + sz) {
-                    print("            *%tc%n",
-                          unixToJavaTime(LG(extra, pos)));
-                    pos += 4;
-                }
-                break;
-            default:
-                print("         ->[tag=%x, size=%d]%n", tag, sz);
-            }
-            off += sz;
-        }
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,884 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.*;
-import java.net.URI;
-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.*;
-
-
-/**
- *
- * @author  Xueming Shen, Rajendra Gutupalli,Jaya Hangal
- */
-
-public class ZipPath implements Path {
-
-    private final ZipFileSystem zfs;
-    private final byte[] path;
-    private volatile int[] offsets;
-    private int hashcode = 0;  // cached hashcode (created lazily)
-
-    ZipPath(ZipFileSystem zfs, byte[] path) {
-        this(zfs, path, false);
-    }
-
-    ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized)
-    {
-        this.zfs = zfs;
-        if (normalized)
-            this.path = path;
-        else
-            this.path = normalize(path);
-    }
-
-    @Override
-    public ZipPath getRoot() {
-        if (this.isAbsolute())
-            return new ZipPath(zfs, new byte[]{path[0]});
-        else
-            return null;
-    }
-
-    @Override
-    public Path 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 new ZipPath(zfs, result);
-    }
-
-    @Override
-    public ZipPath 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 new ZipPath(zfs, result);
-    }
-
-    @Override
-    public int getNameCount() {
-        initOffsets();
-        return offsets.length;
-    }
-
-    @Override
-    public ZipPath 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 new ZipPath(zfs, result);
-    }
-
-    @Override
-    public ZipPath 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 new ZipPath(zfs, result);
-    }
-
-    @Override
-    public ZipPath toRealPath(LinkOption... options) throws IOException {
-        ZipPath realPath = new ZipPath(zfs, getResolvedPath()).toAbsolutePath();
-        realPath.checkAccess();
-        return realPath;
-    }
-
-    boolean isHidden() {
-        return false;
-    }
-
-    @Override
-    public ZipPath toAbsolutePath() {
-        if (isAbsolute()) {
-            return this;
-        } else {
-            //add / bofore the existing path
-            byte[] defaultdir = zfs.getDefaultDir().path;
-            int defaultlen = defaultdir.length;
-            boolean endsWith = (defaultdir[defaultlen - 1] == '/');
-            byte[] t = null;
-            if (endsWith)
-                t = new byte[defaultlen + path.length];
-            else
-                t = new byte[defaultlen + 1 + path.length];
-            System.arraycopy(defaultdir, 0, t, 0, defaultlen);
-            if (!endsWith)
-                t[defaultlen++] = '/';
-            System.arraycopy(path, 0, t, defaultlen, path.length);
-            return new ZipPath(zfs, t, true);  // normalized
-        }
-    }
-
-    @Override
-    public URI toUri() {
-        try {
-            return new URI("jar",
-                           zfs.getZipFile().toUri() +
-                           "!" +
-                           zfs.getString(toAbsolutePath().path),
-                           null);
-        } catch (Exception ex) {
-            throw new AssertionError(ex);
-        }
-    }
-
-    private boolean equalsNameAt(ZipPath other, int index) {
-        int mbegin = offsets[index];
-        int mlen = 0;
-        if (index == (offsets.length-1))
-            mlen = path.length - mbegin;
-        else
-            mlen = offsets[index + 1] - mbegin - 1;
-        int obegin = other.offsets[index];
-        int olen = 0;
-        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 Path relativize(Path other) {
-        final ZipPath o = checkPath(other);
-        if (o.equals(this))
-            return new ZipPath(getFileSystem(), 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 new ZipPath(getFileSystem(), result);
-    }
-
-    @Override
-    public ZipFileSystem getFileSystem() {
-        return zfs;
-    }
-
-    @Override
-    public boolean isAbsolute() {
-        return (this.path.length > 0 && path[0] == '/');
-    }
-
-    @Override
-    public ZipPath resolve(Path other) {
-        final ZipPath o = checkPath(other);
-        if (o.isAbsolute())
-            return o;
-        byte[] resolved = null;
-        if (this.path[path.length - 1] == '/') {
-            resolved = new byte[path.length + o.path.length];
-            System.arraycopy(path, 0, resolved, 0, path.length);
-            System.arraycopy(o.path, 0, resolved, path.length, o.path.length);
-        } else {
-            resolved = new byte[path.length + 1 + o.path.length];
-            System.arraycopy(path, 0, resolved, 0, path.length);
-            resolved[path.length] = '/';
-            System.arraycopy(o.path, 0, resolved, path.length + 1, o.path.length);
-        }
-        return new ZipPath(zfs, resolved);
-    }
-
-    @Override
-    public Path resolveSibling(Path other) {
-        if (other == null)
-            throw new NullPointerException();
-        Path parent = getParent();
-        return (parent == null) ? other : parent.resolve(other);
-    }
-
-    @Override
-    public boolean startsWith(Path other) {
-        final ZipPath 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 boolean endsWith(Path other) {
-        final ZipPath 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 ZipPath 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 Path normalize() {
-        byte[] resolved = getResolved();
-        if (resolved == path)    // no change
-            return this;
-        return new ZipPath(zfs, resolved, true);
-    }
-
-    private ZipPath checkPath(Path path) {
-        if (path == null)
-            throw new NullPointerException();
-        if (!(path instanceof ZipPath))
-            throw new ProviderMismatchException();
-        return (ZipPath) 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;
-            }
-        }
-    }
-
-    // resolved path for locating zip entry inside the zip file,
-    // the result path does not contain ./ and .. components
-    private volatile byte[] resolved = null;
-    byte[] getResolvedPath() {
-        byte[] r = resolved;
-        if (r == null) {
-            if (isAbsolute())
-                r = getResolved();
-            else
-                r = toAbsolutePath().getResolvedPath();
-            if (r[0] == '/')
-                r = Arrays.copyOfRange(r, 1, r.length);
-            resolved = r;
-        }
-        return resolved;
-    }
-
-    // removes redundant slashs, replace "\" to zip separator "/"
-    // and check for invalid characters
-    private 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(zfs.getString(path),
-                                               "Path: nul character not allowed");
-            prevC = c;
-        }
-        return path;
-    }
-
-    private 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(zfs.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 String toString() {
-        return zfs.getString(path);
-    }
-
-    @Override
-    public int hashCode() {
-        int h = hashcode;
-        if (h == 0)
-            hashcode = h = Arrays.hashCode(path);
-        return h;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return obj != null &&
-               obj instanceof ZipPath &&
-               this.zfs == ((ZipPath)obj).zfs &&
-               compareTo((Path) obj) == 0;
-    }
-
-    @Override
-    public int compareTo(Path other) {
-        final ZipPath 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;
-    }
-
-    public 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 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 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();
-            }
-        };
-    }
-
-    /////////////////////////////////////////////////////////////////////
-
-
-    void createDirectory(FileAttribute<?>... attrs)
-        throws IOException
-    {
-        zfs.createDirectory(getResolvedPath(), attrs);
-    }
-
-    InputStream newInputStream(OpenOption... options) throws IOException
-    {
-        if (options.length > 0) {
-            for (OpenOption opt : options) {
-                if (opt != READ)
-                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
-            }
-        }
-        return zfs.newInputStream(getResolvedPath());
-    }
-
-    DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
-        throws IOException
-    {
-        return new ZipDirectoryStream(this, filter);
-    }
-
-    void delete() throws IOException {
-        zfs.deleteFile(getResolvedPath(), true);
-    }
-
-    void deleteIfExists() throws IOException {
-        zfs.deleteFile(getResolvedPath(), false);
-    }
-
-    ZipFileAttributes getAttributes() throws IOException
-    {
-        ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath());
-        if (zfas == null)
-            throw new NoSuchFileException(toString());
-        return zfas;
-    }
-
-    void setAttribute(String attribute, Object value, LinkOption... options)
-        throws IOException
-    {
-        String type = null;
-        String attr = null;
-        int colonPos = attribute.indexOf(':');
-        if (colonPos == -1) {
-            type = "basic";
-            attr = attribute;
-        } else {
-            type = attribute.substring(0, colonPos++);
-            attr = attribute.substring(colonPos);
-        }
-        ZipFileAttributeView view = ZipFileAttributeView.get(this, type);
-        if (view == null)
-            throw new UnsupportedOperationException("view <" + view + "> is not supported");
-        view.setAttribute(attr, value);
-    }
-
-    void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
-        throws IOException
-    {
-        zfs.setTimes(getResolvedPath(), mtime, atime, ctime);
-    }
-
-    Map<String, Object> readAttributes(String attributes, LinkOption... options)
-        throws IOException
-
-    {
-        String view = null;
-        String attrs = null;
-        int colonPos = attributes.indexOf(':');
-        if (colonPos == -1) {
-            view = "basic";
-            attrs = attributes;
-        } else {
-            view = attributes.substring(0, colonPos++);
-            attrs = attributes.substring(colonPos);
-        }
-        ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view);
-        if (zfv == null) {
-            throw new UnsupportedOperationException("view not supported");
-        }
-        return zfv.readAttributes(attrs);
-    }
-
-    FileStore getFileStore() throws IOException {
-        // each ZipFileSystem only has one root (as requested for now)
-        if (exists())
-            return zfs.getFileStore(this);
-        throw new NoSuchFileException(zfs.getString(path));
-    }
-
-    boolean isSameFile(Path other) throws IOException {
-        if (this.equals(other))
-            return true;
-        if (other == null ||
-            this.getFileSystem() != other.getFileSystem())
-            return false;
-        this.checkAccess();
-        ((ZipPath)other).checkAccess();
-        return Arrays.equals(this.getResolvedPath(),
-                             ((ZipPath)other).getResolvedPath());
-    }
-
-    SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
-                                       FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return zfs.newByteChannel(getResolvedPath(), options, attrs);
-    }
-
-
-    FileChannel newFileChannel(Set<? extends OpenOption> options,
-                               FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return zfs.newFileChannel(getResolvedPath(), options, attrs);
-    }
-
-    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();
-            }
-        }
-        ZipFileAttributes attrs = zfs.getFileAttributes(getResolvedPath());
-        if (attrs == null && (path.length != 1 || path[0] != '/'))
-            throw new NoSuchFileException(toString());
-        if (w) {
-            if (zfs.isReadOnly())
-                throw new AccessDeniedException(toString());
-        }
-        if (x)
-            throw new AccessDeniedException(toString());
-    }
-
-    boolean exists() {
-        if (path.length == 1 && path[0] == '/')
-            return true;
-        try {
-            return zfs.exists(getResolvedPath());
-        } catch (IOException x) {}
-        return false;
-    }
-
-    OutputStream newOutputStream(OpenOption... options) throws IOException
-    {
-        if (options.length == 0)
-            return zfs.newOutputStream(getResolvedPath(),
-                                       CREATE_NEW, WRITE);
-        return zfs.newOutputStream(getResolvedPath(), options);
-    }
-
-    void move(ZipPath target, CopyOption... options)
-        throws IOException
-    {
-        if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
-        {
-            zfs.copyFile(true,
-                         getResolvedPath(), target.getResolvedPath(),
-                         options);
-        } else {
-            copyToTarget(target, options);
-            delete();
-        }
-    }
-
-    void copy(ZipPath target, CopyOption... options)
-        throws IOException
-    {
-        if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile()))
-            zfs.copyFile(false,
-                         getResolvedPath(), target.getResolvedPath(),
-                         options);
-        else
-            copyToTarget(target, options);
-    }
-
-    private void copyToTarget(ZipPath 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
-        ZipFileAttributes zfas = 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 (zfas.isDirectory()) {
-            // create directory or file
-            target.createDirectory();
-        } else {
-            InputStream is = zfs.newInputStream(getResolvedPath());
-            try {
-                OutputStream os = target.newOutputStream();
-                try {
-                    byte[] buf = new byte[8192];
-                    int n = 0;
-                    while ((n = is.read(buf)) != -1) {
-                        os.write(buf, 0, n);
-                    }
-                } finally {
-                    os.close();
-                }
-            } finally {
-                is.close();
-            }
-        }
-        if (copyAttrs) {
-            BasicFileAttributeView view =
-                ZipFileAttributeView.get(target, BasicFileAttributeView.class);
-            try {
-                view.setTimes(zfas.lastModifiedTime(),
-                              zfas.lastAccessTime(),
-                              zfas.creationTime());
-            } catch (IOException x) {
-                // rollback?
-                try {
-                    target.delete();
-                } catch (IOException ignore) { }
-                throw x;
-            }
-        }
-    }
-}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.nio.zipfs;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.regex.PatternSyntaxException;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- * @author Xueming Shen
- */
-
-class ZipUtils {
-
-    /*
-     * Writes a 16-bit short to the output stream in little-endian byte order.
-     */
-    public static void writeShort(OutputStream os, int v) throws IOException {
-        os.write(v & 0xff);
-        os.write((v >>> 8) & 0xff);
-    }
-
-    /*
-     * Writes a 32-bit int to the output stream in little-endian byte order.
-     */
-    public static void writeInt(OutputStream os, long v) throws IOException {
-        os.write((int)(v & 0xff));
-        os.write((int)((v >>>  8) & 0xff));
-        os.write((int)((v >>> 16) & 0xff));
-        os.write((int)((v >>> 24) & 0xff));
-    }
-
-    /*
-     * Writes a 64-bit int to the output stream in little-endian byte order.
-     */
-    public static void writeLong(OutputStream os, long v) throws IOException {
-        os.write((int)(v & 0xff));
-        os.write((int)((v >>>  8) & 0xff));
-        os.write((int)((v >>> 16) & 0xff));
-        os.write((int)((v >>> 24) & 0xff));
-        os.write((int)((v >>> 32) & 0xff));
-        os.write((int)((v >>> 40) & 0xff));
-        os.write((int)((v >>> 48) & 0xff));
-        os.write((int)((v >>> 56) & 0xff));
-    }
-
-    /*
-     * Writes an array of bytes to the output stream.
-     */
-    public static void writeBytes(OutputStream os, byte[] b)
-        throws IOException
-    {
-        os.write(b, 0, b.length);
-    }
-
-    /*
-     * Writes an array of bytes to the output stream.
-     */
-    public static void writeBytes(OutputStream os, byte[] b, int off, int len)
-        throws IOException
-    {
-        os.write(b, off, len);
-    }
-
-    /*
-     * Append a slash at the end, if it does not have one yet
-     */
-    public static byte[] toDirectoryPath(byte[] dir) {
-        if (dir.length != 0 && dir[dir.length - 1] != '/') {
-            dir = Arrays.copyOf(dir, dir.length + 1);
-            dir[dir.length - 1] = '/';
-        }
-        return dir;
-    }
-
-    /*
-     * Converts DOS time to Java time (number of milliseconds since epoch).
-     */
-    public static long dosToJavaTime(long dtime) {
-        Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
-                          (int)(((dtime >> 21) & 0x0f) - 1),
-                          (int)((dtime >> 16) & 0x1f),
-                          (int)((dtime >> 11) & 0x1f),
-                          (int)((dtime >> 5) & 0x3f),
-                          (int)((dtime << 1) & 0x3e));
-        return d.getTime();
-    }
-
-    /*
-     * Converts Java time to DOS time.
-     */
-    public static long javaToDosTime(long time) {
-        Date d = new Date(time);
-        int year = d.getYear() + 1900;
-        if (year < 1980) {
-            return (1 << 21) | (1 << 16);
-        }
-        return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
-               d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
-               d.getSeconds() >> 1;
-    }
-
-
-    // used to adjust values between Windows and java epoch
-    private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
-    public static final long winToJavaTime(long wtime) {
-        return TimeUnit.MILLISECONDS.convert(
-               wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS);
-    }
-
-    public static final long javaToWinTime(long time) {
-        return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS)
-               - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
-    }
-
-    public static final long unixToJavaTime(long utime) {
-        return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS);
-    }
-
-    public static final long javaToUnixTime(long time) {
-        return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS);
-    }
-
-    private static final String regexMetaChars = ".^$+{[]|()";
-    private static final String globMetaChars = "\\*?[{";
-    private static boolean isRegexMeta(char c) {
-        return regexMetaChars.indexOf(c) != -1;
-    }
-    private static boolean isGlobMeta(char c) {
-        return globMetaChars.indexOf(c) != -1;
-    }
-    private static char EOL = 0;  //TBD
-    private static char next(String glob, int i) {
-        if (i < glob.length()) {
-            return glob.charAt(i);
-        }
-        return EOL;
-    }
-
-    /*
-     * Creates a regex pattern from the given glob expression.
-     *
-     * @throws  PatternSyntaxException
-     */
-    public static String toRegexPattern(String globPattern) {
-        boolean inGroup = false;
-        StringBuilder regex = new StringBuilder("^");
-
-        int i = 0;
-        while (i < globPattern.length()) {
-            char c = globPattern.charAt(i++);
-            switch (c) {
-                case '\\':
-                    // escape special characters
-                    if (i == globPattern.length()) {
-                        throw new PatternSyntaxException("No character to escape",
-                                globPattern, i - 1);
-                    }
-                    char next = globPattern.charAt(i++);
-                    if (isGlobMeta(next) || isRegexMeta(next)) {
-                        regex.append('\\');
-                    }
-                    regex.append(next);
-                    break;
-                case '/':
-                    regex.append(c);
-                    break;
-                case '[':
-                    // don't match name separator in class
-                    regex.append("[[^/]&&[");
-                    if (next(globPattern, i) == '^') {
-                        // escape the regex negation char if it appears
-                        regex.append("\\^");
-                        i++;
-                    } else {
-                        // negation
-                        if (next(globPattern, i) == '!') {
-                            regex.append('^');
-                            i++;
-                        }
-                        // hyphen allowed at start
-                        if (next(globPattern, i) == '-') {
-                            regex.append('-');
-                            i++;
-                        }
-                    }
-                    boolean hasRangeStart = false;
-                    char last = 0;
-                    while (i < globPattern.length()) {
-                        c = globPattern.charAt(i++);
-                        if (c == ']') {
-                            break;
-                        }
-                        if (c == '/') {
-                            throw new PatternSyntaxException("Explicit 'name separator' in class",
-                                    globPattern, i - 1);
-                        }
-                        // TBD: how to specify ']' in a class?
-                        if (c == '\\' || c == '[' ||
-                                c == '&' && next(globPattern, i) == '&') {
-                            // escape '\', '[' or "&&" for regex class
-                            regex.append('\\');
-                        }
-                        regex.append(c);
-
-                        if (c == '-') {
-                            if (!hasRangeStart) {
-                                throw new PatternSyntaxException("Invalid range",
-                                        globPattern, i - 1);
-                            }
-                            if ((c = next(globPattern, i++)) == EOL || c == ']') {
-                                break;
-                            }
-                            if (c < last) {
-                                throw new PatternSyntaxException("Invalid range",
-                                        globPattern, i - 3);
-                            }
-                            regex.append(c);
-                            hasRangeStart = false;
-                        } else {
-                            hasRangeStart = true;
-                            last = c;
-                        }
-                    }
-                    if (c != ']') {
-                        throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
-                    }
-                    regex.append("]]");
-                    break;
-                case '{':
-                    if (inGroup) {
-                        throw new PatternSyntaxException("Cannot nest groups",
-                                globPattern, i - 1);
-                    }
-                    regex.append("(?:(?:");
-                    inGroup = true;
-                    break;
-                case '}':
-                    if (inGroup) {
-                        regex.append("))");
-                        inGroup = false;
-                    } else {
-                        regex.append('}');
-                    }
-                    break;
-                case ',':
-                    if (inGroup) {
-                        regex.append(")|(?:");
-                    } else {
-                        regex.append(',');
-                    }
-                    break;
-                case '*':
-                    if (next(globPattern, i) == '*') {
-                        // crosses directory boundaries
-                        regex.append(".*");
-                        i++;
-                    } else {
-                        // within directory boundary
-                        regex.append("[^/]*");
-                    }
-                    break;
-                case '?':
-                   regex.append("[^/]");
-                   break;
-                default:
-                    if (isRegexMeta(c)) {
-                        regex.append('\\');
-                    }
-                    regex.append(c);
-            }
-        }
-        if (inGroup) {
-            throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
-        }
-        return regex.append('$').toString();
-    }
-}
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -5166,39 +5166,7 @@
   } else if (log_file[0] != '\0' && (errstrm = fopen(log_file,"a+")) != NULL) {
     return;
   } else {
-    char log_file_name[PATH_MAX+100];
-    char tmpdir[PATH_MAX];
-#ifdef WIN32
-    int n = GetTempPath(PATH_MAX,tmpdir); //API returns with trailing '\'
-    if (n < 1 || n > PATH_MAX) {
-      sprintf(tmpdir,"C:\\");
-    }
-    sprintf(log_file_name, "%sunpack.log", tmpdir);
-#else
-    sprintf(tmpdir,"/tmp");
-    sprintf(log_file_name, "/tmp/unpack.log");
-#endif
-    if ((errstrm = fopen(log_file_name, "a+")) != NULL) {
-      log_file = errstrm_name = saveStr(log_file_name);
-      return ;
-    }
-
-    char *tname = tempnam(tmpdir,"#upkg");
-    if (tname == NULL) return;
-    sprintf(log_file_name, "%s", tname);
-    ::free(tname);
-    if ((errstrm = fopen(log_file_name, "a+")) != NULL) {
-      log_file = errstrm_name = saveStr(log_file_name);
-      return ;
-    }
-#ifndef WIN32
-    sprintf(log_file_name, "/dev/null");
-    // On windows most likely it will fail.
-    if ( (errstrm = fopen(log_file_name, "a+")) != NULL) {
-      log_file = errstrm_name = saveStr(log_file_name);
-      return ;
-    }
-#endif
+    fprintf(stderr, "Can not open log file %s\n", log_file);
     // Last resort
     // (Do not use stdout, since it might be jarout->jarfp.)
     errstrm = stderr;
--- a/jdk/src/share/native/java/net/net_util.h	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/java/net/net_util.h	Wed Jul 05 19:37:28 2017 +0200
@@ -40,7 +40,7 @@
 #define IPv6 2
 
 #define NET_ERROR(env, ex, msg) \
-{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg) }
+{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); }
 
 /************************************************************************
  * Cached field IDs
--- a/jdk/src/share/native/sun/awt/giflib/dgif_lib.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/giflib/dgif_lib.c	Wed Jul 05 19:37:28 2017 +0200
@@ -435,9 +435,7 @@
     Private->PixelCount = (long)GifFile->Image.Width *
        (long)GifFile->Image.Height;
 
-    DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
-
-    return GIF_OK;
+    return DGifSetupDecompress(GifFile);  /* Reset decompress algorithm parameters. */
 }
 
 /******************************************************************************
--- a/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/gif/gifdecoder.c	Wed Jul 05 19:37:28 2017 +0200
@@ -249,6 +249,7 @@
                 /* fill the block */
                 len = (*env)->CallIntMethod(env, this, readID,
                                             blockh, remain, blockLength + 1);
+                if (len > blockLength + 1) len = blockLength + 1;
                 if ((*env)->ExceptionOccurred(env)) {
                     return 0;
                 }
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jul 05 19:37:28 2017 +0200
@@ -945,6 +945,9 @@
                                 JPEGImageReader_readInputDataID,
                                 sb->hstreamBuffer, 0,
                                 sb->bufferLength);
+    if ((ret > 0) && ((unsigned int)ret > sb->bufferLength)) {
+         ret = sb->bufferLength;
+    }
     if ((*env)->ExceptionOccurred(env)
         || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
             cinfo->err->error_exit((j_common_ptr) cinfo);
@@ -1041,6 +1044,7 @@
                                 JPEGImageReader_readInputDataID,
                                 sb->hstreamBuffer,
                                 offset, buflen);
+    if ((ret > 0) && ((unsigned int)ret > buflen)) ret = buflen;
     if ((*env)->ExceptionOccurred(env)
         || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
         cinfo->err->error_exit((j_common_ptr) cinfo);
--- a/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c	Wed Jul 05 19:37:28 2017 +0200
@@ -349,6 +349,12 @@
 
     TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
              compptr->dc_tbl_no, compptr->ac_tbl_no);
+
+    /* This CSi (cc) should differ from the previous CSi */
+    for (ci = 0; ci < i; ci++) {
+      if (cinfo->cur_comp_info[ci] == compptr)
+        ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+    }
   }
 
   /* Collect the additional scan parameters Ss, Se, Ah/Al. */
--- a/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c	Wed Jul 05 19:37:28 2017 +0200
@@ -289,6 +289,7 @@
     buflen = (*env)->GetArrayLength(env, src->hInputBuffer);
     ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_readID,
                                 src->hInputBuffer, 0, buflen);
+    if (ret > buflen) ret = buflen;
     if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) {
         cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
     }
@@ -349,6 +350,7 @@
     }
     ret = (*env)->CallIntMethod(env, src->hInputStream, InputStream_readID,
                                 src->hInputBuffer, offset, buflen);
+    if ((ret > 0) && ((unsigned int)ret > buflen)) ret = buflen;
     if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) {
         cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
     }
@@ -424,6 +426,7 @@
         ret = (*env)->CallIntMethod(env, src->hInputStream,
                                     InputStream_readID,
                                     src->hInputBuffer, 0, buflen);
+        if (ret > buflen) ret = buflen;
         if ((*env)->ExceptionOccurred(env)) {
             cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
         }
--- a/jdk/src/share/native/sun/awt/libpng/pngrtran.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/libpng/pngrtran.c	Wed Jul 05 19:37:28 2017 +0200
@@ -1862,6 +1862,9 @@
 
          info_ptr->bit_depth = 8;
          info_ptr->num_trans = 0;
+
+         if (png_ptr->palette == NULL)
+            png_error (png_ptr, "Palette is NULL in indexed image");
       }
       else
       {
--- a/jdk/src/share/native/sun/awt/libpng/pngset.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/libpng/pngset.c	Wed Jul 05 19:37:28 2017 +0200
@@ -512,6 +512,17 @@
       }
    }
 
+   if ((num_palette > 0 && palette == NULL) ||
+      (num_palette == 0
+#        ifdef PNG_MNG_FEATURES_SUPPORTED
+            && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
+#        endif
+      ))
+   {
+      png_error(png_ptr, "Invalid palette");
+      return;
+   }
+
    /* It may not actually be necessary to set png_ptr->palette here;
     * we do it for backward compatibility with the way the png_handle_tRNS
     * function used to do the allocation.
--- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c	Wed Jul 05 19:37:28 2017 +0200
@@ -228,6 +228,49 @@
     }
 }
 
+/*
+ * We have to make sure that awt_setPixels can be safely applied to the given pair of
+ * raster and mlib image.
+ *
+ * In particular, make sure that
+ *  - dimension is the same
+ *  - number of channels in mlib image corresponds to the number of bands in the raster
+ *  - sample size in image and raster are the same.
+ *
+ * Returns:
+ *  -1 to indicate failure,
+ *   1 to indicate success
+ */
+static int setPixelsFormMlibImage(JNIEnv *env, RasterS_t *rasterP, mlib_image* img) {
+    if (rasterP->width != img->width || rasterP->height != img->height) {
+        /* dimension does not match */
+        return -1;
+    }
+
+    if (rasterP->numBands != img->channels) {
+        /* number of bands does not match */
+        return -1;
+    }
+
+    switch (rasterP->dataType) {
+    case BYTE_DATA_TYPE:
+        if (img->type != MLIB_BYTE) {
+            return -1;
+        }
+        break;
+    case SHORT_DATA_TYPE:
+        if (img->type != MLIB_SHORT && img->type != MLIB_USHORT) {
+            return -1;
+        }
+        break;
+    default:
+        /* awt_setPixels does not support such rasters */
+        return -1;
+    }
+
+    return awt_setPixels(env, rasterP, mlib_ImageGetData(img));
+}
+
 /***************************************************************************
  *                          External Functions                             *
  ***************************************************************************/
@@ -700,7 +743,9 @@
 
     /* Means that we couldn't write directly into the destination buffer */
     if (ddata == NULL) {
-        retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst));
+        if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
+            retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
+        }
     }
 
     /* Release the pinned memory */
@@ -1107,7 +1152,7 @@
         /* Need to store it back into the array */
         if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
             (*env)->ExceptionClear(env); // Could not store the array, try another way
-            retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst));
+            retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
         }
     }
 
@@ -1433,6 +1478,14 @@
         retStatus = 0;
     }
 
+   /* Release the LUT */
+    for (i=0; i < lut_nbands; i++) {
+        (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
+            (jbyte *) jtable[i].table, JNI_ABORT);
+    }
+    free ((void *) jtable);
+    free ((void *) tbl);
+
     /*
      * Means that we couldn't write directly into
      * the destination buffer
@@ -1446,13 +1499,6 @@
         }
     }
 
-    /* Release the LUT */
-    for (i=0; i < lut_nbands; i++) {
-        (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
-            (jbyte *) jtable[i].table, JNI_ABORT);
-    }
-    free ((void *) jtable);
-    free ((void *) tbl);
 
     /* Release the pinned memory */
     freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
@@ -1670,18 +1716,20 @@
         retStatus = 0;
     }
 
+    /* Release the LUT */
+    for (i=0; i < lut_nbands; i++) {
+        (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
+                                              (jbyte *) jtable[i].table, JNI_ABORT);
+    }
+
     /*
      * Means that we couldn't write directly into
      * the destination buffer
      */
     if (ddata == NULL) {
-        retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst));
-    }
-
-    /* Release the LUT */
-    for (i=0; i < lut_nbands; i++) {
-        (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
-                                              (jbyte *) jtable[i].table, JNI_ABORT);
+        if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
+            retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
+        }
     }
 
     /* Release the pinned memory */
@@ -2643,7 +2691,7 @@
             }
         }
         else if (mlibImP->type == MLIB_SHORT) {
-            return awt_setPixels(env, rasterP, mlibImP->data);
+            return setPixelsFormMlibImage(env, rasterP, mlibImP);
         }
     }
     else {
--- a/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualGlyphSubstProc2.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -154,6 +154,7 @@
             TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
             if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
               LEReferenceToArrayOf<LookupValue> valueArray(lookupTable8, success, &lookupTable8->valueArray[0], glyphCount);
+              if (LE_FAILURE(success)) { return newGlyph; }
               newGlyph = SWAPW(valueArray(glyphCode - firstGlyph, success));
             }
         }
--- a/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/ContextualSubstSubtables.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -110,6 +110,8 @@
     LEErrorCode &success,
     le_bool backtrack)
 {
+    if (LE_FAILURE(success)) { return FALSE; }
+
     le_int32 direction = 1;
     le_int32 match = 0;
 
@@ -255,6 +257,7 @@
                 le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
                 le_uint16 substCount = SWAPW(subRuleTable->substCount);
                 LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, subRuleTable->inputGlyphArray, matchCount+2);
+                if (LE_FAILURE(success)) { return 0; }
                 if (matchGlyphIDs(inputGlyphArray, matchCount, glyphIterator)) {
                   LEReferenceToArrayOf<SubstitutionLookupRecord>
                     substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount], substCount);
@@ -315,6 +318,7 @@
 
                 LEReferenceToArrayOf<le_uint16> classArray(base, success, subClassRuleTable->classArray, matchCount+1);
 
+                if (LE_FAILURE(success)) { return 0; }
                 if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) {
                     LEReferenceToArrayOf<SubstitutionLookupRecord>
                       substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount);
@@ -573,7 +577,7 @@
                 if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) {
                     LEReferenceToArrayOf<SubstitutionLookupRecord>
                       substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadClassArray.getAlias(lookaheadGlyphCount + 1, success), substCount);
-
+                    if (LE_FAILURE(success)) { return 0; }
                     applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
 
                     return inputGlyphCount + 1;
@@ -601,9 +605,10 @@
     le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
     le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
     LEReferenceToArrayOf<Offset>   inputCoverageTableOffsetArray(base, success, &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1], inputGlyphCount+2); // offset
+    if (LE_FAILURE(success)) { return 0; }
     const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
 
-    if( LE_FAILURE(success) ) { return 0; }
+    if( LE_FAILURE(success)) { return 0; }
     LEReferenceToArrayOf<Offset>   lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2);
 
     if( LE_FAILURE(success) ) { return 0; }
--- a/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/LigatureSubstProc2.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -95,7 +95,7 @@
 
     if (actionOffset != 0) {
         LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset
-        ap.addObject(ligActionIndex - 1, success);  // index offset ( one before the actual start, because we will pre-increment)
+        ap.addObject(ligActionIndex, success);
         LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY);
         LigatureActionEntry action;
         le_int32 offset, i = 0;
@@ -111,7 +111,6 @@
         do {
             le_uint32 componentGlyph = componentStack[m--]; // pop off
 
-            ap.addObject(success);
             action = SWAPL(*ap.getAlias());
 
             if (m < 0) {
@@ -145,7 +144,8 @@
               LE_DEBUG_BAD_FONT("m<0")
             }
 #endif
-        } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
+            ap.addObject(success);
+        } while (LE_SUCCESS(success) && !(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items
 
         while (mm >= 0) {
             if (++m >= nComponents) {
--- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -282,6 +282,7 @@
 
             for (le_uint16 feature = 0; feature < featureCount; feature += 1) {
               LEReferenceToArrayOf<le_uint16> featureIndexArray(langSysTable, success, langSysTable->featureIndexArray, featureCount);
+              if (LE_FAILURE(success)) { continue; }
               le_uint16 featureIndex = SWAPW(featureIndexArray.getObject(feature,success));
 
                 // don't add the required feature to the list more than once...
--- a/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -67,6 +67,7 @@
 
     LEPoint markAnchor;
     LEReferenceTo<MarkArray> markArray(base, success,  (const MarkArray *) ((char *) this + SWAPW(markArrayOffset)));
+    if(LE_FAILURE(success)) return 0;
     le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success);
     le_uint16 mcCount = SWAPW(classCount);
 
--- a/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/OpenTypeUtilities.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -79,8 +79,8 @@
 
 Offset OpenTypeUtilities::getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success)
 {
+  if(LE_FAILURE(success)) return 0;
   const TagAndOffsetRecord *r0 = (const TagAndOffsetRecord*)records.getAlias();
-  if(LE_FAILURE(success)) return 0;
 
   le_uint32 recordCount = records.getCount();
   le_uint8 bit = highBit(recordCount);
--- a/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -73,6 +73,7 @@
 
             if (offset != 0) {
               LEReferenceToArrayOf<TTGlyphID> glyphArray(subtableHeader, success, offset, LE_UNBOUNDED_ARRAY);
+              if (LE_FAILURE(success)) { continue; }
               TTGlyphID   newGlyph   = SWAPW(glyphArray(LE_GET_GLYPH(thisGlyph) - firstGlyph, success));
               glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
             }
--- a/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/font/layout/StateTableProcessor.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -97,6 +97,7 @@
 
         LEReferenceToArrayOf<EntryTableIndex> stateArray(stHeader, success, currentState, LE_UNBOUNDED_ARRAY);
         EntryTableIndex entryTableIndex = stateArray.getObject((le_uint8)classCode, success);
+        if (LE_FAILURE(success)) { break; }
         LE_STATE_PATIENCE_CURR(le_int32, currGlyph);
         currentState = processStateEntry(glyphStorage, currGlyph, entryTableIndex);
         LE_STATE_PATIENCE_INCR(currGlyph);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Wed Jul 05 19:37:28 2017 +0200
@@ -81,7 +81,7 @@
     cmsUInt32Number surround;
     cmsFloat64Number n, Nbb, Ncb, z, FL, D;
 
-       cmsContext ContextID;
+    cmsContext ContextID;
 
 } cmsCIECAM02;
 
@@ -467,6 +467,7 @@
     CAM02COLOR clr;
     cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
 
+    memset(&clr, 0, sizeof(clr));
     _cmsAssert(lpMod != NULL);
     _cmsAssert(pIn != NULL);
     _cmsAssert(pOut != NULL);
@@ -491,6 +492,7 @@
     CAM02COLOR clr;
     cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
 
+    memset(&clr, 0, sizeof(clr));
     _cmsAssert(lpMod != NULL);
     _cmsAssert(pIn != NULL);
     _cmsAssert(pOut != NULL);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Wed Jul 05 19:37:28 2017 +0200
@@ -59,8 +59,8 @@
 // IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
 
 
-#define MAXID        128     // Max lenght of identifier
-#define MAXSTR      1024     // Max lenght of string
+#define MAXID        128     // Max length of identifier
+#define MAXSTR      1024     // Max length of string
 #define MAXTABLES    255     // Max Number of tables in a single stream
 #define MAXINCLUDE    20     // Max number of nested includes
 
@@ -383,28 +383,28 @@
 //Forward declaration of some internal functions
 static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
 
-// Checks if c is a separator
+// Checks whatever c is a separator
 static
 cmsBool isseparator(int c)
 {
-        return (c == ' ') || (c == '\t') || (c == '\r');
+    return (c == ' ') || (c == '\t') ;
 }
 
-// Checks whatever if c is a valid identifier char
+// Checks whatever c is a valid identifier char
 static
 cmsBool ismiddle(int c)
 {
    return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
 }
 
-// Checks whatsever if c is a valid identifier middle char.
+// Checks whatsever c is a valid identifier middle char.
 static
 cmsBool isidchar(int c)
 {
    return isalnum(c) || ismiddle(c);
 }
 
-// Checks whatsever if c is a valid identifier first char.
+// Checks whatsever c is a valid identifier first char.
 static
 cmsBool isfirstidchar(int c)
 {
@@ -436,7 +436,6 @@
 }
 
 
-
 // Makes a file path based on a given reference path
 // NOTE: this function doesn't check if the path exists or even if it's legal
 static
@@ -634,6 +633,7 @@
     cmsFloat64Number dnum = 0.0;
     int sign = 1;
 
+    // keep safe
     if (Buffer == NULL) return 0.0;
 
     if (*Buffer == '-' || *Buffer == '+') {
@@ -869,6 +869,14 @@
 
 
         // Next line
+        case '\r':
+            NextCh(it8);
+            if (it8 ->ch == '\n')
+                NextCh(it8);
+            it8->sy = SEOLN;
+            it8->lineno++;
+            break;
+
         case '\n':
             NextCh(it8);
             it8->sy = SEOLN;
@@ -878,7 +886,7 @@
         // Comment
         case '#':
             NextCh(it8);
-            while (it8->ch && it8->ch != '\n')
+            while (it8->ch && it8->ch != '\n' && it8->ch != '\r')
                 NextCh(it8);
 
             it8->sy = SCOMMENT;
@@ -996,6 +1004,9 @@
 {
     switch (it8->sy) {
 
+    case SEOLN:   // Empty value
+                  Buffer[0]=0;
+                  break;
     case SIDENT:  strncpy(Buffer, it8->id, max);
                   Buffer[max-1]=0;
                   break;
@@ -1145,9 +1156,9 @@
         if (*Key != '#') { // Comments are ignored
 
             if (cmsstrcasecmp(Key, p->Keyword) == 0)
-                    break;
+                break;
         }
-        }
+    }
 
     if (p == NULL)
         return FALSE;
@@ -1157,11 +1168,13 @@
 
     for (; p != NULL; p = p->NextSubkey) {
 
+        if (p ->Subkey == NULL) continue;
+
         if (LastPtr) *LastPtr = p;
 
         if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
-                    return TRUE;
-        }
+            return TRUE;
+    }
 
     return FALSE;
 }
@@ -1284,7 +1297,7 @@
 
      it8 ->nTable = nTable;
 
-     return nTable;
+     return (cmsInt32Number) nTable;
 }
 
 
@@ -1389,7 +1402,7 @@
     cmsIT8* it8 = (cmsIT8*) hIT8;
     char Buffer[1024];
 
-    sprintf(Buffer, "%d", Val);
+    sprintf(Buffer, "%u", Val);
 
     return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
 }
@@ -1426,6 +1439,8 @@
 {
     const char *v = cmsIT8GetProperty(hIT8, cProp);
 
+    if (v == NULL) return 0.0;
+
     return ParseFloatNumber(v);
 }
 
@@ -1458,7 +1473,7 @@
         t -> nSamples = 10;
         }
 
-    t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *));
+    t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
     if (t->DataFormat == NULL) {
 
         SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
@@ -1514,7 +1529,7 @@
     t-> nSamples   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
     t-> nPatches   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
 
-    t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*));
+    t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*));
     if (t->Data == NULL) {
 
         SynError(it8, "AllocateDataSet: Unable to allocate data array");
@@ -1573,7 +1588,7 @@
     if (str == NULL)
         str = " ";
 
-    // Lenghth to write
+    // Length to write
     len = (cmsUInt32Number) strlen(str);
     f ->Used += len;
 
@@ -2097,7 +2112,7 @@
                                          NextCh(it8);
 
                                      // If a newline is found, then this is a type string
-                                    if (it8 ->ch == '\n') {
+                                    if (it8 ->ch == '\n' || it8->ch == '\r') {
 
                                          cmsIT8SetSheetType(it8, it8 ->id);
                                          InSymbol(it8);
@@ -2212,7 +2227,7 @@
                                         char Buffer[256];
 
                                         char *Type  = p ->Value;
-                                        int  nTable = k;
+                                        int  nTable = (int) k;
 
                                         snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
 
@@ -2566,6 +2581,8 @@
 
     Buffer = cmsIT8GetDataRowCol(hIT8, row, col);
 
+    if (Buffer == NULL) return 0.0;
+
     return ParseFloatNumber(Buffer);
 }
 
@@ -2778,7 +2795,7 @@
     if (Formatter == NULL)
         strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
     else
-        strcpy(it8->DoubleFormatter, Formatter);
+        strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
 
     it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
 }
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Wed Jul 05 19:37:28 2017 +0200
@@ -270,7 +270,7 @@
             // m2 holds CHAD from output white to D50 times abs. col. scaling
 
             // Observer is not adapted, undo the chromatic adaptation
-            _cmsMAT3per(m, &m3, ChromaticAdaptationMatrixOut);
+            _cmsMAT3per(m, &m2, ChromaticAdaptationMatrixOut);
 
             m3 = *ChromaticAdaptationMatrixIn;
             if (!_cmsMAT3inverse(&m3, &m4)) return FALSE;
@@ -411,57 +411,61 @@
     // Handle PCS mismatches. A specialized stage is added to the LUT in such case
     switch (InPCS) {
 
-        case cmsSigXYZData: // Input profile operates in XYZ
-
-            switch (OutPCS) {
+    case cmsSigXYZData: // Input profile operates in XYZ
 
-            case cmsSigXYZData:  // XYZ -> XYZ
-                if (!IsEmptyLayer(m, off))
-                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
-                break;
+        switch (OutPCS) {
 
-            case cmsSigLabData:  // XYZ -> Lab
-                if (!IsEmptyLayer(m, off))
-                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
-                cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID));
-                break;
+        case cmsSigXYZData:  // XYZ -> XYZ
+            if (!IsEmptyLayer(m, off) &&
+                !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
+                return FALSE;
+            break;
 
-            default:
-                return FALSE;   // Colorspace mismatch
-                }
-                break;
-
+        case cmsSigLabData:  // XYZ -> Lab
+            if (!IsEmptyLayer(m, off) &&
+                !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
+                return FALSE;
+            if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)))
+                return FALSE;
+            break;
 
-        case cmsSigLabData: // Input profile operates in Lab
-
-            switch (OutPCS) {
+        default:
+            return FALSE;   // Colorspace mismatch
+        }
+        break;
 
-            case cmsSigXYZData:  // Lab -> XYZ
+    case cmsSigLabData: // Input profile operates in Lab
 
-                cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID));
-                if (!IsEmptyLayer(m, off))
-                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
-                break;
+        switch (OutPCS) {
+
+        case cmsSigXYZData:  // Lab -> XYZ
 
-            case cmsSigLabData:  // Lab -> Lab
+            if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)))
+                return FALSE;
+            if (!IsEmptyLayer(m, off) &&
+                !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
+                return FALSE;
+            break;
 
-                if (!IsEmptyLayer(m, off)) {
-                    cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID));
-                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
-                    cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID));
-                }
-                break;
+        case cmsSigLabData:  // Lab -> Lab
 
-            default:
-                return FALSE;  // Mismatch
+            if (!IsEmptyLayer(m, off)) {
+                if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)) ||
+                    !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)) ||
+                    !cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)))
+                    return FALSE;
             }
             break;
 
+        default:
+            return FALSE;  // Mismatch
+        }
+        break;
 
-            // On colorspaces other than PCS, check for same space
-        default:
-            if (InPCS != OutPCS) return FALSE;
-            break;
+        // On colorspaces other than PCS, check for same space
+    default:
+        if (InPCS != OutPCS) return FALSE;
+        break;
     }
 
     return TRUE;
@@ -497,7 +501,8 @@
                                cmsFloat64Number AdaptationStates[],
                                cmsUInt32Number  dwFlags)
 {
-    cmsPipeline* Lut, *Result;
+    cmsPipeline* Lut = NULL;
+    cmsPipeline* Result;
     cmsHPROFILE hProfile;
     cmsMAT3 m;
     cmsVEC3 off;
@@ -593,8 +598,11 @@
         }
 
         // Concatenate to the output LUT
-        cmsPipelineCat(Result, Lut);
+        if (!cmsPipelineCat(Result, Lut))
+            goto Error;
+
         cmsPipelineFree(Lut);
+        Lut = NULL;
 
         // Update current space
         CurrentColorSpace = ColorSpaceOut;
@@ -604,6 +612,7 @@
 
 Error:
 
+    if (Lut != NULL) cmsPipelineFree(Lut);
     if (Result != NULL) cmsPipelineFree(Result);
     return NULL;
 
@@ -742,7 +751,8 @@
     if (CLUT == NULL) goto Error;
 
     // This is the one and only MPE in this LUT
-    cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT);
+    if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
+        goto Error;
 
     // Sample it. We cannot afford pre/post linearization this time.
     if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
@@ -959,7 +969,8 @@
     CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL);
     if (CLUT == NULL) goto Cleanup;
 
-    cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT);
+    if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
+        goto Cleanup;
 
     cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);
 
@@ -1057,7 +1068,7 @@
 }
 
 // The plug-in registration. User can add new intents or override default routines
-cmsBool  _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data)
 {
     cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data;
     cmsIntentsList* fl;
@@ -1072,7 +1083,7 @@
     fl = SearchIntent(Plugin ->Intent);
 
     if (fl == NULL) {
-        fl = (cmsIntentsList*) _cmsPluginMalloc(sizeof(cmsIntentsList));
+        fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
         if (fl == NULL) return FALSE;
     }
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Wed Jul 05 19:37:28 2017 +0200
@@ -302,8 +302,6 @@
         return NULL;
     }
 
-
-
     chunk ->BlockSize = Initial;
     chunk ->Used      = 0;
     chunk ->next      = NULL;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Wed Jul 05 19:37:28 2017 +0200
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2012 Marti Maria Saguer
+//  Copyright (c) 1998-2013 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -99,7 +99,7 @@
 static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
 
 // As a way to install new parametric curves
-cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data)
 {
     cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
     _cmsParametricCurvesCollection* fl;
@@ -110,7 +110,7 @@
           return TRUE;
     }
 
-    fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(sizeof(_cmsParametricCurvesCollection));
+    fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection));
     if (fl == NULL) return FALSE;
 
     // Copy the parameters
@@ -258,7 +258,8 @@
     }
 
     p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
-    return p;
+    if (p->InterpParams != NULL)
+        return p;
 
 Error:
     if (p -> Segments) _cmsFree(ContextID, p ->Segments);
@@ -423,7 +424,7 @@
             if (e > 0)
                 Val = pow(e, Params[0]) + Params[5];
             else
-                Val = 0;
+                Val = Params[5];
         }
         else
             Val = R*Params[3] + Params[6];
@@ -458,7 +459,7 @@
         e = Params[1]*R + Params[2];
 
         if (e < 0)
-            Val = 0;
+            Val = Params[3];
         else
             Val = pow(e, Params[0]) + Params[3];
         break;
@@ -478,7 +479,7 @@
 
        e = Params[2] * pow(R, Params[0]) + Params[3];
        if (e <= 0)
-           Val = 0;
+           Val = Params[4];
        else
            Val = Params[1]*log10(e) + Params[4];
        break;
@@ -544,7 +545,7 @@
             // Type == 0 means segment is sampled
             if (g ->Segments[i].Type == 0) {
 
-                cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0);
+                cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0);
                 cmsFloat32Number Out;
 
                 // Setup the table (TODO: clean that)
@@ -629,20 +630,21 @@
 // Use a segmented curve to store the floating point table
 cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[])
 {
-    cmsCurveSegment Seg[2];
+    cmsCurveSegment Seg[3];
 
-    // Initialize segmented curve part up to 0
-    Seg[0].x0 = -1;
+    // A segmented tone curve should have function segments in the first and last positions
+    // Initialize segmented curve part up to 0 to constant value = samples[0]
+    Seg[0].x0 = MINUS_INF;
     Seg[0].x1 = 0;
     Seg[0].Type = 6;
 
     Seg[0].Params[0] = 1;
     Seg[0].Params[1] = 0;
     Seg[0].Params[2] = 0;
-    Seg[0].Params[3] = 0;
+    Seg[0].Params[3] = values[0];
     Seg[0].Params[4] = 0;
 
-    // From zero to any
+    // From zero to 1
     Seg[1].x0 = 0;
     Seg[1].x1 = 1.0;
     Seg[1].Type = 0;
@@ -650,7 +652,19 @@
     Seg[1].nGridPoints = nEntries;
     Seg[1].SampledPoints = (cmsFloat32Number*) values;
 
-    return cmsBuildSegmentedToneCurve(ContextID, 2, Seg);
+    // Final segment is constant = lastsample
+    Seg[2].x0 = 1.0;
+    Seg[2].x1 = PLUS_INF;
+    Seg[2].Type = 6;
+
+    Seg[2].Params[0] = 1;
+    Seg[2].Params[1] = 0;
+    Seg[2].Params[2] = 0;
+    Seg[2].Params[3] = values[nEntries-1];
+    Seg[2].Params[4] = 0;
+
+
+    return cmsBuildSegmentedToneCurve(ContextID, 3, Seg);
 }
 
 // Parametric curves
@@ -993,7 +1007,7 @@
 
     if (Tab == NULL) return FALSE;
 
-    if (cmsIsToneCurveLinear(Tab)) return FALSE; // Nothing to do
+    if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do
 
     nItems = Tab -> nEntries;
 
@@ -1020,11 +1034,20 @@
 
         if (z[i] == 0.) Zeros++;
         if (z[i] >= 65535.) Poles++;
-        if (z[i] < z[i-1]) return FALSE; // Non-Monotonic
+        if (z[i] < z[i-1]) {
+            cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
+            return FALSE;
+        }
     }
 
-    if (Zeros > (nItems / 3)) return FALSE;  // Degenerated, mostly zeros
-    if (Poles > (nItems / 3)) return FALSE;  // Degenerated, mostly poles
+    if (Zeros > (nItems / 3)) {
+        cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
+        return FALSE;
+    }
+    if (Poles > (nItems / 3)) {
+        cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
+        return FALSE;
+    }
 
     // Seems ok
     for (i=0; i < nItems; i++) {
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Wed Jul 05 19:37:28 2017 +0200
@@ -249,13 +249,10 @@
     cmsFloat64Number dE1, dE2, ErrorRatio;
 
     // Assume in-gamut by default.
-    dE1 = 0.;
-    dE2 = 0;
     ErrorRatio = 1.0;
 
     // Convert input to Lab
-    if (t -> hInput != NULL)
-        cmsDoTransform(t -> hInput, In, &LabIn1, 1);
+    cmsDoTransform(t -> hInput, In, &LabIn1, 1);
 
     // converts from PCS to colorant. This always
     // does return in-gamut values,
@@ -267,7 +264,7 @@
     memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab));
 
     // Try again, but this time taking Check as input
-    cmsDoTransform(t -> hForward, &LabOut1, Proof2,  1);
+    cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1);
     cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1);
 
     // Take difference of direct value
@@ -374,7 +371,7 @@
     ProfileList[nGamutPCSposition] = hLab;
     BPCList[nGamutPCSposition] = 0;
     AdaptationList[nGamutPCSposition] = 1.0;
-    Intents[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
+    IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
 
 
     ColorSpace  = cmsGetColorSpace(hGamut);
@@ -385,45 +382,48 @@
 
     // 16 bits to Lab double
     Chain.hInput = cmsCreateExtendedTransform(ContextID,
-                                              nGamutPCSposition + 1,
-                                              ProfileList,
-                                              BPCList,
-                                              Intents,
-                                              AdaptationList,
-                                              NULL, 0,
-                                              dwFormat, TYPE_Lab_DBL,
-                                              cmsFLAGS_NOCACHE);
+        nGamutPCSposition + 1,
+        ProfileList,
+        BPCList,
+        IntentList,
+        AdaptationList,
+        NULL, 0,
+        dwFormat, TYPE_Lab_DBL,
+        cmsFLAGS_NOCACHE);
 
 
     // Does create the forward step. Lab double to device
     dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
     Chain.hForward = cmsCreateTransformTHR(ContextID,
-                                           hLab, TYPE_Lab_DBL,
-                                           hGamut, dwFormat,
-                                           INTENT_RELATIVE_COLORIMETRIC,
-                                           cmsFLAGS_NOCACHE);
+        hLab, TYPE_Lab_DBL,
+        hGamut, dwFormat,
+        INTENT_RELATIVE_COLORIMETRIC,
+        cmsFLAGS_NOCACHE);
 
     // Does create the backwards step
     Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat,
-                                           hLab, TYPE_Lab_DBL,
-                                           INTENT_RELATIVE_COLORIMETRIC,
-                                           cmsFLAGS_NOCACHE);
+        hLab, TYPE_Lab_DBL,
+        INTENT_RELATIVE_COLORIMETRIC,
+        cmsFLAGS_NOCACHE);
 
 
     // All ok?
-    if (Chain.hForward && Chain.hReverse) {
+    if (Chain.hInput && Chain.hForward && Chain.hReverse) {
 
         // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
         // dE when doing a transform back and forth on the colorimetric intent.
 
         Gamut = cmsPipelineAlloc(ContextID, 3, 1);
-
         if (Gamut != NULL) {
 
-          CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
-          cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT);
-
-          cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
+            CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
+            if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) {
+                cmsPipelineFree(Gamut);
+                Gamut = NULL;
+            }
+            else {
+                cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
+            }
         }
     }
     else
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Wed Jul 05 19:37:28 2017 +0200
@@ -83,7 +83,6 @@
 
 
 // Set the interpolation method
-
 cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
 {
     // Invoke factory, possibly in the Plug-in
@@ -831,7 +830,7 @@
                      register cmsUInt16Number Output[],
                      register const cmsInterpParams* p16)
 {
-    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
+    const cmsUInt16Number* LutTable;
     cmsS15Fixed16Number fk;
     cmsS15Fixed16Number k0, rk;
     int K0, K1;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Wed Jul 05 19:37:28 2017 +0200
@@ -154,7 +154,6 @@
     return iohandler;
 
 Error:
-    if (fm) _cmsFree(ContextID, fm);
     if (iohandler) _cmsFree(ContextID, iohandler);
     return NULL;
 
@@ -223,12 +222,17 @@
 
 // Writes data to memory, also keeps used space for further reference.
 static
-cmsBool  MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr)
+cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr)
 {
     FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
 
     if (ResData == NULL) return FALSE; // Housekeeping
 
+    // Check for available space. Clip.
+    if (iohandler ->UsedSpace + size > ResData->Size) {
+        size = ResData ->Size - iohandler ->UsedSpace;
+    }
+
     if (size == 0) return TRUE;     // Write zero bytes is ok, but does nothing
 
     memmove(ResData ->Block + ResData ->Pointer, Ptr, size);
@@ -350,7 +354,7 @@
     return nReaded;
 }
 
-// Position file pointer in the file
+// Postion file pointer in the file
 static
 cmsBool  FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset)
 {
@@ -389,13 +393,15 @@
     return TRUE;
 }
 
-// Create a iohandler for disk based files. if FileName is NULL, then 'stream' member is also set
-// to NULL and no real writting is performed. This only happens in writting access mode
+// Create a iohandler for disk based files.
 cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode)
 {
     cmsIOHANDLER* iohandler = NULL;
     FILE* fm = NULL;
 
+    _cmsAssert(FileName != NULL);
+    _cmsAssert(AccessMode != NULL);
+
     iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
     if (iohandler == NULL) return NULL;
 
@@ -432,11 +438,8 @@
     iohandler ->UsedSpace = 0;
 
     // Keep track of the original file
-    if (FileName != NULL)  {
-
-        strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1);
-        iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0;
-    }
+    strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1);
+    iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0;
 
     iohandler ->Read    = FileRead;
     iohandler ->Seek    = FileSeek;
@@ -616,6 +619,31 @@
        return _cmsSearchTag(Icc, sig, FALSE) >= 0;
 }
 
+/*
+ * Enforces that the profile version is per. spec.
+ * Operates on the big endian bytes from the profile.
+ * Called before converting to platform endianness.
+ * Byte 0 is BCD major version, so max 9.
+ * Byte 1 is 2 BCD digits, one per nibble.
+ * Reserved bytes 2 & 3 must be 0.
+ */
+static cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
+{
+    cmsUInt8Number* pByte = (cmsUInt8Number*)&DWord;
+    cmsUInt8Number temp1;
+    cmsUInt8Number temp2;
+
+    if (*pByte > 0x09) *pByte = (cmsUInt8Number)9;
+    temp1 = *(pByte+1) & 0xf0;
+    temp2 = *(pByte+1) & 0x0f;
+    if (temp1 > 0x90) temp1 = 0x90;
+    if (temp2 > 9) temp2 = 0x09;
+    *(pByte+1) = (cmsUInt8Number)(temp1 | temp2);
+    *(pByte+2) = (cmsUInt8Number)0;
+    *(pByte+3) = (cmsUInt8Number)0;
+
+    return DWord;
+}
 
 // Read profile header and validate it
 cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
@@ -643,12 +671,15 @@
     Icc -> DeviceClass     = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass);
     Icc -> ColorSpace      = (cmsColorSpaceSignature)   _cmsAdjustEndianess32(Header.colorSpace);
     Icc -> PCS             = (cmsColorSpaceSignature)   _cmsAdjustEndianess32(Header.pcs);
+
     Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent);
     Icc -> flags           = _cmsAdjustEndianess32(Header.flags);
     Icc -> manufacturer    = _cmsAdjustEndianess32(Header.manufacturer);
     Icc -> model           = _cmsAdjustEndianess32(Header.model);
+    Icc -> creator         = _cmsAdjustEndianess32(Header.creator);
+
     _cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes);
-    Icc -> Version         = _cmsAdjustEndianess32(Header.version);
+    Icc -> Version         = _cmsAdjustEndianess32(_validatedVersion(Header.version));
 
     // Get size as reported in header
     HeaderSize = _cmsAdjustEndianess32(Header.size);
@@ -815,28 +846,33 @@
 cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile)
 {
     _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
-    return (cmsUInt32Number) Icc ->manufacturer;
+    return Icc ->manufacturer;
 }
 
 void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer)
 {
     _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
-    Icc -> manufacturer = (cmsUInt32Number) manufacturer;
+    Icc -> manufacturer = manufacturer;
+}
+
+cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile)
+{
+    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
+    return Icc ->creator;
 }
 
 cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile)
 {
     _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
-    return (cmsUInt32Number) Icc ->model;
+    return Icc ->model;
 }
 
 void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model)
 {
     _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
-    Icc -> model = (cmsUInt32Number) model;
+    Icc -> model = model;
 }
 
-
 void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags)
 {
     _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
@@ -1073,7 +1109,6 @@
     return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize);
 }
 
-
 static
 cmsBool SanityCheck(_cmsICCPROFILE* profile)
 {
@@ -1112,11 +1147,13 @@
     cmsIOHANDLER* io = Icc ->IOhandler;
     cmsTagDescriptor* TagDescriptor;
     cmsTagTypeSignature TypeBase;
+    cmsTagTypeSignature Type;
     cmsTagTypeHandler* TypeHandler;
+    cmsFloat64Number   Version = cmsGetProfileVersion((cmsHPROFILE) Icc);
+    cmsTagTypeHandler LocalTypeHandler;
 
     for (i=0; i < Icc -> TagCount; i++) {
 
-
         if (Icc ->TagNames[i] == 0) continue;
 
         // Linked tags are not written
@@ -1168,7 +1205,16 @@
             TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]);
             if (TagDescriptor == NULL) continue;                        // Unsupported, ignore it
 
-            TypeHandler = Icc ->TagTypeHandlers[i];
+            if (TagDescriptor ->DecideType != NULL) {
+
+                Type = TagDescriptor ->DecideType(Version, Data);
+            }
+            else {
+
+                Type = TagDescriptor ->SupportedTypes[0];
+            }
+
+            TypeHandler =  _cmsGetTagTypeHandler(Type);
 
             if (TypeHandler == NULL) {
                 cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]);
@@ -1179,9 +1225,10 @@
             if (!_cmsWriteTypeBase(io, TypeBase))
                 return FALSE;
 
-            TypeHandler ->ContextID  = Icc ->ContextID;
-            TypeHandler ->ICCVersion = Icc ->Version;
-            if (!TypeHandler ->WritePtr(TypeHandler, io, Data, TagDescriptor ->ElemCount)) {
+            LocalTypeHandler = *TypeHandler;
+            LocalTypeHandler.ContextID  = Icc ->ContextID;
+            LocalTypeHandler.ICCVersion = Icc ->Version;
+            if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, io, Data, TagDescriptor ->ElemCount)) {
 
                 char String[5];
 
@@ -1318,8 +1365,8 @@
     // Should we just calculate the needed space?
     if (MemPtr == NULL) {
 
-        *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL);
-        return (*BytesNeeded == 0 ? FALSE : TRUE);
+           *BytesNeeded =  cmsSaveProfileToIOhandler(hProfile, NULL);
+            return (*BytesNeeded == 0 ? FALSE : TRUE);
     }
 
     // That is a real write operation
@@ -1357,10 +1404,11 @@
             cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
 
             if (TypeHandler != NULL) {
+                cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
 
-                TypeHandler ->ContextID = Icc ->ContextID;              // As an additional parameters
-                TypeHandler ->ICCVersion = Icc ->Version;
-                TypeHandler ->FreePtr(TypeHandler, Icc -> TagPtrs[i]);
+                LocalTypeHandler.ContextID = Icc ->ContextID;              // As an additional parameters
+                LocalTypeHandler.ICCVersion = Icc ->Version;
+                LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
             }
             else
                 _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
@@ -1404,6 +1452,7 @@
     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
     cmsIOHANDLER* io = Icc ->IOhandler;
     cmsTagTypeHandler* TypeHandler;
+    cmsTagTypeHandler LocalTypeHandler;
     cmsTagDescriptor*  TagDescriptor;
     cmsTagTypeSignature BaseType;
     cmsUInt32Number Offset, TagSize;
@@ -1427,7 +1476,7 @@
 
     // Seek to its location
     if (!io -> Seek(io, Offset))
-            return NULL;
+        return NULL;
 
     // Search for support on this tag
     TagDescriptor = _cmsGetTagDescriptor(sig);
@@ -1444,14 +1493,15 @@
     // Get type handler
     TypeHandler = _cmsGetTagTypeHandler(BaseType);
     if (TypeHandler == NULL) return NULL;
+    LocalTypeHandler = *TypeHandler;
 
 
     // Read the tag
     Icc -> TagTypeHandlers[n] = TypeHandler;
 
-    TypeHandler ->ContextID = Icc ->ContextID;
-    TypeHandler ->ICCVersion = Icc ->Version;
-    Icc -> TagPtrs[n] = TypeHandler ->ReadPtr(TypeHandler, io, &ElemCount, TagSize);
+    LocalTypeHandler.ContextID = Icc ->ContextID;
+    LocalTypeHandler.ICCVersion = Icc ->Version;
+    Icc -> TagPtrs[n] = LocalTypeHandler.ReadPtr(&LocalTypeHandler, io, &ElemCount, TagSize);
 
     // The tag type is supported, but something wrong happend and we cannot read the tag.
     // let know the user about this (although it is just a warning)
@@ -1472,7 +1522,7 @@
 
         _cmsTagSignature2String(String, sig);
         cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
-                                                             String, TagDescriptor ->ElemCount, ElemCount);
+            String, TagDescriptor ->ElemCount, ElemCount);
     }
 
 
@@ -1504,6 +1554,7 @@
 {
     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
     cmsTagTypeHandler* TypeHandler = NULL;
+    cmsTagTypeHandler LocalTypeHandler;
     cmsTagDescriptor* TagDescriptor = NULL;
     cmsTagTypeSignature Type;
     int i;
@@ -1534,9 +1585,10 @@
 
                 if (TypeHandler != NULL) {
 
-                    TypeHandler ->ContextID = Icc ->ContextID;              // As an additional parameter
-                    TypeHandler ->ICCVersion = Icc ->Version;
-                    TypeHandler->FreePtr(TypeHandler, Icc -> TagPtrs[i]);
+                    LocalTypeHandler = *TypeHandler;
+                    LocalTypeHandler.ContextID = Icc ->ContextID;              // As an additional parameter
+                    LocalTypeHandler.ICCVersion = Icc ->Version;
+                    LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
                 }
             }
         }
@@ -1575,7 +1627,7 @@
         // Let the tag descriptor to decide the type base on depending on
         // the data. This is useful for example on parametric curves, where
         // curves specified by a table cannot be saved as parametric and needs
-        // to be revented to single v2-curves, even on v4 profiles.
+        // to be casted to single v2-curves, even on v4 profiles.
 
         Type = TagDescriptor ->DecideType(Version, data);
     }
@@ -1613,9 +1665,10 @@
     Icc ->TagSizes[i]         = 0;
     Icc ->TagOffsets[i]       = 0;
 
-    TypeHandler ->ContextID  = Icc ->ContextID;
-    TypeHandler ->ICCVersion = Icc ->Version;
-    Icc ->TagPtrs[i]         = TypeHandler ->DupPtr(TypeHandler, data, TagDescriptor ->ElemCount);
+    LocalTypeHandler = *TypeHandler;
+    LocalTypeHandler.ContextID  = Icc ->ContextID;
+    LocalTypeHandler.ICCVersion = Icc ->Version;
+    Icc ->TagPtrs[i]         = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
 
     if (Icc ->TagPtrs[i] == NULL)  {
 
@@ -1642,6 +1695,7 @@
     int i;
     cmsIOHANDLER* MemIO;
     cmsTagTypeHandler* TypeHandler = NULL;
+    cmsTagTypeHandler LocalTypeHandler;
     cmsTagDescriptor* TagDescriptor = NULL;
     cmsUInt32Number rc;
     cmsUInt32Number Offset, TagSize;
@@ -1657,15 +1711,16 @@
         Offset   = Icc ->TagOffsets[i];
         TagSize  = Icc ->TagSizes[i];
 
-
         // read the data directly, don't keep copy
         if (data != NULL) {
 
             if (BufferSize < TagSize)
-                 TagSize = BufferSize;
+                TagSize = BufferSize;
 
             if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0;
             if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0;
+
+            return TagSize;
         }
 
         return Icc ->TagSizes[i];
@@ -1679,9 +1734,11 @@
 
             TagSize  = Icc ->TagSizes[i];
             if (BufferSize < TagSize)
-                       TagSize = BufferSize;
+                TagSize = BufferSize;
 
             memmove(data, Icc ->TagPtrs[i], TagSize);
+
+            return TagSize;
         }
 
         return Icc ->TagSizes[i];
@@ -1697,7 +1754,7 @@
     if (data == NULL) {
         MemIO = cmsOpenIOhandlerFromNULL(cmsGetProfileContextID(hProfile));
     } else{
-      MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
+        MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
     }
     if (MemIO == NULL) return 0;
 
@@ -1705,20 +1762,22 @@
     TypeHandler = Icc ->TagTypeHandlers[i];
     TagDescriptor = _cmsGetTagDescriptor(sig);
     if (TagDescriptor == NULL) {
-         cmsCloseIOhandler(MemIO);
-         return 0;
+        cmsCloseIOhandler(MemIO);
+        return 0;
     }
 
+    // FIXME: No handling for TypeHandler == NULL here?
     // Serialize
-    TypeHandler ->ContextID  = Icc ->ContextID;
-    TypeHandler ->ICCVersion = Icc ->Version;
+    LocalTypeHandler = *TypeHandler;
+    LocalTypeHandler.ContextID  = Icc ->ContextID;
+    LocalTypeHandler.ICCVersion = Icc ->Version;
 
     if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
         cmsCloseIOhandler(MemIO);
         return 0;
     }
 
-    if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
+    if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
         cmsCloseIOhandler(MemIO);
         return 0;
     }
@@ -1756,7 +1815,7 @@
 // Using this function you can collapse several tag entries to the same block in the profile
 cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest)
 {
-     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
+    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
     int i;
 
     if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Wed Jul 05 19:37:28 2017 +0200
@@ -129,7 +129,6 @@
     Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag);
 
     if (Tag != NULL) {
-
         *Dest = *Tag;
         return TRUE;
     }
@@ -193,7 +192,8 @@
     if (GrayTRC == NULL) return NULL;
 
     Lut = cmsPipelineAlloc(ContextID, 1, 3);
-    if (Lut == NULL) return NULL;
+    if (Lut == NULL)
+        goto Error;
 
     if (cmsGetPCS(hProfile) == cmsSigLabData) {
 
@@ -204,28 +204,35 @@
 
         EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
 
-        if (EmptyTab == NULL) {
-
-                 cmsPipelineFree(Lut);
-                 return NULL;
-        }
+        if (EmptyTab == NULL)
+            goto Error;
 
         LabCurves[0] = GrayTRC;
         LabCurves[1] = EmptyTab;
         LabCurves[2] = EmptyTab;
 
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3,  1, OneToThreeInputMatrix, NULL));
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3,  1, OneToThreeInputMatrix, NULL)) ||
+            !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves))) {
+                cmsFreeToneCurve(EmptyTab);
+                goto Error;
+        }
 
         cmsFreeToneCurve(EmptyTab);
 
     }
     else  {
-       cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC));
-       cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3,  1, GrayInputMatrix, NULL));
+
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC)) ||
+            !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3,  1, GrayInputMatrix, NULL)))
+            goto Error;
     }
 
     return Lut;
+
+Error:
+    cmsFreeToneCurve(GrayTRC);
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 // RGB Matrix shaper
@@ -259,49 +266,31 @@
     Lut = cmsPipelineAlloc(ContextID, 3, 3);
     if (Lut != NULL) {
 
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes));
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes)) ||
+            !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL)))
+            goto Error;
 
         // Note that it is certainly possible a single profile would have a LUT based
         // tag for output working in lab and a matrix-shaper for the fallback cases.
         // This is not allowed by the spec, but this code is tolerant to those cases
         if (cmsGetPCS(hProfile) == cmsSigLabData) {
 
-             cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID)))
+                goto Error;
         }
 
     }
 
     return Lut;
+
+Error:
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 
 
 // Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
-/*static
-cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
-{
-    cmsContext ContextID       = cmsGetProfileContextID(hProfile);
-    cmsPipeline* Lut           = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
-    cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile);
-
-    if (Lut == NULL) return NULL;
-
-    // If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
-    // and since the formatter has already accomodated to 0..1.0, we should undo this change
-    if ( spc == cmsSigLabData)
-    {
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
-    }
-    else
-        if (spc == cmsSigXYZData)
-        {
-            cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
-        }
-
-    return Lut;
-}
-*/
 static
 cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
 {
@@ -316,23 +305,31 @@
     //  these need to be normalized into the appropriate ranges (Lab = 100,0,0, XYZ=1.0,1.0,1.0)
     if ( spc == cmsSigLabData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
+            goto Error;
     }
     else if (spc == cmsSigXYZData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
+            goto Error;
     }
 
     if ( PCS == cmsSigLabData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+            goto Error;
     }
     else if( PCS == cmsSigXYZData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
+            goto Error;
     }
 
     return Lut;
+
+Error:
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 
@@ -359,8 +356,11 @@
             return NULL;
         }
 
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE));
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)) ||
+            !cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) {
+            cmsPipelineFree(Lut);
+            return NULL;
+        }
         return Lut;
     }
 
@@ -395,12 +395,18 @@
             return Lut;
 
         // If the input is Lab, add also a conversion at the begin
-        if (cmsGetColorSpace(hProfile) == cmsSigLabData)
-            cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
+        if (cmsGetColorSpace(hProfile) == cmsSigLabData &&
+            !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+            goto Error;
 
         // Add a matrix for conversion V2 to V4 Lab PCS
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+            goto Error;
+
         return Lut;
+Error:
+        cmsPipelineFree(Lut);
+        return NULL;
     }
 
     // Lut was not found, try to create a matrix-shaper
@@ -445,21 +451,27 @@
 
     if (cmsGetPCS(hProfile) == cmsSigLabData) {
 
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1,  3, PickLstarMatrix, NULL));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1,  3, PickLstarMatrix, NULL)))
+            goto Error;
     }
     else  {
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1,  3, PickYMatrix, NULL));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1,  3, PickYMatrix, NULL)))
+            goto Error;
     }
 
-    cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC));
+    if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC)))
+        goto Error;
+
     cmsFreeToneCurve(RevGrayTRC);
-
     return Lut;
+
+Error:
+    cmsFreeToneCurve(RevGrayTRC);
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 
-
-
 static
 cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
 {
@@ -506,15 +518,21 @@
         // This is not allowed by the spec, but this code is tolerant to those cases
         if (cmsGetPCS(hProfile) == cmsSigLabData) {
 
-             cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID)))
+                goto Error;
         }
 
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL));
-        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL)) ||
+            !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes)))
+            goto Error;
     }
 
     cmsFreeToneCurveTriple(InvShapes);
     return Lut;
+Error:
+    cmsFreeToneCurveTriple(InvShapes);
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 
@@ -540,30 +558,6 @@
 
 
 // Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
-/*static
-cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
-{
-    cmsContext ContextID       = cmsGetProfileContextID(hProfile);
-    cmsPipeline* Lut           = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
-    cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
-
-    if (Lut == NULL) return NULL;
-
-    // If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
-    // and since the formatter has already accomodated to 0..1.0, we should undo this change
-    if ( PCS == cmsSigLabData)
-    {
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
-    }
-    else
-        if (PCS == cmsSigXYZData)
-        {
-            cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
-        }
-
-    return Lut;
-}*/
-
 static
 cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
 {
@@ -578,25 +572,33 @@
     // and since the formatter has already accomodated to 0..1.0, we should undo this change
     if ( PCS == cmsSigLabData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
+            goto Error;
     }
     else
         if (PCS == cmsSigXYZData)
         {
-            cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
+                goto Error;
         }
 
     // the output can be Lab or XYZ, in which case normalisation is needed on the end of the pipeline
     if ( dataSpace == cmsSigLabData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+            goto Error;
     }
-    else if ( dataSpace == cmsSigXYZData)
+    else if (dataSpace == cmsSigXYZData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
+            goto Error;
     }
 
     return Lut;
+
+Error:
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 // Create an output MPE LUT from agiven profile. Version mismatches are handled here
@@ -636,30 +638,35 @@
         // Now it is time for a controversial stuff. I found that for 3D LUTS using
         // Lab used as indexer space,  trilinear interpolation should be used
         if (cmsGetPCS(hProfile) == cmsSigLabData)
-                             ChangeInterpolationToTrilinear(Lut);
+            ChangeInterpolationToTrilinear(Lut);
 
         // We need to adjust data only for Lab and Lut16 type
         if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
             return Lut;
 
         // Add a matrix for conversion V4 to V2 Lab PCS
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+            goto Error;
 
         // If the output is Lab, add also a conversion at the end
         if (cmsGetColorSpace(hProfile) == cmsSigLabData)
-            cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+                goto Error;
 
         return Lut;
+Error:
+        cmsPipelineFree(Lut);
+        return NULL;
     }
 
     // Lut not found, try to create a matrix-shaper
 
     // Check if this is a grayscale profile.
-     if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
+    if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
 
-              // if so, build appropiate conversion tables.
-              // The tables are the PCS iluminant, scaled across GrayTRC
-              return BuildGrayOutputPipeline(hProfile);
+        // if so, build appropiate conversion tables.
+        // The tables are the PCS iluminant, scaled across GrayTRC
+        return BuildGrayOutputPipeline(hProfile);
     }
 
     // Not gray, create a normal matrix-shaper, which only operates in XYZ space
@@ -681,25 +688,32 @@
 
     if (spc == cmsSigLabData)
     {
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
+            goto Error;
     }
     else
         if (spc == cmsSigXYZData)
         {
-            cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
+                goto Error;
         }
 
         if (PCS == cmsSigLabData)
         {
-            cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+                goto Error;
         }
         else
             if (PCS == cmsSigXYZData)
             {
-                cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
+                if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
+                    goto Error;
             }
 
-            return Lut;
+    return Lut;
+Error:
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 // This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
@@ -721,15 +735,21 @@
         if (nc == NULL) return NULL;
 
         Lut = cmsPipelineAlloc(ContextID, 0, 0);
-        if (Lut == NULL) {
-            cmsFreeNamedColorList(nc);
-            return NULL;
-        }
+        if (Lut == NULL)
+            goto Error;
+
+        if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE)))
+            goto Error;
 
-        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE));
         if (cmsGetColorSpace(hProfile) == cmsSigLabData)
-              cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+                goto Error;
+
         return Lut;
+Error:
+        cmsPipelineFree(Lut);
+        cmsFreeNamedColorList(nc);
+        return NULL;
     }
 
     if (cmsIsTag(hProfile, tagFloat)) {  // Float tag takes precedence
@@ -760,10 +780,10 @@
     Lut = cmsPipelineDup(Lut);
     if (Lut == NULL) return NULL;
 
-     // Now it is time for a controversial stuff. I found that for 3D LUTS using
-     // Lab used as indexer space,  trilinear interpolation should be used
+    // Now it is time for a controversial stuff. I found that for 3D LUTS using
+    // Lab used as indexer space,  trilinear interpolation should be used
     if (cmsGetColorSpace(hProfile) == cmsSigLabData)
-                        ChangeInterpolationToTrilinear(Lut);
+        ChangeInterpolationToTrilinear(Lut);
 
     // After reading it, we have info about the original type
     OriginalType =  _cmsGetTagTrueType(hProfile, tag16);
@@ -774,16 +794,20 @@
     // Here it is possible to get Lab on both sides
 
     if (cmsGetPCS(hProfile) == cmsSigLabData) {
-            cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
+        if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
+            goto Error2;
     }
 
     if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
-            cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
+        if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
+            goto Error2;
     }
 
     return Lut;
 
-
+Error2:
+    cmsPipelineFree(Lut);
+    return NULL;
 }
 
 // ---------------------------------------------------------------------------------------------------------------
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Wed Jul 05 19:37:28 2017 +0200
@@ -264,10 +264,10 @@
     if (NewElem ->TheCurves != NULL) {
         for (i=0; i < NewElem ->nCurves; i++) {
             if (NewElem ->TheCurves[i])
-                cmsFreeToneCurve(Data ->TheCurves[i]);
+                cmsFreeToneCurve(NewElem ->TheCurves[i]);
         }
     }
-    _cmsFree(mpe ->ContextID, Data ->TheCurves);
+    _cmsFree(mpe ->ContextID, NewElem ->TheCurves);
     _cmsFree(mpe ->ContextID, NewElem);
     return NULL;
 }
@@ -392,6 +392,8 @@
 void MatrixElemTypeFree(cmsStage* mpe)
 {
     _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
+    if (Data == NULL)
+        return;
     if (Data ->Double)
         _cmsFree(mpe ->ContextID, Data ->Double);
 
@@ -526,10 +528,15 @@
 
     if (Data ->Tab.T) {
 
-        if (Data ->HasFloatValues)
+        if (Data ->HasFloatValues) {
             NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number));
-        else
+            if (NewElem ->Tab.TFloat == NULL)
+                goto Error;
+        } else {
             NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number));
+            if (NewElem ->Tab.TFloat == NULL)
+                goto Error;
+        }
     }
 
     NewElem ->Params   = _cmsComputeInterpParamsEx(mpe ->ContextID,
@@ -538,8 +545,14 @@
                                                    Data ->Params ->nOutputs,
                                                    NewElem ->Tab.T,
                                                    Data ->Params ->dwFlags);
-
-    return (void*) NewElem;
+    if (NewElem->Params != NULL)
+        return (void*) NewElem;
+ Error:
+    if (NewElem->Tab.T)
+        // This works for both types
+        _cmsFree(mpe ->ContextID, NewElem -> Tab.T);
+    _cmsFree(mpe ->ContextID, NewElem);
+    return NULL;
 }
 
 
@@ -636,7 +649,6 @@
     for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
         Dimensions[i] = nGridPoints;
 
-
     return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table);
 }
 
@@ -706,15 +718,12 @@
         }
     }
 
-
     NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints,  inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT);
     if (NewElem ->Params == NULL) {
         cmsStageFree(NewMPE);
         return NULL;
     }
 
-
-
     return NewMPE;
 }
 
@@ -772,7 +781,7 @@
     int i, t, nTotalPoints, index, rest;
     int nInputs, nOutputs;
     cmsUInt32Number* nSamples;
-    cmsUInt16Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS];
+    cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
     _cmsStageCLutData* clut;
 
     if (mpe == NULL) return FALSE;
@@ -785,7 +794,9 @@
     nInputs  = clut->Params ->nInputs;
     nOutputs = clut->Params ->nOutputs;
 
-    if (nInputs >= cmsMAXCHANNELS) return FALSE;
+    if (nInputs <= 0) return FALSE;
+    if (nOutputs <= 0) return FALSE;
+    if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
     if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
 
     nTotalPoints = CubeSize(nSamples, nInputs);
@@ -832,14 +843,16 @@
     int i, t, nTotalPoints, index, rest;
     int nInputs, nOutputs;
     cmsUInt32Number* nSamples;
-    cmsFloat32Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS];
+    cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
 
     nSamples = clut->Params ->nSamples;
     nInputs  = clut->Params ->nInputs;
     nOutputs = clut->Params ->nOutputs;
 
-    if (nInputs >= cmsMAXCHANNELS) return FALSE;
+    if (nInputs <= 0) return FALSE;
+    if (nOutputs <= 0) return FALSE;
+    if (nInputs  > MAX_INPUT_DIMENSIONS) return FALSE;
     if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
 
     nTotalPoints = CubeSize(nSamples, nInputs);
@@ -1021,8 +1034,7 @@
     mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
     cmsFreeToneCurveTriple(LabTable);
 
-    if (mpe == NULL) return mpe;
-
+    if (mpe == NULL) return NULL;
     mpe ->Implements = cmsSigLabV2toV4;
     return mpe;
 }
@@ -1248,12 +1260,22 @@
                                      NULL);
     if (NewMPE == NULL) return NULL;
 
-    NewMPE ->Implements     = mpe ->Implements;
+    NewMPE ->Implements = mpe ->Implements;
+
+    if (mpe ->DupElemPtr) {
+
+        NewMPE ->Data = mpe ->DupElemPtr(mpe);
+
+        if (NewMPE->Data == NULL) {
 
-    if (mpe ->DupElemPtr)
-        NewMPE ->Data       = mpe ->DupElemPtr(mpe);
-    else
+            cmsStageFree(NewMPE);
+            return NULL;
+        }
+
+    } else {
+
         NewMPE ->Data       = NULL;
+    }
 
     return NewMPE;
 }
@@ -1266,7 +1288,7 @@
 static
 void BlessLUT(cmsPipeline* lut)
 {
-    // We can set the input/output channels only if we have elements.
+    // We can set the input/ouput channels only if we have elements.
     if (lut ->Elements != NULL) {
 
         cmsStage *First, *Last;
@@ -1466,12 +1488,12 @@
 }
 
 
-void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
+int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
 {
     cmsStage* Anterior = NULL, *pt;
 
-    _cmsAssert(lut != NULL);
-    _cmsAssert(mpe != NULL);
+    if (lut == NULL || mpe == NULL)
+        return FALSE;
 
     switch (loc) {
 
@@ -1495,9 +1517,11 @@
             }
             break;
         default:;
+            return FALSE;
     }
 
     BlessLUT(lut);
+    return TRUE;
 }
 
 // Unlink an element and return the pointer to it
@@ -1559,7 +1583,7 @@
 // Concatenate two LUT into a new single one
 cmsBool  CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
 {
-    cmsStage* mpe, *NewMPE;
+    cmsStage* mpe;
 
     // If both LUTS does not have elements, we need to inherit
     // the number of channels
@@ -1574,17 +1598,12 @@
          mpe = mpe ->Next) {
 
             // We have to dup each element
-             NewMPE = cmsStageDup(mpe);
-
-             if (NewMPE == NULL) {
-                 return FALSE;
-             }
-
-             cmsPipelineInsertStage(l1, cmsAT_END, NewMPE);
+            if (!cmsPipelineInsertStage(l1, cmsAT_END, cmsStageDup(mpe)))
+                return FALSE;
     }
 
-  BlessLUT(l1);
-  return TRUE;
+    BlessLUT(l1);
+    return TRUE;
 }
 
 
@@ -1714,16 +1733,11 @@
     cmsFloat32Number  fx[4], x[4], xd[4], fxd[4];
     cmsVEC3 tmp, tmp2;
     cmsMAT3 Jacobian;
-    cmsFloat64Number LastResult[4];
-
 
     // Only 3->3 and 4->3 are supported
     if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE;
     if (lut ->OutputChannels != 3) return FALSE;
 
-    // Mark result of -1
-    LastResult[0] = LastResult[1] = LastResult[2] = -1.0f;
-
     // Take the hint as starting point if specified
     if (Hint == NULL) {
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c	Wed Jul 05 19:37:28 2017 +0200
@@ -338,7 +338,7 @@
 Error:
 
     // Free resources as something went wrong
-    if (MD5 != NULL) _cmsFree(ContextID, MD5);
+    // "MD5" cannot be other than NULL here, so no need to free it
     if (Mem != NULL) _cmsFree(ContextID, Mem);
     memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
     return FALSE;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Wed Jul 05 19:37:28 2017 +0200
@@ -359,9 +359,9 @@
     if (Best == -1)
         Best = 0;
 
-     v = mlu ->Entries + Best;
+    v = mlu ->Entries + Best;
 
-     if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
+    if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
     if (UsedCountryCode  != NULL) *UsedCountryCode = v ->Country;
 
     if (len != NULL) *len   = v ->Len;
@@ -475,6 +475,35 @@
 }
 
 
+
+// Get the number of translations in the MLU object
+cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu)
+{
+    if (mlu == NULL) return 0;
+    return mlu->UsedEntries;
+}
+
+// Get the language and country codes for a specific MLU index
+cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
+                                          cmsUInt32Number idx,
+                                          char LanguageCode[3],
+                                          char CountryCode[3])
+{
+    _cmsMLUentry *entry;
+
+    if (mlu == NULL) return FALSE;
+
+    if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE;
+
+    entry = &mlu->Entries[idx];
+
+    *(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language);
+    *(cmsUInt16Number *)CountryCode  = _cmsAdjustEndianess16(entry->Country);
+
+    return TRUE;
+}
+
+
 // Named color lists --------------------------------------------------------------------------------------------
 
 // Grow the list to keep at least NumElements
@@ -517,9 +546,9 @@
     while (v -> Allocated < n)
         GrowNamedColorList(v);
 
-    strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix) - 1);
-    strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix) - 1);
-    v->Prefix[sizeof(v ->Prefix) - 1] = v->Suffix[sizeof(v ->Suffix) - 1] = 0;
+    strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
+    strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1);
+    v->Prefix[32] = v->Suffix[32] = 0;
 
     v -> ColorantCount = ColorantCount;
 
@@ -529,8 +558,9 @@
 // Free a list
 void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v)
 {
+    if (v == NULL) return;
     if (v ->List) _cmsFree(v ->ContextID, v ->List);
-    if (v) _cmsFree(v ->ContextID, v);
+    _cmsFree(v ->ContextID, v);
 }
 
 cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
@@ -576,11 +606,8 @@
 
     if (Name != NULL) {
 
-        strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name,
-                    sizeof(NamedColorList ->List[NamedColorList ->nColors].Name) - 1);
-
-        NamedColorList ->List[NamedColorList ->nColors].
-            Name[sizeof(NamedColorList ->List[NamedColorList ->nColors].Name) - 1] = 0;
+        strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, cmsMAX_PATH-1);
+        NamedColorList ->List[NamedColorList ->nColors].Name[cmsMAX_PATH-1] = 0;
 
     }
     else
@@ -891,7 +918,6 @@
 {
     _cmsDICT* old_dict = (_cmsDICT*) hDict;
     cmsHANDLE hNew;
-    _cmsDICT* new_dict;
     cmsDICTentry *entry;
 
     _cmsAssert(old_dict != NULL);
@@ -899,8 +925,6 @@
     hNew  = cmsDictAlloc(old_dict ->ContextID);
     if (hNew == NULL) return NULL;
 
-    new_dict = (_cmsDICT*) hNew;
-
     // Walk the list freeing all nodes
     entry = old_dict ->head;
     while (entry != NULL) {
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsopt.c	Wed Jul 05 19:37:28 2017 +0200
@@ -27,6 +27,7 @@
 // However, the following notice accompanied the original version of this
 // file:
 //
+
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
@@ -81,10 +82,6 @@
     int nInputs;
     int nOutputs;
 
-    // Since there is no limitation of the output number of channels, this buffer holding the connexion CLUT-shaper
-    // has to be dynamically allocated. This is not the case of first step shaper-CLUT, which is limited to max inputs
-    cmsUInt16Number* StageDEF;
-
     _cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS];       // The maximum number of input channels is known in advance
     cmsInterpParams*  ParamsCurveIn16[MAX_INPUT_DIMENSIONS];
 
@@ -202,8 +199,6 @@
 {
     cmsBool AnyOpt = FALSE, Opt;
 
-    AnyOpt = FALSE;
-
     do {
 
         Opt = FALSE;
@@ -253,6 +248,7 @@
 {
     Prelin16Data* p16 = (Prelin16Data*) D;
     cmsUInt16Number  StageABC[MAX_INPUT_DIMENSIONS];
+    cmsUInt16Number  StageDEF[cmsMAXCHANNELS];
     int i;
 
     for (i=0; i < p16 ->nInputs; i++) {
@@ -260,11 +256,11 @@
         p16 ->EvalCurveIn16[i](&Input[i], &StageABC[i], p16 ->ParamsCurveIn16[i]);
     }
 
-    p16 ->EvalCLUT(StageABC, p16 ->StageDEF, p16 ->CLUTparams);
+    p16 ->EvalCLUT(StageABC, StageDEF, p16 ->CLUTparams);
 
     for (i=0; i < p16 ->nOutputs; i++) {
 
-        p16 ->EvalCurveOut16[i](&p16->StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]);
+        p16 ->EvalCurveOut16[i](&StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]);
     }
 }
 
@@ -274,7 +270,6 @@
 {
     Prelin16Data* p16 = (Prelin16Data*) ptr;
 
-    _cmsFree(ContextID, p16 ->StageDEF);
     _cmsFree(ContextID, p16 ->EvalCurveOut16);
     _cmsFree(ContextID, p16 ->ParamsCurveOut16);
 
@@ -289,7 +284,6 @@
 
     if (Duped == NULL) return NULL;
 
-    Duped ->StageDEF         = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
     Duped ->EvalCurveOut16   = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
     Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
 
@@ -328,7 +322,6 @@
     p16 ->EvalCLUT   = ColorMap ->Interpolation.Lerp16;
 
 
-    p16 -> StageDEF = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
     p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
     p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
 
@@ -413,7 +406,7 @@
     int        i, index;
 
     if (CLUT -> Type != cmsSigCLutElemType) {
-        cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut MPE");
+        cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut stage");
         return FALSE;
     }
 
@@ -579,8 +572,8 @@
 static
 cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
 {
-    cmsPipeline* Src;
-    cmsPipeline* Dest;
+    cmsPipeline* Src = NULL;
+    cmsPipeline* Dest = NULL;
     cmsStage* mpe;
     cmsStage* CLUT;
     cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
@@ -593,7 +586,6 @@
     cmsToneCurve** DataSetOut;
     Prelin16Data* p16;
 
-
     // This is a loosy optimization! does not apply in floating-point cases
     if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
 
@@ -607,10 +599,10 @@
 
     Src = *Lut;
 
-   // Named color pipelines cannot be optimized either
-   for (mpe = cmsPipelineGetPtrToFirstStage(Src);
-         mpe != NULL;
-         mpe = cmsStageNext(mpe)) {
+    // Named color pipelines cannot be optimized either
+    for (mpe = cmsPipelineGetPtrToFirstStage(Src);
+        mpe != NULL;
+        mpe = cmsStageNext(mpe)) {
             if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
     }
 
@@ -632,7 +624,8 @@
 
                 // All seems ok, proceed.
                 NewPreLin = cmsStageDup(PreLin);
-                cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin);
+                if(!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin))
+                    goto Error;
 
                 // Remove prelinearization. Since we have duplicated the curve
                 // in destination LUT, the sampling shoud be applied after this stage.
@@ -646,7 +639,9 @@
     if (CLUT == NULL) return FALSE;
 
     // Add the CLUT to the destination LUT
-    cmsPipelineInsertStage(Dest, cmsAT_END, CLUT);
+    if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
+        goto Error;
+    }
 
     // Postlinearization tables are kept unless indicated by flags
     if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) {
@@ -662,7 +657,8 @@
 
                 // All seems ok, proceed.
                 NewPostLin = cmsStageDup(PostLin);
-                cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin);
+                if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin))
+                    goto Error;
 
                 // In destination LUT, the sampling shoud be applied after this stage.
                 cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin);
@@ -673,10 +669,18 @@
     // Now its time to do the sampling. We have to ignore pre/post linearization
     // The source LUT whithout pre/post curves is passed as parameter.
     if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) {
-
+Error:
         // Ops, something went wrong, Restore stages
-        if (KeepPreLin != NULL)  cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin);
-        if (KeepPostLin != NULL) cmsPipelineInsertStage(Src, cmsAT_END,   KeepPostLin);
+        if (KeepPreLin != NULL) {
+            if (!cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin)) {
+                _cmsAssert(0); // This never happens
+            }
+        }
+        if (KeepPostLin != NULL) {
+            if (!cmsPipelineInsertStage(Src, cmsAT_END,   KeepPostLin)) {
+                _cmsAssert(0); // This never happens
+            }
+        }
         cmsPipelineFree(Dest);
         return FALSE;
     }
@@ -703,12 +707,11 @@
     else {
 
         p16 = PrelinOpt16alloc(Dest ->ContextID,
-                               DataCLUT ->Params,
-                               Dest ->InputChannels,
-                               DataSetIn,
-                               Dest ->OutputChannels,
-                               DataSetOut);
-
+            DataCLUT ->Params,
+            Dest ->InputChannels,
+            DataSetIn,
+            Dest ->OutputChannels,
+            DataSetOut);
 
         _cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
     }
@@ -1062,7 +1065,8 @@
     LutPlusCurves = cmsPipelineDup(OriginalLut);
     if (LutPlusCurves == NULL) goto Error;
 
-    cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse));
+    if (!cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse)))
+        goto Error;
 
     // Create the result LUT
     OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels);
@@ -1071,13 +1075,15 @@
     OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans);
 
     // Create and insert the curves at the beginning
-    cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe);
+    if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe))
+        goto Error;
 
     // Allocate the CLUT for result
     OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL);
 
     // Add the CLUT to the destination LUT
-    cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe);
+    if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe))
+        goto Error;
 
     // Resample the LUT
     if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error;
@@ -1205,13 +1211,14 @@
     for (i=0; i < nCurves; i++) {
 
         c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
+
         if (c16->Curves[i] == NULL) {
+
             for (j=0; j < i; j++) {
                 _cmsFree(ContextID, c16->Curves[j]);
             }
             _cmsFree(ContextID, c16->Curves);
             _cmsFree(ContextID, c16);
-
             return NULL;
         }
 
@@ -1340,7 +1347,8 @@
     // Maybe the curves are linear at the end
     if (!AllCurvesAreLinear(ObtainedCurves)) {
 
-        cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves);
+        if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves))
+            goto Error;
 
         // If the curves are to be applied in 8 bits, we can save memory
         if (_cmsFormatterIs8bit(*InputFormat)) {
@@ -1348,6 +1356,7 @@
             _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data;
              Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves);
 
+             if (c16 == NULL) goto Error;
              *dwFlags |= cmsFLAGS_NOCACHE;
             _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup);
 
@@ -1357,6 +1366,7 @@
             _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves);
              Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves);
 
+             if (c16 == NULL) goto Error;
              *dwFlags |= cmsFLAGS_NOCACHE;
             _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup);
         }
@@ -1366,7 +1376,8 @@
         // LUT optimizes to nothing. Set the identity LUT
         cmsStageFree(ObtainedCurves);
 
-        cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels));
+        if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)))
+            goto Error;
 
         *dwFlags |= cmsFLAGS_NOCACHE;
         _cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL);
@@ -1596,10 +1607,14 @@
     if (!Dest) return FALSE;
 
     // Assamble the new LUT
-    cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1));
+    if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
+        goto Error;
+
     if (!IdentityMat)
-        cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset));
-    cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2));
+        if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset)))
+            goto Error;
+    if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
+        goto Error;
 
     // If identity on matrix, we can further optimize the curves, so call the join curves routine
     if (IdentityMat) {
@@ -1621,6 +1636,10 @@
     cmsPipelineFree(Src);
     *Lut = Dest;
     return TRUE;
+Error:
+    // Leave Src unchanged
+    cmsPipelineFree(Dest);
+    return FALSE;
 }
 
 
@@ -1650,7 +1669,7 @@
 static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization;
 
 // Register new ways to optimize
-cmsBool  _cmsRegisterOptimizationPlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data)
 {
     cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
     _cmsOptimizationCollection* fl;
@@ -1664,7 +1683,7 @@
     // Optimizer callback is required
     if (Plugin ->OptimizePtr == NULL) return FALSE;
 
-    fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(sizeof(_cmsOptimizationCollection));
+    fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection));
     if (fl == NULL) return FALSE;
 
     // Copy the parameters
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Wed Jul 05 19:37:28 2017 +0200
@@ -317,6 +317,23 @@
 }
 
 static
+cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(register _cmsTRANSFORM* info,
+                                              register cmsUInt16Number wIn[],
+                                              register cmsUInt8Number* accum,
+                                              register cmsUInt32Number Stride)
+{
+    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
+    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
+    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
+    accum++; // A
+
+    return accum;
+
+    cmsUNUSED_PARAMETER(info);
+    cmsUNUSED_PARAMETER(Stride);
+}
+
+static
 cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info,
                                            register cmsUInt16Number wIn[],
                                            register cmsUInt8Number* accum,
@@ -2901,6 +2918,9 @@
     { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1),     ANYSPACE,  Unroll3BytesSkip1Swap},
     { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1),  ANYSPACE,  Unroll3BytesSkip1SwapFirst},
 
+    { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
+                                                               ANYSPACE,  Unroll3BytesSkip1SwapSwapFirst},
+
     { CHANNELS_SH(4)|BYTES_SH(1),                              ANYSPACE,  Unroll4Bytes},
     { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1),                 ANYSPACE,  Unroll4BytesReverse},
     { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll4BytesSwapFirst},
@@ -3166,7 +3186,7 @@
 
 
 // Formatters management
-cmsBool  _cmsRegisterFormattersPlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data)
 {
     cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
     cmsFormattersFactoryList* fl ;
@@ -3178,7 +3198,7 @@
           return TRUE;
     }
 
-    fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(sizeof(cmsFormattersFactoryList));
+    fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList));
     if (fl == NULL) return FALSE;
 
     fl ->Factory    = Plugin ->FormattersFactory;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Wed Jul 05 19:37:28 2017 +0200
@@ -898,9 +898,11 @@
 {
     switch (ColorSpace) {
 
+    case cmsSigMCH1Data:
     case cmsSig1colorData:
     case cmsSigGrayData: return 1;
 
+    case cmsSigMCH2Data:
     case cmsSig2colorData:  return 2;
 
     case cmsSigXYZData:
@@ -912,10 +914,12 @@
     case cmsSigHsvData:
     case cmsSigHlsData:
     case cmsSigCmyData:
+    case cmsSigMCH3Data:
     case cmsSig3colorData:  return 3;
 
     case cmsSigLuvKData:
     case cmsSigCmykData:
+    case cmsSigMCH4Data:
     case cmsSig4colorData:  return 4;
 
     case cmsSigMCH5Data:
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c	Wed Jul 05 19:37:28 2017 +0200
@@ -125,10 +125,14 @@
     pOut[0] = pIn[7];
 
 #else
-
     _cmsAssert(Result != NULL);
 
+#  ifdef CMS_DONT_USE_INT64
+    (*Result)[0] = QWord[0];
+    (*Result)[1] = QWord[1];
+#  else
     *Result = *QWord;
+#  endif
 #endif
 }
 
@@ -543,10 +547,10 @@
 static _cmsSubAllocator* PluginPool = NULL;
 
 // Specialized malloc for plug-ins, that is freed upon exit.
-void* _cmsPluginMalloc(cmsUInt32Number size)
+void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size)
 {
     if (PluginPool == NULL)
-        PluginPool = _cmsCreateSubAlloc(0, 4*1024);
+        PluginPool = _cmsCreateSubAlloc(id, 4*1024);
 
     return _cmsSubAlloc(PluginPool, size);
 }
@@ -555,6 +559,11 @@
 // Main plug-in dispatcher
 cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
 {
+  return cmsPluginTHR(NULL, Plug_in);
+}
+
+cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
+{
     cmsPluginBase* Plugin;
 
     for (Plugin = (cmsPluginBase*) Plug_in;
@@ -583,35 +592,35 @@
                     break;
 
                 case cmsPluginTagTypeSig:
-                    if (!_cmsRegisterTagTypePlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginTagSig:
-                    if (!_cmsRegisterTagPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginFormattersSig:
-                    if (!_cmsRegisterFormattersPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginRenderingIntentSig:
-                    if (!_cmsRegisterRenderingIntentPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginParametricCurveSig:
-                    if (!_cmsRegisterParametricCurvesPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginMultiProcessElementSig:
-                    if (!_cmsRegisterMultiProcessElementPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginOptimizationSig:
-                    if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE;
                     break;
 
                 case cmsPluginTransformSig:
-                    if (!_cmsRegisterTransformPlugin(Plugin)) return FALSE;
+                    if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
                     break;
 
                 default:
@@ -630,14 +639,14 @@
 {
     _cmsRegisterMemHandlerPlugin(NULL);
     _cmsRegisterInterpPlugin(NULL);
-    _cmsRegisterTagTypePlugin(NULL);
-    _cmsRegisterTagPlugin(NULL);
-    _cmsRegisterFormattersPlugin(NULL);
-    _cmsRegisterRenderingIntentPlugin(NULL);
-    _cmsRegisterParametricCurvesPlugin(NULL);
-    _cmsRegisterMultiProcessElementPlugin(NULL);
-    _cmsRegisterOptimizationPlugin(NULL);
-    _cmsRegisterTransformPlugin(NULL);
+    _cmsRegisterTagTypePlugin(NULL, NULL);
+    _cmsRegisterTagPlugin(NULL, NULL);
+    _cmsRegisterFormattersPlugin(NULL, NULL);
+    _cmsRegisterRenderingIntentPlugin(NULL, NULL);
+    _cmsRegisterParametricCurvesPlugin(NULL, NULL);
+    _cmsRegisterMultiProcessElementPlugin(NULL, NULL);
+    _cmsRegisterOptimizationPlugin(NULL, NULL);
+    _cmsRegisterTransformPlugin(NULL, NULL);
 
     if (PluginPool != NULL)
         _cmsSubAllocDestroy(PluginPool);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Wed Jul 05 19:37:28 2017 +0200
@@ -806,7 +806,6 @@
 
     mpe = Pipeline ->Elements;
 
-
     switch (cmsStageInputChannels(mpe)) {
     case 3:
 
@@ -838,8 +837,6 @@
         mpe = mpe ->Next;
     }
 
-
-
     if (cmsStageType(mpe) == cmsSigCLutElemType) {
 
             _cmsIOPrintf(m, "/Table ");
@@ -854,7 +851,6 @@
     _cmsIOPrintf(m, "   >>\n");
     _cmsIOPrintf(m, "]\n");
 
-
     return 1;
 }
 
@@ -950,6 +946,7 @@
 
             rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
             cmsPipelineFree(DeviceLink);
+            if (rc == 0) return 0;
             }
             break;
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Wed Jul 05 19:37:28 2017 +0200
@@ -56,6 +56,8 @@
 #include "lcms2_internal.h"
 
 
+#define cmsmin(a, b) (((a) < (b)) ? (a) : (b))
+#define cmsmax(a, b) (((a) > (b)) ? (a) : (b))
 
 // This file contains routines for resampling and LUT optimization, black point detection
 // and black preservation.
@@ -67,13 +69,13 @@
 static
 cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent)
 {
-    cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
+    cmsContext ContextID = cmsGetProfileContextID(hProfile);
+    cmsHPROFILE hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
     cmsHTRANSFORM xform;
     cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE };
     cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 };
     cmsHPROFILE hProfiles[4];
     cmsUInt32Number Intents[4];
-    cmsContext ContextID = cmsGetProfileContextID(hProfile);
 
     hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab;
     Intents[0]   = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC;
@@ -141,8 +143,8 @@
     cmsCloseProfile(hLab);
 
     if (xform == NULL) {
+
         // Something went wrong. Get rid of open resources and return zero as black
-
         BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
         return FALSE;
     }
@@ -173,7 +175,6 @@
 // Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
 static
 cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile)
-
 {
     cmsHTRANSFORM hRoundTrip;
     cmsCIELab LabIn, LabOut;
@@ -218,17 +219,27 @@
 // involves to turn BP to neutral and to use only L component.
 cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
+    cmsProfileClassSignature devClass;
 
-    // Zero for black point
-    if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) {
+    // Make sure the device class is adequate
+    devClass = cmsGetDeviceClass(hProfile);
+    if (devClass == cmsSigLinkClass ||
+        devClass == cmsSigAbstractClass ||
+        devClass == cmsSigNamedColorClass) {
+            BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+            return FALSE;
+    }
 
-        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
-        return FALSE;
+    // Make sure intent is adequate
+    if (Intent != INTENT_PERCEPTUAL &&
+        Intent != INTENT_RELATIVE_COLORIMETRIC &&
+        Intent != INTENT_SATURATION) {
+            BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+            return FALSE;
     }
 
     // v4 + perceptual & saturation intents does have its own black point, and it is
     // well specified enough to use it. Black point tag is deprecated in V4.
-
     if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
         (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
 
@@ -303,7 +314,7 @@
 {
     double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
     double sum_y = 0, sum_yx = 0, sum_yx2 = 0;
-    double disc;
+    double d, a, b, c;
     int i;
     cmsMAT3 m;
     cmsVEC3 v, res;
@@ -333,14 +344,32 @@
 
     if (!_cmsMAT3solve(&res, &m, &v)) return 0;
 
-    // y = t x2 + u x + c
-    // x = ( - u + Sqrt( u^2 - 4 t c ) ) / ( 2 t )
-    disc = res.n[1]*res.n[1] - 4.0 * res.n[0] * res.n[2];
-    if (disc < 0) return -1;
+
+    a = res.n[2];
+    b = res.n[1];
+    c = res.n[0];
+
+    if (fabs(a) < 1.0E-10) {
+
+        return cmsmin(0, cmsmax(50, -c/b ));
+    }
+    else {
 
-    return ( -1.0 * res.n[1] + sqrt( disc )) / (2.0 * res.n[0]);
+         d = b*b - 4.0 * a * c;
+         if (d <= 0) {
+             return 0;
+         }
+         else {
+
+             double rt = (-b + sqrt(d)) / (2.0 * a);
+
+             return cmsmax(0, cmsmin(50, rt));
+         }
+   }
+
 }
 
+/*
 static
 cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
 {
@@ -361,6 +390,7 @@
 
     return TRUE;
 }
+*/
 
 // Calculates the black point of a destination profile.
 // This algorithm comes from the Adobe paper disclosing its black point compensation method.
@@ -369,21 +399,30 @@
     cmsColorSpaceSignature ColorSpace;
     cmsHTRANSFORM hRoundTrip = NULL;
     cmsCIELab InitialLab, destLab, Lab;
-
+    cmsFloat64Number inRamp[256], outRamp[256];
     cmsFloat64Number MinL, MaxL;
-    cmsBool NearlyStraightMidRange = FALSE;
-    cmsFloat64Number L;
-    cmsFloat64Number x[101], y[101];
-    cmsFloat64Number lo, hi, NonMonoMin;
-    int n, l, i, NonMonoIndx;
+    cmsBool NearlyStraightMidrange = TRUE;
+    cmsFloat64Number yRamp[256];
+    cmsFloat64Number x[256], y[256];
+    cmsFloat64Number lo, hi;
+    int n, l;
+    cmsProfileClassSignature devClass;
 
+    // Make sure the device class is adequate
+    devClass = cmsGetDeviceClass(hProfile);
+    if (devClass == cmsSigLinkClass ||
+        devClass == cmsSigAbstractClass ||
+        devClass == cmsSigNamedColorClass) {
+            BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+            return FALSE;
+    }
 
     // Make sure intent is adequate
     if (Intent != INTENT_PERCEPTUAL &&
         Intent != INTENT_RELATIVE_COLORIMETRIC &&
         Intent != INTENT_SATURATION) {
-        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
-        return FALSE;
+            BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+            return FALSE;
     }
 
 
@@ -415,10 +454,8 @@
         return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags);
     }
 
-    // It is one of the valid cases!, presto chargo hocus pocus, go for the Adobe magic
+    // It is one of the valid cases!, use Adobe algorithm
 
-    // Step 1
-    // ======
 
     // Set a first guess, that should work on good profiles.
     if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
@@ -449,71 +486,68 @@
     hRoundTrip = CreateRoundtripXForm(hProfile, Intent);
     if (hRoundTrip == NULL)  return FALSE;
 
-    // Calculate Min L*
-    Lab = InitialLab;
-    Lab.L = 0;
-    cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
-    MinL = destLab.L;
+    // Compute ramps
 
-    // Calculate Max L*
-    Lab = InitialLab;
-    Lab.L = 100;
-    cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
-    MaxL = destLab.L;
+    for (l=0; l < 256; l++) {
 
-    // Step 3
-    // ======
-
-    // check if quadratic estimation needs to be done.
-    if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
+        Lab.L = (cmsFloat64Number) (l * 100.0) / 255.0;
+        Lab.a = cmsmin(50, cmsmax(-50, InitialLab.a));
+        Lab.b = cmsmin(50, cmsmax(-50, InitialLab.b));
 
-        // Conceptually, this code tests how close the source l and converted L are to one another in the mid-range
-        // of the values. If the converted ramp of L values is close enough to a straight line y=x, then InitialLab
-        // is good enough to be the DestinationBlackPoint,
-        NearlyStraightMidRange = TRUE;
-
-        for (l=0; l <= 100; l++) {
+        cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
 
-            Lab.L = l;
-            Lab.a = InitialLab.a;
-            Lab.b = InitialLab.b;
-
-            cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
-
-            L = destLab.L;
-
-            // Check the mid range in 20% after MinL
-            if (L > (MinL + 0.2 * (MaxL - MinL))) {
+        inRamp[l]  = Lab.L;
+        outRamp[l] = destLab.L;
+    }
 
-                // Is close enough?
-                if (fabs(L - l) > 4.0) {
+    // Make monotonic
+    for (l = 254; l > 0; --l) {
+        outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]);
+    }
 
-                    // Too far away, profile is buggy!
-                    NearlyStraightMidRange = FALSE;
-                    break;
-                }
-            }
-        }
-    }
-    else {
-        // Check is always performed for perceptual and saturation intents
-        NearlyStraightMidRange = FALSE;
+    // Check
+    if (! (outRamp[0] < outRamp[255])) {
+
+        cmsDeleteTransform(hRoundTrip);
+        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+        return FALSE;
     }
 
 
-    // If no furter checking is needed, we are done
-    if (NearlyStraightMidRange) {
+    // Test for mid range straight (only on relative colorimetric)
+
+    NearlyStraightMidrange = TRUE;
+    MinL = outRamp[0]; MaxL = outRamp[255];
+    if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
+
+        for (l=0; l < 256; l++) {
 
-        cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
-        cmsDeleteTransform(hRoundTrip);
-        return TRUE;
+            if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) ||
+                (fabs(inRamp[l] - outRamp[l]) < 4.0 )))
+                NearlyStraightMidrange = FALSE;
+        }
+
+        // If the mid range is straight (as determined above) then the
+        // DestinationBlackPoint shall be the same as initialLab.
+        // Otherwise, the DestinationBlackPoint shall be determined
+        // using curve fitting.
+
+        if (NearlyStraightMidrange) {
+
+            cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
+            cmsDeleteTransform(hRoundTrip);
+            return TRUE;
+        }
     }
 
-    // The round-trip curve normally looks like a nearly constant section at the black point,
+
+    // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
     // with a corner and a nearly straight line to the white point.
 
-    // STEP 4
-    // =======
+    for (l=0; l < 256; l++) {
+
+        yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
+    }
 
     // find the black point using the least squares error quadratic curve fitting
 
@@ -528,62 +562,32 @@
         hi = 0.25;
     }
 
-    // Capture points for the fitting.
+    // Capture shadow points for the fitting.
     n = 0;
-    for (l=0; l <= 100; l++) {
-
-        cmsFloat64Number ff;
+    for (l=0; l < 256; l++) {
 
-        Lab.L = (cmsFloat64Number) l;
-        Lab.a = InitialLab.a;
-        Lab.b = InitialLab.b;
-
-        cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
-
-        ff = (destLab.L - MinL)/(MaxL - MinL);
+        cmsFloat64Number ff = yRamp[l];
 
         if (ff >= lo && ff < hi) {
-
-            x[n] = Lab.L;
-            y[n] = ff;
+            x[n] = inRamp[l];
+            y[n] = yRamp[l];
             n++;
         }
-
-    }
-
-    // This part is not on the Adobe paper, but I found is necessary for getting any result.
-
-    if (IsMonotonic(n, y)) {
-
-        // Monotonic means lower point is stil valid
-        cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
-        cmsDeleteTransform(hRoundTrip);
-        return TRUE;
-    }
-
-    // No suitable points, regret and use safer algorithm
-    if (n == 0) {
-        cmsDeleteTransform(hRoundTrip);
-        return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags);
     }
 
 
-    NonMonoMin = 100;
-    NonMonoIndx = 0;
-    for (i=0; i < n; i++) {
-
-        if (y[i] < NonMonoMin) {
-            NonMonoIndx = i;
-            NonMonoMin = y[i];
-        }
+    // No suitable points
+    if (n < 3 ) {
+        cmsDeleteTransform(hRoundTrip);
+        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
+        return FALSE;
     }
 
-    Lab.L = x[NonMonoIndx];
 
     // fit and get the vertex of quadratic curve
     Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y);
 
-    if (Lab.L < 0.0 || Lab.L > 50.0) { // clip to zero L* if the vertex is negative
+    if (Lab.L < 0.0) { // clip to zero L* if the vertex is negative
         Lab.L = 0;
     }
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmstypes.c	Wed Jul 05 19:37:28 2017 +0200
@@ -91,7 +91,7 @@
 
 // Register a new type handler. This routine is shared between normal types and MPE
 static
-cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
+cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
 {
     cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
     _cmsTagTypeLinkedList *pt, *Anterior = NULL;
@@ -118,7 +118,7 @@
     }
 
     // Registering happens in plug-in memory pool
-    pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagTypeLinkedList));
+    pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
     if (pt == NULL) return FALSE;
 
     pt ->Handler   = Plugin ->Handler;
@@ -208,10 +208,10 @@
     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 
     // Let's take the offsets to each element
-    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
     if (ElementOffsets == NULL) goto Error;
 
-    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
     if (ElementSizes == NULL) goto Error;
 
     for (i=0; i < Count; i++) {
@@ -257,10 +257,10 @@
     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 
      // Create table
-    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
     if (ElementOffsets == NULL) goto Error;
 
-    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
+    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
     if (ElementSizes == NULL) goto Error;
 
     // Keep starting position of curve offsets
@@ -456,6 +456,7 @@
 void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 {
     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
+
     cmsUNUSED_PARAMETER(n);
 }
 
@@ -1106,8 +1107,6 @@
 {
     cmsUInt32Number Count;
     cmsToneCurve* NewGamma;
-    cmsUInt16Number Linear[2] = { 0, 0xffff };
-
 
     *nItems = 0;
     if (!_cmsReadUInt32Number(io, &Count)) return NULL;
@@ -1115,11 +1114,14 @@
     switch (Count) {
 
            case 0:   // Linear.
-
-               NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, 2, Linear);
-               if (!NewGamma) return NULL;
-               *nItems = 1;
-               return NewGamma;
+               {
+                   cmsFloat64Number SingleGamma = 1.0;
+
+                   NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
+                   if (!NewGamma) return NULL;
+                   *nItems = 1;
+                   return NewGamma;
+               }
 
            case 1:  // Specified as the exponent of gamma function
                {
@@ -1210,6 +1212,7 @@
     if (ICCVersion < 4.0) return cmsSigCurveType;
     if (Curve ->nSegments != 1) return cmsSigCurveType;          // Only 1-segment curves can be saved as parametric
     if (Curve ->Segments[0].Type < 0) return cmsSigCurveType;    // Only non-inverted curves
+    if (Curve ->Segments[0].Type > 5) return cmsSigCurveType;    // Only ICC parametric curves
 
     return cmsSigParametricCurveType;
 }
@@ -1386,6 +1389,9 @@
 {
     cmsICCMeasurementConditions mc;
 
+
+    memset(&mc, 0, sizeof(mc));
+
     if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
     if (!_cmsReadXYZNumber(io,    &mc.Backing)) return NULL;
     if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
@@ -1640,7 +1646,6 @@
 static
 cmsBool  Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels)
 {
-    cmsStage* mpe;
     cmsUInt8Number* Temp = NULL;
     int i, j;
     cmsToneCurve* Tables[cmsMAXCHANNELS];
@@ -1669,11 +1674,8 @@
     _cmsFree(ContextID, Temp);
     Temp = NULL;
 
-
-    mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables);
-    if (mpe == NULL) goto Error;
-
-    cmsPipelineInsertStage(lut, cmsAT_END, mpe);
+    if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
+        goto Error;
 
     for (i=0; i < nChannels; i++)
         cmsFreeToneCurve(Tables[i]);
@@ -1701,21 +1703,30 @@
 
         if (Tables) {
 
-            if (Tables ->TheCurves[i]->nEntries != 256) {
-                cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
-                return FALSE;
+            // Usual case of identity curves
+            if ((Tables ->TheCurves[i]->nEntries == 2) &&
+                (Tables->TheCurves[i]->Table16[0] == 0) &&
+                (Tables->TheCurves[i]->Table16[1] == 65535)) {
+
+                    for (j=0; j < 256; j++) {
+                        if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE;
+                    }
             }
-
-        }
-
-        for (j=0; j < 256; j++) {
-
-            if (Tables != NULL)
-                val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
             else
-                val = (cmsUInt8Number) j;
-
-            if (!_cmsWriteUInt8Number(io, val)) return FALSE;
+                if (Tables ->TheCurves[i]->nEntries != 256) {
+                    cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
+                    return FALSE;
+                }
+                else
+                    for (j=0; j < 256; j++) {
+
+                        if (Tables != NULL)
+                            val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
+                        else
+                            val = (cmsUInt8Number) j;
+
+                        if (!_cmsWriteUInt8Number(io, val)) return FALSE;
+                    }
         }
     }
     return TRUE;
@@ -1724,7 +1735,7 @@
 
 // Check overflow
 static
-size_t uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
+cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
 {
     cmsUInt32Number rv = 1, rc;
 
@@ -1736,13 +1747,13 @@
         rv *= a;
 
         // Check for overflow
-        if (rv > UINT_MAX / a) return (size_t) -1;
+        if (rv > UINT_MAX / a) return (cmsUInt32Number) -1;
 
     }
 
     rc = rv * n;
 
-    if (rv != rc / n) return (size_t) -1;
+    if (rv != rc / n) return (cmsUInt32Number) -1;
     return rc;
 }
 
@@ -1757,7 +1768,6 @@
     cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
     cmsUInt8Number* Temp = NULL;
     cmsPipeline* NewLUT = NULL;
-    cmsStage *mpemat, *mpeclut;
     cmsUInt32Number nTabSize, i;
     cmsFloat64Number Matrix[3*3];
 
@@ -1796,9 +1806,8 @@
     // Only operates if not identity...
     if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
 
-        mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL);
-        if (mpemat == NULL) goto Error;
-        cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, mpemat);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
+            goto Error;
     }
 
     // Get input tables
@@ -1806,13 +1815,10 @@
 
     // Get 3D CLUT. Check the overflow....
     nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
-    if (nTabSize == (size_t) -1) goto Error;
+    if (nTabSize == (cmsUInt32Number) -1) goto Error;
     if (nTabSize > 0) {
 
         cmsUInt16Number *PtrW, *T;
-        cmsUInt32Number Tsize;
-
-        Tsize = (cmsUInt32Number) nTabSize * sizeof(cmsUInt16Number);
 
         PtrW = T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
         if (T  == NULL) goto Error;
@@ -1829,10 +1835,8 @@
         _cmsFree(self ->ContextID, Temp);
         Temp = NULL;
 
-
-        mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T);
-        if (mpeclut == NULL) goto Error;
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
+            goto Error;
         _cmsFree(self ->ContextID, T);
     }
 
@@ -1934,7 +1938,7 @@
     if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
 
     nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
-    if (nTabSize == (size_t) -1) return FALSE;
+    if (nTabSize == (cmsUInt32Number) -1) return FALSE;
     if (nTabSize > 0) {
 
         // The 3D CLUT.
@@ -1983,7 +1987,6 @@
 static
 cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
 {
-    cmsStage* mpe;
     int i;
     cmsToneCurve* Tables[cmsMAXCHANNELS];
 
@@ -2007,10 +2010,8 @@
 
 
     // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
-    mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables);
-    if (mpe == NULL) goto Error;
-
-    cmsPipelineInsertStage(lut, cmsAT_END, mpe);
+    if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
+        goto Error;
 
     for (i=0; i < nChannels; i++)
         cmsFreeToneCurve(Tables[i]);
@@ -2031,7 +2032,9 @@
     int j;
     cmsUInt32Number i;
     cmsUInt16Number val;
-    int nEntries = 256;
+    int nEntries;
+
+    _cmsAssert(Tables != NULL);
 
     nEntries = Tables->TheCurves[0]->nEntries;
 
@@ -2039,11 +2042,7 @@
 
         for (j=0; j < nEntries; j++) {
 
-            if (Tables != NULL)
-                val = Tables->TheCurves[i]->Table16[j];
-            else
-                val = _cmsQuantizeVal(j, nEntries);
-
+            val = Tables->TheCurves[i]->Table16[j];
             if (!_cmsWriteUInt16Number(io, val)) return FALSE;
         }
     }
@@ -2057,7 +2056,6 @@
 {
     cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
     cmsPipeline* NewLUT = NULL;
-    cmsStage *mpemat,  *mpeclut;
     cmsUInt32Number nTabSize;
     cmsFloat64Number Matrix[3*3];
     cmsUInt16Number InputEntries, OutputEntries;
@@ -2094,9 +2092,8 @@
     // Only operates on 3 channels
     if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
 
-        mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL);
-        if (mpemat == NULL) goto Error;
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpemat);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
+            goto Error;
     }
 
     if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error;
@@ -2110,7 +2107,7 @@
 
     // Get 3D CLUT
     nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
-    if (nTabSize == (size_t) -1) goto Error;
+    if (nTabSize == (cmsUInt32Number) -1) goto Error;
     if (nTabSize > 0) {
 
         cmsUInt16Number *T;
@@ -2123,13 +2120,10 @@
             goto Error;
         }
 
-        mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T);
-        if (mpeclut == NULL) {
-             _cmsFree(self ->ContextID, T);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
+            _cmsFree(self ->ContextID, T);
             goto Error;
         }
-
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
         _cmsFree(self ->ContextID, T);
     }
 
@@ -2159,7 +2153,7 @@
     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
     _cmsStageMatrixData* MatMPE = NULL;
     _cmsStageCLutData* clut = NULL;
-    int InputChannels, OutputChannels, clutPoints;
+    int i, InputChannels, OutputChannels, clutPoints;
 
     // Disassemble the LUT into components.
     mpe = NewLUT -> Elements;
@@ -2234,13 +2228,13 @@
     if (PreMPE != NULL) {
         if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
     } else {
-            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+            if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
     }
 
     if (PostMPE != NULL) {
         if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE;
     } else {
-        if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+        if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
 
     }
 
@@ -2249,9 +2243,16 @@
     if (PreMPE != NULL) {
         if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE;
     }
+    else {
+        for (i=0; i < InputChannels; i++) {
+
+            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+            if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
+        }
+    }
 
     nTabSize = uipow(OutputChannels, clutPoints, InputChannels);
-    if (nTabSize == (size_t) -1) return FALSE;
+    if (nTabSize == (cmsUInt32Number) -1) return FALSE;
     if (nTabSize > 0) {
         // The 3D CLUT.
         if (clut != NULL) {
@@ -2263,7 +2264,13 @@
     if (PostMPE != NULL) {
         if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
     }
-
+    else {
+        for (i=0; i < OutputChannels; i++) {
+
+            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
+            if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
+        }
+    }
 
     return TRUE;
 
@@ -2479,7 +2486,6 @@
     cmsUInt32Number      offsetM;        // Offset to first "M" curve
     cmsUInt32Number      offsetC;        // Offset to CLUT
     cmsUInt32Number      offsetA;        // Offset to first "A" curve
-    cmsStage* mpe;
     cmsPipeline* NewLUT = NULL;
 
 
@@ -2501,37 +2507,35 @@
     if (NewLUT == NULL) return NULL;
 
     if (offsetA!= 0) {
-        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan)))
+            goto Error;
     }
 
     if (offsetC != 0) {
-        mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
+            goto Error;
     }
 
     if (offsetM != 0) {
-        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
+            goto Error;
     }
 
     if (offsetMat != 0) {
-        mpe = ReadMatrix(self, io, BaseOffset + offsetMat);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
+            goto Error;
     }
 
     if (offsetB != 0) {
-        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
+            goto Error;
     }
 
     *nItems = 1;
     return NewLUT;
+Error:
+    cmsPipelineFree(NewLUT);
+    return NULL;
 
     cmsUNUSED_PARAMETER(SizeOfTag);
 }
@@ -2798,7 +2802,6 @@
     cmsUInt32Number      offsetM;        // Offset to first "M" curve
     cmsUInt32Number      offsetC;        // Offset to CLUT
     cmsUInt32Number      offsetA;        // Offset to first "A" curve
-    cmsStage* mpe;
     cmsPipeline* NewLUT = NULL;
 
 
@@ -2821,37 +2824,35 @@
     if (NewLUT == NULL) return NULL;
 
     if (offsetB != 0) {
-        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan)))
+            goto Error;
     }
 
     if (offsetMat != 0) {
-        mpe = ReadMatrix(self, io, BaseOffset + offsetMat);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
+            goto Error;
     }
 
     if (offsetM != 0) {
-        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
+            goto Error;
     }
 
     if (offsetC != 0) {
-        mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
+            goto Error;
     }
 
     if (offsetA!= 0) {
-        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan);
-        if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; }
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
+            goto Error;
     }
 
     *nItems = 1;
     return NewLUT;
+Error:
+    cmsPipelineFree(NewLUT);
+    return NULL;
 
     cmsUNUSED_PARAMETER(SizeOfTag);
 }
@@ -3287,7 +3288,7 @@
         SizeOfTag -= sizeof(cmsUInt32Number);
 
         if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error;
-        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
+        if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error;
         SizeOfTag -= sizeof(cmsUInt64Number);
 
         if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error;
@@ -4292,6 +4293,9 @@
     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
 
+    if (InputChans == 0) goto Error;
+    if (OutputChans == 0) goto Error;
+
     if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
         goto Error;
 
@@ -4381,7 +4385,6 @@
 {
     cmsStageSignature ElementSig;
     cmsTagTypeHandler* TypeHandler;
-    cmsStage *mpe = NULL;
     cmsUInt32Number nItems;
     cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
 
@@ -4409,11 +4412,8 @@
     if (TypeHandler ->ReadPtr != NULL) {
 
         // This is a real element which should be read and processed
-        mpe = (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag);
-        if (mpe == NULL) return FALSE;
-
-        // All seems ok, insert element
-        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
+            return FALSE;
     }
 
     return TRUE;
@@ -4479,10 +4479,10 @@
     outputChan = cmsPipelineOutputChannels(Lut);
     ElemCount  = cmsPipelineStageCount(Lut);
 
-    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
+    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
     if (ElementOffsets == NULL) goto Error;
 
-    ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
+    ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
     if (ElementSizes == NULL) goto Error;
 
     // Write the head
@@ -4825,10 +4825,10 @@
 static
 cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e,  cmsUInt32Number Count)
 {
-    e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *));
+    e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
     if (e->Offsets == NULL) return FALSE;
 
-    e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *));
+    e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
     if (e->Sizes == NULL) {
 
         _cmsFree(ContextID, e -> Offsets);
@@ -4844,7 +4844,7 @@
 void FreeElem(_cmsDICelem* e)
 {
     if (e ->Offsets != NULL)  _cmsFree(e -> ContextID, e -> Offsets);
-    if (e ->Sizes   != NULL)  _cmsFree(e -> ContextID, e ->Sizes);
+    if (e ->Sizes   != NULL)  _cmsFree(e -> ContextID, e -> Sizes);
     e->Offsets = e ->Sizes = NULL;
 }
 
@@ -5084,7 +5084,7 @@
     if (!_cmsReadUInt32Number(io, &Count)) return NULL;
     SizeOfTag -= sizeof(cmsUInt32Number);
 
-    // Get rec lenghth
+    // Get rec length
     if (!_cmsReadUInt32Number(io, &Length)) return NULL;
     SizeOfTag -= sizeof(cmsUInt32Number);
 
@@ -5118,14 +5118,22 @@
             if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error;
         }
 
+        if (NameWCS == NULL || ValueWCS == NULL) {
+
+            cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED, "Bad dictionary Name/Value");
+            rc = FALSE;
+        }
+        else {
+
         rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
+        }
 
         if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
         if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS);
         if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU);
         if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU);
 
-        if (!rc) return FALSE;
+        if (!rc) goto Error;
     }
 
    FreeArray(&a);
@@ -5277,14 +5285,14 @@
 #define DEFAULT_TAG_TYPE_COUNT  (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList))
 
 // Both kind of plug-ins share same structure
-cmsBool  _cmsRegisterTagTypePlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data)
 {
-    return RegisterTypesPlugin(Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
+    return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
 }
 
-cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data)
 {
-    return RegisterTypesPlugin(Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
+    return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
 }
 
 
@@ -5391,7 +5399,9 @@
     { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
     { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
     { cmsSigMetaTag,                { 1, 1, { cmsSigDictType},               NULL }, &SupportedTags[61]},
-    { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL},  NULL}
+    { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL },  &SupportedTags[62]},
+    { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL}
+
 
 };
 
@@ -5406,7 +5416,7 @@
 
 #define DEFAULT_TAG_COUNT  (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList))
 
-cmsBool  _cmsRegisterTagPlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
 {
     cmsPluginTag* Plugin = (cmsPluginTag*) Data;
     _cmsTagLinkedList *pt, *Anterior;
@@ -5430,7 +5440,7 @@
         pt = pt ->Next;
     }
 
-    pt = (_cmsTagLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagLinkedList));
+    pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList));
     if (pt == NULL) return FALSE;
 
     pt ->Signature  = Plugin ->Signature;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Wed Jul 05 19:37:28 2017 +0200
@@ -208,9 +208,26 @@
 
     if (TransferFunction) {
 
+        // Tries to minimize space. Thanks to Richard Hughes for this nice idea
         if (!cmsWriteTag(hICC, cmsSigRedTRCTag,   (void*) TransferFunction[0])) goto Error;
-        if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
-        if (!cmsWriteTag(hICC, cmsSigBlueTRCTag,  (void*) TransferFunction[2])) goto Error;
+
+        if (TransferFunction[1] == TransferFunction[0]) {
+
+            if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error;
+
+        } else {
+
+            if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
+        }
+
+        if (TransferFunction[2] == TransferFunction[0]) {
+
+            if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error;
+
+        } else {
+
+            if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
+        }
     }
 
     if (Primaries) {
@@ -303,7 +320,6 @@
 {
     cmsHPROFILE hICC;
     cmsPipeline* Pipeline;
-    cmsStage* Lin;
     int nChannels;
 
     hICC = cmsCreateProfilePlaceholder(ContextID);
@@ -327,10 +343,8 @@
 
 
     // Copy tables to Pipeline
-    Lin = cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions);
-    if (Lin == NULL) goto Error;
-
-    cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Lin);
+    if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions)))
+        goto Error;
 
     // Create tags
     if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;
@@ -344,6 +358,7 @@
     return hICC;
 
 Error:
+    cmsPipelineFree(Pipeline);
     if (hICC)
         cmsCloseProfile(hICC);
 
@@ -451,9 +466,10 @@
 
     if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error;
 
-    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels));
-    cmsPipelineInsertStage(LUT, cmsAT_END, CLUT);
-    cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels));
+    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)) ||
+        !cmsPipelineInsertStage(LUT, cmsAT_END, CLUT) ||
+        !cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels)))
+        goto Error;
 
     // Create tags
     if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error;
@@ -504,7 +520,8 @@
     LUT = cmsPipelineAlloc(ContextID, 3, 3);
     if (LUT == NULL) goto Error;
 
-    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3));
+    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3)))
+        goto Error;
 
     if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
     cmsPipelineFree(LUT);
@@ -550,7 +567,8 @@
     LUT = cmsPipelineAlloc(ContextID, 3, 3);
     if (LUT == NULL) goto Error;
 
-    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
+    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
+        goto Error;
 
     if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
     cmsPipelineFree(LUT);
@@ -595,7 +613,8 @@
     LUT = cmsPipelineAlloc(ContextID, 3, 3);
     if (LUT == NULL) goto Error;
 
-    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
+    if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
+        goto Error;
 
     if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
     cmsPipelineFree(LUT);
@@ -734,81 +753,83 @@
 // contrast, Saturation and white point displacement
 
 cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
-                                                     int nLUTPoints,
-                                                     cmsFloat64Number Bright,
-                                                     cmsFloat64Number Contrast,
-                                                     cmsFloat64Number Hue,
-                                                     cmsFloat64Number Saturation,
-                                                     int TempSrc,
-                                                     int TempDest)
+    int nLUTPoints,
+    cmsFloat64Number Bright,
+    cmsFloat64Number Contrast,
+    cmsFloat64Number Hue,
+    cmsFloat64Number Saturation,
+    int TempSrc,
+    int TempDest)
 {
-     cmsHPROFILE hICC;
-     cmsPipeline* Pipeline;
-     BCHSWADJUSTS bchsw;
-     cmsCIExyY WhitePnt;
-     cmsStage* CLUT;
-     cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
-     int i;
+    cmsHPROFILE hICC;
+    cmsPipeline* Pipeline;
+    BCHSWADJUSTS bchsw;
+    cmsCIExyY WhitePnt;
+    cmsStage* CLUT;
+    cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
+    int i;
 
-
-     bchsw.Brightness = Bright;
-     bchsw.Contrast   = Contrast;
-     bchsw.Hue        = Hue;
-     bchsw.Saturation = Saturation;
+    bchsw.Brightness = Bright;
+    bchsw.Contrast   = Contrast;
+    bchsw.Hue        = Hue;
+    bchsw.Saturation = Saturation;
 
-     cmsWhitePointFromTemp(&WhitePnt, TempSrc );
-     cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
+    cmsWhitePointFromTemp(&WhitePnt, TempSrc );
+    cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
 
-     cmsWhitePointFromTemp(&WhitePnt, TempDest);
-     cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
+    cmsWhitePointFromTemp(&WhitePnt, TempDest);
+    cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
 
-      hICC = cmsCreateProfilePlaceholder(ContextID);
-       if (!hICC)                          // can't allocate
-            return NULL;
+    hICC = cmsCreateProfilePlaceholder(ContextID);
+    if (!hICC)                          // can't allocate
+        return NULL;
 
 
-       cmsSetDeviceClass(hICC,      cmsSigAbstractClass);
-       cmsSetColorSpace(hICC,       cmsSigLabData);
-       cmsSetPCS(hICC,              cmsSigLabData);
+    cmsSetDeviceClass(hICC,      cmsSigAbstractClass);
+    cmsSetColorSpace(hICC,       cmsSigLabData);
+    cmsSetPCS(hICC,              cmsSigLabData);
 
-       cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
-
+    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 
-       // Creates a Pipeline with 3D grid only
-       Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
-       if (Pipeline == NULL) {
-           cmsCloseProfile(hICC);
-           return NULL;
-           }
+    // Creates a Pipeline with 3D grid only
+    Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
+    if (Pipeline == NULL) {
+        cmsCloseProfile(hICC);
+        return NULL;
+    }
 
-       for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
-       CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
-       if (CLUT == NULL) return NULL;
+    for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
+    CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
+    if (CLUT == NULL) return NULL;
 
 
-       if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
+    if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
+
+        // Shouldn't reach here
+        goto Error;
+    }
 
-                // Shouldn't reach here
-                cmsPipelineFree(Pipeline);
-                cmsCloseProfile(hICC);
-                return NULL;
-       }
+    if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT)) {
+        goto Error;
+    }
 
-       cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT);
-
-       // Create tags
+    // Create tags
+    if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
 
-       if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
+    cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
 
-       cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
+    cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
 
-       cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
+    // Pipeline is already on virtual profile
+    cmsPipelineFree(Pipeline);
 
-       // Pipeline is already on virtual profile
-       cmsPipelineFree(Pipeline);
+    // Ok, done
+    return hICC;
 
-       // Ok, done
-       return hICC;
+Error:
+    cmsPipelineFree(Pipeline);
+    cmsCloseProfile(hICC);
+    return NULL;
 }
 
 
@@ -856,7 +877,8 @@
     PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
     cmsFreeToneCurve(EmptyTab);
 
-    cmsPipelineInsertStage(LUT, cmsAT_END, PostLin);
+    if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin))
+        goto Error;
 
     if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
     if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
@@ -999,6 +1021,7 @@
 
     { FALSE, 0,              cmsSigLut16Type,    4,  { cmsSigMatrixElemType,  cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
     { FALSE, 0,              cmsSigLut16Type,    3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
+    { FALSE, 0,              cmsSigLut16Type,    2,  { cmsSigCurveSetElemType, cmsSigCLutElemType}},
     { TRUE , 0,              cmsSigLutAtoBType,  1,  { cmsSigCurveSetElemType }},
     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType   } },
@@ -1059,6 +1082,7 @@
     cmsContext ContextID = cmsGetTransformContextID(hTransform);
     const cmsAllowedLUT* AllowedLUT;
     cmsTagSignature DestinationTag;
+    cmsProfileClassSignature deviceClass;
 
     _cmsAssert(hTransform != NULL);
 
@@ -1080,13 +1104,15 @@
     // Time to fix the Lab2/Lab4 issue.
     if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
 
-        cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID));
+        if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
+            goto Error;
     }
 
     // On the output side too
     if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
 
-        cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID));
+        if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
+            goto Error;
     }
 
 
@@ -1108,8 +1134,9 @@
     FrmIn  = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
     FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);
 
+    deviceClass = cmsGetDeviceClass(hProfile);
 
-     if (cmsGetDeviceClass(hProfile) == cmsSigOutputClass)
+     if (deviceClass == cmsSigOutputClass)
          DestinationTag = cmsSigBToA0Tag;
      else
          DestinationTag = cmsSigAToB0Tag;
@@ -1136,10 +1163,12 @@
 
         // Put identity curves if needed
         if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
-             cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn));
+             if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)))
+                 goto Error;
 
         if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType)
-             cmsPipelineInsertStage(LUT, cmsAT_END,   _cmsStageAllocIdentityCurves(ContextID, ChansOut));
+             if (!cmsPipelineInsertStage(LUT, cmsAT_END,   _cmsStageAllocIdentityCurves(ContextID, ChansOut)))
+                 goto Error;
 
         AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
     }
@@ -1168,10 +1197,22 @@
            if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
     }
 
-    if (xform ->Sequence != NULL) {
+    if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) {
         if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
     }
 
+    // Set the white point
+    if (deviceClass == cmsSigInputClass) {
+        if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error;
+    }
+    else {
+         if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error;
+    }
+
+
+    // Per 7.2.15 in spec 4.3
+    cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent);
+
     cmsPipelineFree(LUT);
     return hProfile;
 
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Wed Jul 05 19:37:28 2017 +0200
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2010 Marti Maria Saguer
+//  Copyright (c) 1998-2012 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -76,48 +76,48 @@
 // Obtains WhitePoint from Temperature
 cmsBool  CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK)
 {
-       cmsFloat64Number x, y;
-       cmsFloat64Number T, T2, T3;
-       // cmsFloat64Number M1, M2;
+    cmsFloat64Number x, y;
+    cmsFloat64Number T, T2, T3;
+    // cmsFloat64Number M1, M2;
 
-       _cmsAssert(WhitePoint != NULL);
+    _cmsAssert(WhitePoint != NULL);
 
-       T = TempK;
-       T2 = T*T;            // Square
-       T3 = T2*T;           // Cube
+    T = TempK;
+    T2 = T*T;            // Square
+    T3 = T2*T;           // Cube
 
-       // For correlated color temperature (T) between 4000K and 7000K:
+    // For correlated color temperature (T) between 4000K and 7000K:
 
-       if (T >= 4000. && T <= 7000.)
-       {
-              x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063;
-       }
-       else
-              // or for correlated color temperature (T) between 7000K and 25000K:
+    if (T >= 4000. && T <= 7000.)
+    {
+        x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063;
+    }
+    else
+        // or for correlated color temperature (T) between 7000K and 25000K:
 
-       if (T > 7000.0 && T <= 25000.0)
-       {
-              x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
-       }
-       else {
-              cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
-              return FALSE;
-              }
+        if (T > 7000.0 && T <= 25000.0)
+        {
+            x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
+        }
+        else {
+            cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
+            return FALSE;
+        }
 
-       // Obtain y(x)
+        // Obtain y(x)
 
-       y = -3.000*(x*x) + 2.870*x - 0.275;
+        y = -3.000*(x*x) + 2.870*x - 0.275;
 
-       // wave factors (not used, but here for futures extensions)
+        // wave factors (not used, but here for futures extensions)
 
-       // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
-       // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
+        // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
+        // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
 
-       WhitePoint -> x = x;
-       WhitePoint -> y = y;
-       WhitePoint -> Y = 1.0;
+        WhitePoint -> x = x;
+        WhitePoint -> y = y;
+        WhitePoint -> Y = 1.0;
 
-       return TRUE;
+        return TRUE;
 }
 
 
@@ -266,7 +266,7 @@
         {{  0.8951,  0.2664, -0.1614 }},
         {{ -0.7502,  1.7135,  0.0367 }},
         {{  0.0389, -0.0685,  1.0296 }}
-      }};
+    }};
 
     if (ConeMatrix == NULL)
         ConeMatrix = &LamRigg;
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Wed Jul 05 19:37:28 2017 +0200
@@ -396,7 +396,7 @@
 static _cmsTransformCollection* TransformCollection = NULL;
 
 // Register new ways to transform
-cmsBool  _cmsRegisterTransformPlugin(cmsPluginBase* Data)
+cmsBool  _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data)
 {
     cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
     _cmsTransformCollection* fl;
@@ -412,7 +412,7 @@
    if (Plugin ->Factory == NULL) return FALSE;
 
 
-    fl = (_cmsTransformCollection*) _cmsPluginMalloc(sizeof(_cmsTransformCollection));
+    fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection));
     if (fl == NULL) return FALSE;
 
       // Copy the parameters
@@ -651,6 +651,22 @@
 
 // ----------------------------------------------------------------------------------------------------------------
 
+static
+void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
+{
+    if (src == NULL) {
+        wtPt ->X = cmsD50X;
+        wtPt ->Y = cmsD50Y;
+        wtPt ->Z = cmsD50Z;
+    }
+    else {
+        wtPt ->X = src->X;
+        wtPt ->Y = src->Y;
+        wtPt ->Z = src->Z;
+    }
+
+}
+
 // New to lcms 2.0 -- have all parameters available.
 cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
                                                    cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
@@ -664,7 +680,6 @@
                                                    cmsUInt32Number dwFlags)
 {
     _cmsTRANSFORM* xform;
-    cmsBool  FloatTransform;
     cmsColorSpaceSignature EntryColorSpace;
     cmsColorSpaceSignature ExitColorSpace;
     cmsPipeline* Lut;
@@ -681,9 +696,7 @@
         if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
     }
 
-    // On floating point transforms, inhibit optimizations
-    FloatTransform = (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat));
-
+    // On floating point transforms, inhibit cache
     if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
         dwFlags |= cmsFLAGS_NOCACHE;
 
@@ -730,6 +743,10 @@
     xform ->ExitColorSpace  = ExitColorSpace;
     xform ->RenderingIntent = Intents[nProfiles-1];
 
+    // Take white points
+    SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag));
+    SetWhitePoint(&xform->ExitWhitePoint,  (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag));
+
 
     // Create a gamut check LUT if requested
     if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2.h	Wed Jul 05 19:37:28 2017 +0200
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2011 Marti Maria Saguer
+//  Copyright (c) 1998-2013 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -52,7 +52,7 @@
 //
 //---------------------------------------------------------------------------------
 //
-// Version 2.4
+// Version 2.5
 //
 
 #ifndef _lcms2_H
@@ -101,7 +101,7 @@
 #endif
 
 // Version/release
-#define LCMS_VERSION        2040
+#define LCMS_VERSION        2050
 
 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
 #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -367,6 +367,7 @@
     cmsSigPreview1Tag                       = 0x70726531,  // 'pre1'
     cmsSigPreview2Tag                       = 0x70726532,  // 'pre2'
     cmsSigProfileDescriptionTag             = 0x64657363,  // 'desc'
+    cmsSigProfileDescriptionMLTag           = 0x6473636d,  // 'dscm'
     cmsSigProfileSequenceDescTag            = 0x70736571,  // 'pseq'
     cmsSigProfileSequenceIdTag              = 0x70736964,  // 'psid'
     cmsSigPs2CRD0Tag                        = 0x70736430,  // 'psd0'
@@ -1014,6 +1015,7 @@
 // Plug-In registering  ---------------------------------------------------------------------------------------------------
 
 CMSAPI cmsBool           CMSEXPORT cmsPlugin(void* Plugin);
+CMSAPI cmsBool           CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
 CMSAPI void              CMSEXPORT cmsUnregisterPlugins(void);
 
 // Error logging ----------------------------------------------------------------------------------------------------------
@@ -1190,7 +1192,7 @@
 // Where to place/locate the stages in the pipeline chain
 typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc;
 
-CMSAPI void              CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
+CMSAPI int               CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
 CMSAPI void              CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe);
 
 // This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements
@@ -1274,6 +1276,13 @@
                                                          const char LanguageCode[3], const char CountryCode[3],
                                                          char ObtainedLanguage[3], char ObtainedCountry[3]);
 
+CMSAPI cmsUInt32Number   CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu);
+
+CMSAPI cmsBool           CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
+                                                             cmsUInt32Number idx,
+                                                             char LanguageCode[3],
+                                                             char CountryCode[3]);
+
 // Undercolorremoval & black generation -------------------------------------------------------------------------------------
 
 typedef struct {
@@ -1424,6 +1433,7 @@
 CMSAPI void              CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags);
 CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile);
 CMSAPI void              CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer);
+CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile);
 CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile);
 CMSAPI void              CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model);
 CMSAPI void              CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags);
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h	Wed Jul 05 19:37:28 2017 +0200
@@ -27,7 +27,7 @@
 // However, the following notice accompanied the original version of this
 // file:
 //
-//---------------------------------------------------------------------------------
+
 //
 //  Little Color Management System
 //  Copyright (c) 1998-2011 Marti Maria Saguer
@@ -196,7 +196,7 @@
 // Plug-In registering ---------------------------------------------------------------
 
 // Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
-void* _cmsPluginMalloc(cmsUInt32Number size);
+void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size);
 
 // Memory management
 cmsBool   _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
@@ -205,28 +205,28 @@
 cmsBool  _cmsRegisterInterpPlugin(cmsPluginBase* Plugin);
 
 // Parametric curves
-cmsBool  _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Formatters management
-cmsBool  _cmsRegisterFormattersPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Tag type management
-cmsBool  _cmsRegisterTagTypePlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterTagTypePlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Tag management
-cmsBool  _cmsRegisterTagPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterTagPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Intent management
-cmsBool  _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterRenderingIntentPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Multi Process elements
-cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Optimization
-cmsBool  _cmsRegisterOptimizationPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // Transform
-cmsBool  _cmsRegisterTransformPlugin(cmsPluginBase* Plugin);
+cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // ---------------------------------------------------------------------------------------------------------
 
@@ -263,7 +263,7 @@
     cmsUInt16Number Country;
 
     cmsUInt32Number StrW;       // Offset to current unicode string
-    cmsUInt32Number Len;        // Lenght in bytes
+    cmsUInt32Number Len;        // Length in bytes
 
 } _cmsMLUentry;
 
@@ -330,9 +330,11 @@
     cmsColorSpaceSignature   ColorSpace;
     cmsColorSpaceSignature   PCS;
     cmsUInt32Number          RenderingIntent;
+
     cmsUInt32Number          flags;
     cmsUInt32Number          manufacturer, model;
     cmsUInt64Number          attributes;
+    cmsUInt32Number          creator;
 
     cmsProfileID             ProfileID;
 
@@ -585,6 +587,10 @@
     cmsColorSpaceSignature EntryColorSpace;
     cmsColorSpaceSignature ExitColorSpace;
 
+    // White points (informative only)
+    cmsCIEXYZ EntryWhitePoint;
+    cmsCIEXYZ ExitWhitePoint;
+
     // Profiles used to create the transform
     cmsSEQ* Sequence;
 
--- a/jdk/src/share/native/sun/management/Flag.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/management/Flag.c	Wed Jul 05 19:37:28 2017 +0200
@@ -97,12 +97,12 @@
         return 0;
     }
 
-    if (count == 0) {
+    if (count <= 0) {
         JNU_ThrowIllegalArgumentException(env, 0);
         return 0;
     }
 
-    gsize = count * sizeof(jmmVMGlobal);
+    gsize = (size_t)count * sizeof(jmmVMGlobal);
     globals = (jmmVMGlobal*) malloc(gsize);
     if (globals == NULL) {
         JNU_ThrowOutOfMemoryError(env, 0);
--- a/jdk/src/share/native/sun/management/GcInfoBuilder.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/share/native/sun/management/GcInfoBuilder.c	Wed Jul 05 19:37:28 2017 +0200
@@ -59,12 +59,12 @@
         return;
     }
 
-    if (num_attributes == 0) {
+    if (num_attributes <= 0) {
         JNU_ThrowIllegalArgumentException(env, "Invalid num_attributes");
         return;
     }
 
-    ext_att_info = (jmmExtAttributeInfo*) malloc(num_attributes *
+    ext_att_info = (jmmExtAttributeInfo*) malloc((size_t)num_attributes *
                                                  sizeof(jmmExtAttributeInfo));
     if (ext_att_info == NULL) {
         JNU_ThrowOutOfMemoryError(env, 0);
@@ -78,7 +78,7 @@
         return;
     }
 
-    nativeTypes = (jchar*) malloc(num_attributes * sizeof(jchar));
+    nativeTypes = (jchar*) malloc((size_t)num_attributes * sizeof(jchar));
     if (nativeTypes == NULL) {
         free(ext_att_info);
         JNU_ThrowOutOfMemoryError(env, 0);
@@ -188,11 +188,16 @@
         return 0;
     }
 
+    if (ext_att_count <= 0) {
+        JNU_ThrowIllegalArgumentException(env, "Invalid ext_att_count");
+        return 0;
+    }
+
     gc_stat.usage_before_gc = usageBeforeGC;
     gc_stat.usage_after_gc = usageAfterGC;
     gc_stat.gc_ext_attribute_values_size = ext_att_count;
     if (ext_att_count > 0) {
-        gc_stat.gc_ext_attribute_values = (jvalue*) malloc(ext_att_count *
+        gc_stat.gc_ext_attribute_values = (jvalue*) malloc((size_t)ext_att_count *
                                                            sizeof(jvalue));
         if (gc_stat.gc_ext_attribute_values == NULL) {
             JNU_ThrowOutOfMemoryError(env, 0);
@@ -212,7 +217,7 @@
     }
 
     // convert the ext_att_types to native types
-    nativeTypes = (jchar*) malloc(ext_att_count * sizeof(jchar));
+    nativeTypes = (jchar*) malloc((size_t)ext_att_count * sizeof(jchar));
     if (nativeTypes == NULL) {
         if (gc_stat.gc_ext_attribute_values != NULL) {
             free(gc_stat.gc_ext_attribute_values);
--- a/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -25,6 +25,11 @@
 package java.net;
 
 import java.io.IOException;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import jdk.net.*;
+import static sun.net.ExtendedOptionsImpl.*;
 
 /*
  * On Unix systems we simply delegate to native methods.
@@ -38,6 +43,42 @@
         init();
     }
 
+    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
+        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+            super.setOption(name, value);
+        } else {
+            if (isClosed()) {
+                throw new SocketException("Socket closed");
+            }
+            checkSetOptionPermission(name);
+            checkValueType(value, SocketFlow.class);
+            setFlowOption(getFileDescriptor(), (SocketFlow)value);
+        }
+    }
+
+    protected <T> T getOption(SocketOption<T> name) throws IOException {
+        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+            return super.getOption(name);
+        }
+        if (isClosed()) {
+            throw new SocketException("Socket closed");
+        }
+        checkGetOptionPermission(name);
+        SocketFlow flow = SocketFlow.create();
+        getFlowOption(getFileDescriptor(), flow);
+        return (T)flow;
+    }
+
+    protected Set<SocketOption<?>> supportedOptions() {
+        HashSet<SocketOption<?>> options = new HashSet(
+            super.supportedOptions());
+
+        if (flowSupported()) {
+            options.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        return options;
+    }
+
     protected synchronized native void bind0(int lport, InetAddress laddr)
         throws SocketException;
 
--- a/jdk/src/solaris/classes/java/net/PlainSocketImpl.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/java/net/PlainSocketImpl.java	Wed Jul 05 19:37:28 2017 +0200
@@ -26,6 +26,12 @@
 
 import java.io.IOException;
 import java.io.FileDescriptor;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import jdk.net.*;
+
+import static sun.net.ExtendedOptionsImpl.*;
 
 /*
  * On Unix systems we simply delegate to native methods.
@@ -51,6 +57,42 @@
         this.fd = fd;
     }
 
+    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
+        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+            super.setOption(name, value);
+        } else {
+            if (isClosedOrPending()) {
+                throw new SocketException("Socket closed");
+            }
+            checkSetOptionPermission(name);
+            checkValueType(value, SocketFlow.class);
+            setFlowOption(getFileDescriptor(), (SocketFlow)value);
+        }
+    }
+
+    protected <T> T getOption(SocketOption<T> name) throws IOException {
+        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+            return super.getOption(name);
+        }
+        if (isClosedOrPending()) {
+            throw new SocketException("Socket closed");
+        }
+        checkGetOptionPermission(name);
+        SocketFlow flow = SocketFlow.create();
+        getFlowOption(getFileDescriptor(), flow);
+        return (T)flow;
+    }
+
+    protected Set<SocketOption<?>> supportedOptions() {
+        HashSet<SocketOption<?>> options = new HashSet(
+            super.supportedOptions());
+
+        if (getSocket() != null && flowSupported()) {
+            options.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        return options;
+    }
+
     native void socketCreate(boolean isServer) throws IOException;
 
     native void socketConnect(InetAddress address, int port, int timeout)
@@ -77,5 +119,4 @@
     native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
 
     native void socketSendUrgentData(int data) throws IOException;
-
 }
--- a/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XClipboard.java	Wed Jul 05 19:37:28 2017 +0200
@@ -86,7 +86,7 @@
     protected synchronized void setContentsNative(Transferable contents) {
         SortedMap<Long,DataFlavor> formatMap =
             DataTransferer.getInstance().getFormatsForTransferable
-                (contents, DataTransferer.adaptFlavorMap(flavorMap));
+                (contents, DataTransferer.adaptFlavorMap(getDefaultFlavorTable()));
         long[] formats = DataTransferer.keysToLongArray(formatMap);
 
         if (!selection.setOwner(contents, formatMap, formats,
@@ -125,7 +125,7 @@
     private void checkChangeHere(Transferable contents) {
         if (areFlavorListenersRegistered()) {
             checkChange(DataTransferer.getInstance().
-                        getFormatsForTransferableAsArray(contents, flavorMap));
+                        getFormatsForTransferableAsArray(contents, getDefaultFlavorTable()));
         }
     }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Wed Jul 05 19:37:28 2017 +0200
@@ -50,7 +50,8 @@
 import sun.awt.datatransfer.DataTransferer;
 import sun.font.FontConfigManager;
 import sun.java2d.SunGraphicsEnvironment;
-import sun.misc.PerformanceLogger;
+import sun.misc.*;
+import sun.misc.ThreadGroupUtils;
 import sun.print.PrintJob2D;
 import sun.security.action.GetPropertyAction;
 import sun.security.action.GetBooleanAction;
@@ -254,33 +255,25 @@
         } finally {
             awtUnlock();
         }
-        PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
-            public Void run() {
-                ThreadGroup mainTG = Thread.currentThread().getThreadGroup();
-                ThreadGroup parentTG = mainTG.getParent();
-                while (parentTG != null) {
-                    mainTG = parentTG;
-                    parentTG = mainTG.getParent();
-                }
-                Thread shutdownThread = new Thread(mainTG, "XToolkt-Shutdown-Thread") {
-                        public void run() {
-                            XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
-                            if (peer != null) {
-                                peer.dispose();
-                            }
-                            if (xs != null) {
-                                ((XAWTXSettings)xs).dispose();
-                            }
-                            freeXKB();
-                            if (log.isLoggable(PlatformLogger.Level.FINE)) {
-                                dumpPeers();
-                            }
+        PrivilegedAction<Void> a = () -> {
+            Thread shutdownThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), "XToolkt-Shutdown-Thread") {
+                    public void run() {
+                        XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
+                        if (peer != null) {
+                            peer.dispose();
+                        }
+                        if (xs != null) {
+                            ((XAWTXSettings)xs).dispose();
                         }
-                    };
-                shutdownThread.setContextClassLoader(null);
-                Runtime.getRuntime().addShutdownHook(shutdownThread);
-                return null;
-            }
+                        freeXKB();
+                        if (log.isLoggable(PlatformLogger.Level.FINE)) {
+                            dumpPeers();
+                        }
+                    }
+                };
+            shutdownThread.setContextClassLoader(null);
+            Runtime.getRuntime().addShutdownHook(shutdownThread);
+            return null;
         };
         AccessController.doPrivileged(a);
     }
@@ -322,21 +315,13 @@
             init();
             XWM.init();
 
-            PrivilegedAction<Thread> action = new PrivilegedAction() {
-                public Thread run() {
-                    ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
-                    ThreadGroup parentTG = currentTG.getParent();
-                    while (parentTG != null) {
-                        currentTG = parentTG;
-                        parentTG = currentTG.getParent();
-                    }
-                    Thread thread = new Thread(currentTG, XToolkit.this, "AWT-XAWT");
-                    thread.setPriority(Thread.NORM_PRIORITY + 1);
-                    thread.setDaemon(true);
-                    return thread;
-                }
-            };
-            toolkitThread = AccessController.doPrivileged(action);
+            toolkitThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
+                Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), XToolkit.this, "AWT-XAWT");
+                thread.setContextClassLoader(null);
+                thread.setPriority(Thread.NORM_PRIORITY + 1);
+                thread.setDaemon(true);
+                return thread;
+            });
             toolkitThread.start();
         }
     }
--- a/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java	Wed Jul 05 19:37:28 2017 +0200
@@ -42,6 +42,8 @@
 import sun.java2d.xr.XRGraphicsConfig;
 import sun.java2d.loops.SurfaceType;
 
+import sun.misc.ThreadGroupUtils;
+
 /**
  * This is an implementation of a GraphicsDevice object for a single
  * X11 screen.
@@ -423,28 +425,19 @@
             // is already in the original DisplayMode at that time, this
             // hook will have no effect)
             shutdownHookRegistered = true;
-            PrivilegedAction<Void> a = new PrivilegedAction<Void>() {
-                public Void run() {
-                    ThreadGroup mainTG = Thread.currentThread().getThreadGroup();
-                    ThreadGroup parentTG = mainTG.getParent();
-                    while (parentTG != null) {
-                        mainTG = parentTG;
-                        parentTG = mainTG.getParent();
+            PrivilegedAction<Void> a = () -> {
+                ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                Runnable r = () -> {
+                    Window old = getFullScreenWindow();
+                    if (old != null) {
+                        exitFullScreenExclusive(old);
+                        setDisplayMode(origDisplayMode);
                     }
-                    Runnable r = new Runnable() {
-                            public void run() {
-                                Window old = getFullScreenWindow();
-                                if (old != null) {
-                                    exitFullScreenExclusive(old);
-                                    setDisplayMode(origDisplayMode);
-                                }
-                            }
-                        };
-                    Thread t = new Thread(mainTG, r,"Display-Change-Shutdown-Thread-"+screen);
-                    t.setContextClassLoader(null);
-                    Runtime.getRuntime().addShutdownHook(t);
-                    return null;
-                }
+                };
+                Thread t = new Thread(rootTG, r,"Display-Change-Shutdown-Thread-"+screen);
+                t.setContextClassLoader(null);
+                Runtime.getRuntime().addShutdownHook(t);
+                return null;
             };
             AccessController.doPrivileged(a);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/net/www/content-types.properties	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,280 @@
+#sun.net.www MIME content-types table
+#
+# Property fields:
+#
+#   <description> ::= 'description' '=' <descriptive string>
+#    <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
+#         <image> ::= 'icon' '=' <filename of icon image>
+#        <action> ::= 'browser' | 'application' | 'save' | 'unknown'
+#   <application> ::= 'application' '=' <command line template>
+#
+
+#
+# The "we don't know anything about this data" type(s).
+# Used internally to mark unrecognized types.
+#
+content/unknown: description=Unknown Content
+unknown/unknown: description=Unknown Data Type
+
+#
+# The template we should use for temporary files when launching an application
+# to view a document of given type.
+#
+temp.file.template: /tmp/%s
+
+#
+# The "real" types.
+#
+application/octet-stream: \
+	description=Generic Binary Stream;\
+	file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz
+
+application/oda: \
+	description=ODA Document;\
+	file_extensions=.oda
+
+application/pdf: \
+	description=Adobe PDF Format;\
+	file_extensions=.pdf
+
+application/postscript: \
+	description=Postscript File;\
+	file_extensions=.eps,.ai,.ps;\
+	icon=ps;\
+	action=application;\
+	application=imagetool %s
+
+application/x-dvi: \
+	description=TeX DVI File;\
+	file_extensions=.dvi;\
+	action=application;\
+	application=xdvi %s
+
+application/x-hdf: \
+	description=Hierarchical Data Format;\
+	file_extensions=.hdf;\
+	action=save
+
+application/x-latex: \
+	description=LaTeX Source;\
+	file_extensions=.latex
+
+application/x-netcdf: \
+	description=Unidata netCDF Data Format;\
+	file_extensions=.nc,.cdf;\
+	action=save
+
+application/x-tex: \
+	description=TeX Source;\
+	file_extensions=.tex
+
+application/x-texinfo: \
+	description=Gnu Texinfo;\
+	file_extensions=.texinfo,.texi
+
+application/x-troff: \
+	description=Troff Source;\
+	file_extensions=.t,.tr,.roff;\
+	action=application;\
+	application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
+
+application/x-troff-man: \
+	description=Troff Manpage Source;\
+	file_extensions=.man;\
+	action=application;\
+	application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
+
+application/x-troff-me: \
+	description=Troff ME Macros;\
+	file_extensions=.me;\
+	action=application;\
+	application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
+
+application/x-troff-ms: \
+	description=Troff MS Macros;\
+	file_extensions=.ms;\
+	action=application;\
+	application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
+
+application/x-wais-source: \
+	description=Wais Source;\
+	file_extensions=.src,.wsrc
+
+application/zip: \
+	description=Zip File;\
+	file_extensions=.zip;\
+	icon=zip;\
+	action=save
+
+application/x-bcpio: \
+	description=Old Binary CPIO Archive;\
+	file_extensions=.bcpio; action=save
+
+application/x-cpio: \
+	description=Unix CPIO Archive;\
+	file_extensions=.cpio; action=save
+
+application/x-gtar: \
+	description=Gnu Tar Archive;\
+	file_extensions=.gtar;\
+	icon=tar;\
+	action=save
+
+application/x-shar: \
+	description=Shell Archive;\
+	file_extensions=.sh,.shar;\
+	action=save
+
+application/x-sv4cpio: \
+	description=SVR4 CPIO Archive;\
+	file_extensions=.sv4cpio; action=save
+
+application/x-sv4crc: \
+	description=SVR4 CPIO with CRC;\
+	file_extensions=.sv4crc; action=save
+
+application/x-tar: \
+	description=Tar Archive;\
+	file_extensions=.tar;\
+	icon=tar;\
+	action=save
+
+application/x-ustar: \
+	description=US Tar Archive;\
+	file_extensions=.ustar;\
+	action=save
+
+audio/basic: \
+	description=Basic Audio;\
+	file_extensions=.snd,.au;\
+	icon=audio;\
+	action=application;\
+	application=audiotool %s
+
+audio/x-aiff: \
+	description=Audio Interchange Format File;\
+	file_extensions=.aifc,.aif,.aiff;\
+	icon=aiff
+
+audio/x-wav: \
+	description=Wav Audio;\
+	file_extensions=.wav;\
+	icon=wav
+
+image/gif: \
+	description=GIF Image;\
+	file_extensions=.gif;\
+	icon=gif;\
+	action=browser
+
+image/ief: \
+	description=Image Exchange Format;\
+	file_extensions=.ief
+
+image/jpeg: \
+	description=JPEG Image;\
+	file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
+	icon=jpeg;\
+	action=browser;\
+	application=imagetool %s
+
+image/tiff: \
+	description=TIFF Image;\
+	file_extensions=.tif,.tiff;\
+	icon=tiff
+
+image/vnd.fpx: \
+	description=FlashPix Image;\
+	file_extensions=.fpx,.fpix
+
+image/x-cmu-rast: \
+	description=CMU Raster Image;\
+	file_extensions=.ras
+
+image/x-portable-anymap: \
+	description=PBM Anymap Format;\
+	file_extensions=.pnm
+
+image/x-portable-bitmap: \
+	description=PBM Bitmap Format;\
+	file_extensions=.pbm
+
+image/x-portable-graymap: \
+	description=PBM Graymap Format;\
+	file_extensions=.pgm
+
+image/x-portable-pixmap: \
+	description=PBM Pixmap Format;\
+	file_extensions=.ppm
+
+image/x-rgb: \
+	description=RGB Image;\
+	file_extensions=.rgb
+
+image/x-xbitmap: \
+	description=X Bitmap Image;\
+	file_extensions=.xbm,.xpm
+
+image/x-xwindowdump: \
+	description=X Window Dump Image;\
+	file_extensions=.xwd
+
+image/png: \
+	description=PNG Image;\
+	file_extensions=.png;\
+	icon=png;\
+	action=browser
+
+image/bmp: \
+	description=Bitmap Image;\
+	file_extensions=.bmp;
+
+text/html: \
+	description=HTML Document;\
+	file_extensions=.htm,.html;\
+	icon=html
+
+text/plain: \
+	description=Plain Text;\
+	file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
+	icon=text;\
+	action=browser
+
+text/tab-separated-values: \
+	description=Tab Separated Values Text;\
+	file_extensions=.tsv
+
+text/x-setext: \
+	description=Structure Enhanced Text;\
+	file_extensions=.etx
+
+video/mpeg: \
+	description=MPEG Video Clip;\
+	file_extensions=.mpg,.mpe,.mpeg;\
+	icon=mpeg;\
+	action=application;\
+	application=mpeg_play %s
+
+video/quicktime: \
+	description=QuickTime Video Clip;\
+	file_extensions=.mov,.qt
+
+application/x-troff-msvideo: \
+	description=AVI Video;\
+	file_extensions=.avi;\
+	icon=avi
+
+video/x-sgi-movie: \
+	description=SGI Movie;\
+	file_extensions=.movie,.mv
+
+message/rfc822: \
+	description=Internet Email Message;\
+	file_extensions=.mime
+
+application/xml: \
+	description=XML document;\
+	file_extensions=.xml
+
+
+
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java	Wed Jul 05 19:37:28 2017 +0200
@@ -77,7 +77,7 @@
     }
 
     private static native int fgetxattr0(int filedes, long nameAddress,
-        long valueAdddress, int valueLen) throws UnixException;
+        long valueAddress, int valueLen) throws UnixException;
 
     /**
      *  fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags);
@@ -94,7 +94,7 @@
     }
 
     private static native void fsetxattr0(int filedes, long nameAddress,
-        long valueAdddress, int valueLen) throws UnixException;
+        long valueAddress, int valueLen) throws UnixException;
 
     /**
      * fremovexattr(int filedes, const char *name);
--- a/jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/MagicFileTypeDetector.java	Wed Jul 05 19:37:28 2017 +0200
@@ -36,7 +36,7 @@
 
 class MagicFileTypeDetector extends AbstractFileTypeDetector {
 
-    private static final String UNKNOW_MIME_TYPE = "application/octet-stream";
+    private static final String UNKNOWN_MIME_TYPE = "application/octet-stream";
 
     // true if libmagic is available and successfully loaded
     private final boolean libmagicAvailable;
@@ -57,7 +57,7 @@
         try {
             byte[] type = probe0(buffer.address());
             String mimeType = (type == null) ? null : new String(type);
-            return UNKNOW_MIME_TYPE.equals(mimeType) ? null : mimeType;
+            return UNKNOWN_MIME_TYPE.equals(mimeType) ? null : mimeType;
         } finally {
             buffer.release();
         }
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Wed Jul 05 19:37:28 2017 +0200
@@ -290,7 +290,7 @@
         return acl;
     }
 
-    // Retrns true if NFSv4 ACLs not enabled on file system
+    // Returns true if NFSv4 ACLs not enabled on file system
     private static boolean isAclsEnabled(int fd) {
         try {
             long enabled = fpathconf(fd, _PC_ACL_ENABLED);
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java	Wed Jul 05 19:37:28 2017 +0200
@@ -627,14 +627,14 @@
 
         /**
          * Update watch key's events. If ENTRY_MODIFY changes to be enabled
-         * then register each file in the direcory; If ENTRY_MODIFY changed to
+         * then register each file in the directory; If ENTRY_MODIFY changed to
          * be disabled then unregister each file.
          */
         void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events)
             throws UnixException
         {
 
-            // update events, rembering if ENTRY_MODIFY was previously
+            // update events, remembering if ENTRY_MODIFY was previously
             // enabled or disabled.
             boolean oldModifyEnabled = key.events()
                 .contains(StandardWatchEventKinds.ENTRY_MODIFY);
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Wed Jul 05 19:37:28 2017 +0200
@@ -48,7 +48,7 @@
     // filter (may be null)
     private final DirectoryStream.Filter<? super Path> filter;
 
-    // used to coorindate closing of directory stream
+    // used to coordinate closing of directory stream
     private final ReentrantReadWriteLock streamLock =
         new ReentrantReadWriteLock(true);
 
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java	Wed Jul 05 19:37:28 2017 +0200
@@ -133,7 +133,7 @@
         private static final String OWNER_NAME = "owner";
         private static final String GROUP_NAME = "group";
 
-        // the names of the posix attributes (incudes basic)
+        // the names of the posix attributes (includes basic)
         static final Set<String> posixAttributeNames =
             Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME);
 
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java	Wed Jul 05 19:37:28 2017 +0200
@@ -339,7 +339,7 @@
             };
     }
 
-    // Override if the platform has different path match requrement, such as
+    // Override if the platform has different path match requirement, such as
     // case insensitive or Unicode canonical equal on MacOSX
     Pattern compilePathMatchPattern(String expr) {
         return Pattern.compile(expr);
--- a/jdk/src/solaris/demo/jni/Poller/Poller.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/demo/jni/Poller/Poller.c	Wed Jul 05 19:37:28 2017 +0200
@@ -318,7 +318,7 @@
 
   ioevent_t *ioeh;
 
-  if (handle < 0 || handle > MAX_HANDLES)
+  if (handle < 0 || handle >= MAX_HANDLES)
     {
       STATE_EXCEPTION("DestroyPoller - handle out of range");
       return;
@@ -366,7 +366,7 @@
   int retval;
   ioevent_t *ioeh;
 
-  if (handle < 0 || handle > MAX_HANDLES)
+  if (handle < 0 || handle >= MAX_HANDLES)
     return STATE_EXCEPTION("AddFd - handle out of range");
 
   ioeh = &IOE_handles[handle];
@@ -459,7 +459,7 @@
   return fd;
 }
 
-/*
+/*
  * Class:     Poller
  * Method:    nativeRemoveFd
  * Signature: (II)I
@@ -469,7 +469,7 @@
 {
   ioevent_t *ioeh;
 
-  if (handle < 0 || handle > MAX_HANDLES)
+  if (handle < 0 || handle >= MAX_HANDLES)
     return STATE_EXCEPTION("RemoveFd - handle out of range");
 
   ioeh = &IOE_handles[handle];
@@ -576,7 +576,7 @@
   int i;
   ioevent_t *ioeh;
 
-  if (handle < 0 || handle > MAX_HANDLES)
+  if (handle < 0 || handle >= MAX_HANDLES)
     return STATE_EXCEPTION("IsMember - handle out of range");
 
   ioeh = &IOE_handles[handle];
@@ -629,7 +629,7 @@
   ioevent_t *ioeh;
   jboolean isCopy1,isCopy2;
 
-  if (handle < 0 || handle > MAX_HANDLES)
+  if (handle < 0 || handle >= MAX_HANDLES)
     return STATE_EXCEPTION("nativeWait - handle out of range");
 
   ioeh = &IOE_handles[handle];
--- a/jdk/src/solaris/lib/content-types.properties	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-#sun.net.www MIME content-types table
-#
-# Property fields:
-#
-#   <description> ::= 'description' '=' <descriptive string>
-#    <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
-#         <image> ::= 'icon' '=' <filename of icon image>
-#        <action> ::= 'browser' | 'application' | 'save' | 'unknown'
-#   <application> ::= 'application' '=' <command line template>
-#
-
-#
-# The "we don't know anything about this data" type(s).
-# Used internally to mark unrecognized types.
-#
-content/unknown: description=Unknown Content
-unknown/unknown: description=Unknown Data Type
-
-#
-# The template we should use for temporary files when launching an application
-# to view a document of given type.
-#
-temp.file.template: /tmp/%s
-
-#
-# The "real" types.
-#
-application/octet-stream: \
-	description=Generic Binary Stream;\
-	file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z,.gz
-
-application/oda: \
-	description=ODA Document;\
-	file_extensions=.oda
-
-application/pdf: \
-	description=Adobe PDF Format;\
-	file_extensions=.pdf
-
-application/postscript: \
-	description=Postscript File;\
-	file_extensions=.eps,.ai,.ps;\
-	icon=ps;\
-	action=application;\
-	application=imagetool %s
-
-application/x-dvi: \
-	description=TeX DVI File;\
-	file_extensions=.dvi;\
-	action=application;\
-	application=xdvi %s
-
-application/x-hdf: \
-	description=Hierarchical Data Format;\
-	file_extensions=.hdf;\
-	action=save
-
-application/x-latex: \
-	description=LaTeX Source;\
-	file_extensions=.latex
-
-application/x-netcdf: \
-	description=Unidata netCDF Data Format;\
-	file_extensions=.nc,.cdf;\
-	action=save
-
-application/x-tex: \
-	description=TeX Source;\
-	file_extensions=.tex
-
-application/x-texinfo: \
-	description=Gnu Texinfo;\
-	file_extensions=.texinfo,.texi
-
-application/x-troff: \
-	description=Troff Source;\
-	file_extensions=.t,.tr,.roff;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
-
-application/x-troff-man: \
-	description=Troff Manpage Source;\
-	file_extensions=.man;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
-
-application/x-troff-me: \
-	description=Troff ME Macros;\
-	file_extensions=.me;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
-
-application/x-troff-ms: \
-	description=Troff MS Macros;\
-	file_extensions=.ms;\
-	action=application;\
-	application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
-
-application/x-wais-source: \
-	description=Wais Source;\
-	file_extensions=.src,.wsrc
-
-application/zip: \
-	description=Zip File;\
-	file_extensions=.zip;\
-	icon=zip;\
-	action=save
-
-application/x-bcpio: \
-	description=Old Binary CPIO Archive;\
-	file_extensions=.bcpio; action=save
-
-application/x-cpio: \
-	description=Unix CPIO Archive;\
-	file_extensions=.cpio; action=save
-
-application/x-gtar: \
-	description=Gnu Tar Archive;\
-	file_extensions=.gtar;\
-	icon=tar;\
-	action=save
-
-application/x-shar: \
-	description=Shell Archive;\
-	file_extensions=.sh,.shar;\
-	action=save
-
-application/x-sv4cpio: \
-	description=SVR4 CPIO Archive;\
-	file_extensions=.sv4cpio; action=save
-
-application/x-sv4crc: \
-	description=SVR4 CPIO with CRC;\
-	file_extensions=.sv4crc; action=save
-
-application/x-tar: \
-	description=Tar Archive;\
-	file_extensions=.tar;\
-	icon=tar;\
-	action=save
-
-application/x-ustar: \
-	description=US Tar Archive;\
-	file_extensions=.ustar;\
-	action=save
-
-audio/basic: \
-	description=Basic Audio;\
-	file_extensions=.snd,.au;\
-	icon=audio;\
-	action=application;\
-	application=audiotool %s
-
-audio/x-aiff: \
-	description=Audio Interchange Format File;\
-	file_extensions=.aifc,.aif,.aiff;\
-	icon=aiff
-
-audio/x-wav: \
-	description=Wav Audio;\
-	file_extensions=.wav;\
-	icon=wav
-
-image/gif: \
-	description=GIF Image;\
-	file_extensions=.gif;\
-	icon=gif;\
-	action=browser
-
-image/ief: \
-	description=Image Exchange Format;\
-	file_extensions=.ief
-
-image/jpeg: \
-	description=JPEG Image;\
-	file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
-	icon=jpeg;\
-	action=browser;\
-	application=imagetool %s
-
-image/tiff: \
-	description=TIFF Image;\
-	file_extensions=.tif,.tiff;\
-	icon=tiff
-
-image/vnd.fpx: \
-	description=FlashPix Image;\
-	file_extensions=.fpx,.fpix
-
-image/x-cmu-rast: \
-	description=CMU Raster Image;\
-	file_extensions=.ras
-
-image/x-portable-anymap: \
-	description=PBM Anymap Format;\
-	file_extensions=.pnm
-
-image/x-portable-bitmap: \
-	description=PBM Bitmap Format;\
-	file_extensions=.pbm
-
-image/x-portable-graymap: \
-	description=PBM Graymap Format;\
-	file_extensions=.pgm
-
-image/x-portable-pixmap: \
-	description=PBM Pixmap Format;\
-	file_extensions=.ppm
-
-image/x-rgb: \
-	description=RGB Image;\
-	file_extensions=.rgb
-
-image/x-xbitmap: \
-	description=X Bitmap Image;\
-	file_extensions=.xbm,.xpm
-
-image/x-xwindowdump: \
-	description=X Window Dump Image;\
-	file_extensions=.xwd
-
-image/png: \
-	description=PNG Image;\
-	file_extensions=.png;\
-	icon=png;\
-	action=browser
-
-image/bmp: \
-	description=Bitmap Image;\
-	file_extensions=.bmp;
-
-text/html: \
-	description=HTML Document;\
-	file_extensions=.htm,.html;\
-	icon=html
-
-text/plain: \
-	description=Plain Text;\
-	file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
-	icon=text;\
-	action=browser
-
-text/tab-separated-values: \
-	description=Tab Separated Values Text;\
-	file_extensions=.tsv
-
-text/x-setext: \
-	description=Structure Enhanced Text;\
-	file_extensions=.etx
-
-video/mpeg: \
-	description=MPEG Video Clip;\
-	file_extensions=.mpg,.mpe,.mpeg;\
-	icon=mpeg;\
-	action=application;\
-	application=mpeg_play %s
-
-video/quicktime: \
-	description=QuickTime Video Clip;\
-	file_extensions=.mov,.qt
-
-application/x-troff-msvideo: \
-	description=AVI Video;\
-	file_extensions=.avi;\
-	icon=avi
-
-video/x-sgi-movie: \
-	description=SGI Movie;\
-	file_extensions=.movie,.mv
-
-message/rfc822: \
-	description=Internet Email Message;\
-	file_extensions=.mime
-
-application/xml: \
-	description=XML document;\
-	file_extensions=.xml
-
-
-
--- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_SolarisOS_Utils.c	Wed Jul 05 19:37:28 2017 +0200
@@ -76,7 +76,7 @@
             adPath[*count].st_ino = statBuf.st_ino;
             adPath[*count].st_dev = statBuf.st_dev;
             strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
-            adPath[*count].path[MAX_NAME_LENGTH] = 0;
+            adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
             (*count)++;
             TRACE1("Added audio device %s\n", path);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/java/net/ExtendedOptionsImpl.c	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,337 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <string.h>
+
+#include "net_util.h"
+#include "jdk_net_SocketFlow.h"
+
+static jclass sf_status_class;          /* Status enum type */
+
+static jfieldID sf_status;
+static jfieldID sf_priority;
+static jfieldID sf_bandwidth;
+
+static jfieldID sf_fd_fdID;             /* FileDescriptor.fd */
+
+/* References to the literal enum values */
+
+static jobject sfs_NOSTATUS;
+static jobject sfs_OK;
+static jobject sfs_NOPERMISSION;
+static jobject sfs_NOTCONNECTED;
+static jobject sfs_NOTSUPPORTED;
+static jobject sfs_ALREADYCREATED;
+static jobject sfs_INPROGRESS;
+static jobject sfs_OTHER;
+
+static jobject getEnumField(JNIEnv *env, char *name);
+static void setStatus(JNIEnv *env, jobject obj, int errval);
+
+/* OS specific code is implemented in these three functions */
+
+static jboolean flowSupported0() ;
+
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
+  (JNIEnv *env, jclass UNUSED)
+{
+    static int initialized = 0;
+    jclass c;
+
+    /* Global class references */
+
+    if (initialized) {
+        return;
+    }
+
+    c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status");
+    CHECK_NULL(c);
+    sf_status_class = (*env)->NewGlobalRef(env, c);
+    CHECK_NULL(sf_status_class);
+
+    /* int "fd" field of java.io.FileDescriptor  */
+
+    c = (*env)->FindClass(env, "java/io/FileDescriptor");
+    CHECK_NULL(c);
+    sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I");
+    CHECK_NULL(sf_fd_fdID);
+
+
+    /* SocketFlow fields */
+
+    c = (*env)->FindClass(env, "jdk/net/SocketFlow");
+
+    /* status */
+
+    sf_status = (*env)->GetFieldID(env, c, "status",
+                                        "Ljdk/net/SocketFlow$Status;");
+    CHECK_NULL(sf_status);
+
+    /* priority */
+
+    sf_priority = (*env)->GetFieldID(env, c, "priority", "I");
+    CHECK_NULL(sf_priority);
+
+    /* bandwidth */
+
+    sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J");
+    CHECK_NULL(sf_bandwidth);
+
+    /* Initialize the static enum values */
+
+    sfs_NOSTATUS = getEnumField(env, "NO_STATUS");
+    CHECK_NULL(sfs_NOSTATUS);
+    sfs_OK = getEnumField(env, "OK");
+    CHECK_NULL(sfs_OK);
+    sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION");
+    CHECK_NULL(sfs_NOPERMISSION);
+    sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED");
+    CHECK_NULL(sfs_NOTCONNECTED);
+    sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED");
+    CHECK_NULL(sfs_NOTSUPPORTED);
+    sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED");
+    CHECK_NULL(sfs_ALREADYCREATED);
+    sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS");
+    CHECK_NULL(sfs_INPROGRESS);
+    sfs_OTHER = getEnumField(env, "OTHER");
+    CHECK_NULL(sfs_OTHER);
+    initialized = JNI_TRUE;
+}
+
+static jobject getEnumField(JNIEnv *env, char *name)
+{
+    jobject f;
+    jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name,
+        "Ljdk/net/SocketFlow$Status;");
+    CHECK_NULL_RETURN(fID, NULL);
+
+    f = (*env)->GetStaticObjectField(env, sf_status_class, fID);
+    CHECK_NULL_RETURN(f, NULL);
+    f  = (*env)->NewGlobalRef(env, f);
+    CHECK_NULL_RETURN(f, NULL);
+    return f;
+}
+
+/*
+ * Retrieve the int file-descriptor from a public socket type object.
+ * Gets impl, then the FileDescriptor from the impl, and then the fd
+ * from that.
+ */
+static int getFD(JNIEnv *env, jobject fileDesc) {
+    return (*env)->GetIntField(env, fileDesc, sf_fd_fdID);
+}
+
+/**
+ * Sets the status field of a SocketFlow to one of the
+ * canned enum values
+ */
+static void setStatus (JNIEnv *env, jobject obj, int errval)
+{
+    switch (errval) {
+      case 0: /* OK */
+        (*env)->SetObjectField(env, obj, sf_status, sfs_OK);
+        break;
+      case EPERM:
+        (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION);
+        break;
+      case ENOTCONN:
+        (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED);
+        break;
+      case EOPNOTSUPP:
+        (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED);
+        break;
+      case EALREADY:
+        (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED);
+        break;
+      case EINPROGRESS:
+        (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS);
+        break;
+      default:
+        (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER);
+        break;
+    }
+}
+
+#ifdef __solaris__
+
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    setFlowOption
+ * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
+ */
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+{
+    int fd = getFD(env, fileDesc);
+
+    if (fd < 0) {
+        NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
+        return;
+    } else {
+        sock_flow_props_t props;
+        jlong bandwidth;
+        int rv;
+
+        jint priority = (*env)->GetIntField(env, flow, sf_priority);
+        memset(&props, 0, sizeof(props));
+        props.sfp_version = SOCK_FLOW_PROP_VERSION1;
+
+        if (priority != jdk_net_SocketFlow_UNSET) {
+            props.sfp_mask |= SFP_PRIORITY;
+            props.sfp_priority = priority;
+        }
+        bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth);
+        if (bandwidth > -1)  {
+            props.sfp_mask |= SFP_MAXBW;
+            props.sfp_maxbw = (uint64_t) bandwidth;
+        }
+        rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
+        if (rv < 0) {
+            if (errno == ENOPROTOOPT) {
+                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                        "unsupported socket option");
+            } else {
+                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
+                                "set option SO_FLOW_SLA failed");
+            }
+            return;
+        }
+        setStatus(env, flow, props.sfp_status);
+    }
+}
+
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    getFlowOption
+ * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
+ */
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+{
+    int fd = getFD(env, fileDesc);
+
+    if (fd < 0) {
+        NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
+        return;
+    } else {
+        sock_flow_props_t props;
+        int status;
+        socklen_t sz = sizeof(props);
+
+        int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz);
+        if (rv < 0) {
+            if (errno == ENOPROTOOPT) {
+                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                        "unsupported socket option");
+            } else {
+                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
+                                "set option SO_FLOW_SLA failed");
+            }
+            return;
+        }
+        /* first check status to see if flow exists */
+        status = props.sfp_status;
+        setStatus(env, flow, status);
+        if (status == 0) { /* OK */
+            /* can set the other fields now */
+            if (props.sfp_mask & SFP_PRIORITY) {
+                (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority);
+            }
+            if (props.sfp_mask & SFP_MAXBW) {
+                (*env)->SetLongField(env, flow, sf_bandwidth,
+                                        (jlong)props.sfp_maxbw);
+            }
+        }
+    }
+}
+
+static jboolean flowsupported;
+static jboolean flowsupported_set = JNI_FALSE;
+
+static jboolean flowSupported0()
+{
+    /* Do a simple dummy call, and try to figure out from that */
+    sock_flow_props_t props;
+    int rv, s;
+    if (flowsupported_set) {
+        return flowsupported;
+    }
+    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (s < 0) {
+        flowsupported = JNI_FALSE;
+        flowsupported_set = JNI_TRUE;
+        return JNI_FALSE;
+    }
+    memset(&props, 0, sizeof(props));
+    props.sfp_version = SOCK_FLOW_PROP_VERSION1;
+    props.sfp_mask |= SFP_PRIORITY;
+    props.sfp_priority = SFP_PRIO_NORMAL;
+    rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
+    if (rv != 0 && errno == ENOPROTOOPT) {
+        rv = JNI_FALSE;
+    } else {
+        rv = JNI_TRUE;
+    }
+    close(s);
+    flowsupported = rv;
+    flowsupported_set = JNI_TRUE;
+    return flowsupported;
+}
+
+#else /* __solaris__ */
+
+/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */
+
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+}
+
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+}
+
+static jboolean flowSupported0()  {
+    return JNI_FALSE;
+}
+
+#endif /* __solaris__ */
+
+JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
+  (JNIEnv *env, jclass UNUSED)
+{
+    return flowSupported0();
+}
--- a/jdk/src/solaris/native/java/net/net_util_md.h	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.h	Wed Jul 05 19:37:28 2017 +0200
@@ -107,6 +107,47 @@
 
 #ifdef __solaris__
 int net_getParam(char *driver, char *param);
+
+#ifndef SO_FLOW_SLA
+#define SO_FLOW_SLA 0x1018
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack(4)
 #endif
 
+/*
+ * Used with the setsockopt(SO_FLOW_SLA, ...) call to set
+ * per socket service level properties.
+ * When the application uses per-socket API, we will enforce the properties
+ * on both outbound and inbound packets.
+ *
+ * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1.
+ */
+typedef struct sock_flow_props_s {
+        int             sfp_version;
+        uint32_t        sfp_mask;
+        int             sfp_priority;   /* flow priority */
+        uint64_t        sfp_maxbw;      /* bandwidth limit in bps */
+        int             sfp_status;     /* flow create status for getsockopt */
+} sock_flow_props_t;
+
+#define SOCK_FLOW_PROP_VERSION1 1
+
+/* bit mask values for sfp_mask */
+#define SFP_MAXBW       0x00000001      /* Flow Bandwidth Limit */
+#define SFP_PRIORITY    0x00000008      /* Flow priority */
+
+/* possible values for sfp_priority */
+#define SFP_PRIO_NORMAL 1
+#define SFP_PRIO_HIGH   2
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack()
+#endif /* _LONG_LONG_ALIGNMENT */
+
+#endif /* SO_FLOW_SLA */
+#endif /* __solaris__ */
+
+JNIEXPORT jboolean JNICALL NET_IsFlowSupported();
+
 #endif /* NET_UTILS_MD_H */
--- a/jdk/src/solaris/native/java/util/TimeZone_md.c	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/solaris/native/java/util/TimeZone_md.c	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -56,6 +56,9 @@
 static const char *ZONEINFO_DIR = "/usr/share/zoneinfo";
 static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime";
 #else
+#ifdef _AIX
+static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
+#endif
 static const char *SYS_INIT_FILE = "/etc/default/init";
 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
@@ -619,8 +622,29 @@
 static char *
 getPlatformTimeZoneID()
 {
-    return NULL;
+    FILE *fp;
+    char *tz = NULL;
+    char *tz_key = "TZ=";
+    char line[256];
+    size_t tz_key_len = strlen(tz_key);
+
+    if ((fp = fopen(ETC_ENVIRONMENT_FILE, "r")) != NULL) {
+        while (fgets(line, sizeof(line), fp) != NULL) {
+            char *p = strchr(line, '\n');
+            if (p != NULL) {
+                *p = '\0';
+            }
+            if (0 == strncmp(line, tz_key, tz_key_len)) {
+                tz = strdup(line + tz_key_len);
+                break;
+            }
+        }
+        (void) fclose(fp);
+    }
+
+    return tz;
 }
+static char *mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz);
 #endif
 
 /*
@@ -678,9 +702,19 @@
         if (freetz != NULL) {
             free((void *) freetz);
         }
+
+#ifdef _AIX
+        freetz = mapPlatformToJavaTimezone(java_home_dir, javatz);
+        if (javatz != NULL) {
+            free((void *) javatz);
+        }
+        javatz = freetz;
+#endif
     }
+
     return javatz;
 }
+
 /**
  * Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00")
  */
@@ -747,3 +781,101 @@
     return strdup(buf);
 }
 #endif /* MACOSX */
+
+#ifdef _AIX
+static char *
+mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) {
+    FILE *tzmapf;
+    char mapfilename[PATH_MAX+1];
+    char line[256];
+    int linecount = 0;
+    char temp[100], *temp_tz;
+    char *javatz = NULL;
+    char *str_tmp = NULL;
+    size_t temp_tz_len = 0;
+
+    /* On AIX, the TZ environment variable may end with a comma
+     * followed by modifier fields. These are ignored here.
+     */
+    strncpy(temp, tz, 100);
+    temp_tz = strtok_r(temp, ",", &str_tmp);
+
+    if(temp_tz == NULL)
+        goto tzerr;
+
+    temp_tz_len = strlen(temp_tz);
+
+    if (strlen(java_home_dir) >= (PATH_MAX - 15)) {
+        jio_fprintf(stderr, "java.home longer than maximum path length \n");
+        goto tzerr;
+    }
+
+    strncpy(mapfilename, java_home_dir, PATH_MAX);
+    strcat(mapfilename, "/lib/tzmappings");
+
+    if ((tzmapf = fopen(mapfilename, "r")) == NULL) {
+        jio_fprintf(stderr, "can't open %s\n", mapfilename);
+        goto tzerr;
+    }
+
+    while (fgets(line, sizeof(line), tzmapf) != NULL) {
+        char *p = line;
+        char *sol = line;
+        char *java;
+        int result;
+
+        linecount++;
+        /*
+         * Skip comments and blank lines
+         */
+        if (*p == '#' || *p == '\n') {
+            continue;
+        }
+
+        /*
+         * Get the first field, platform zone ID
+         */
+        while (*p != '\0' && *p != '\t') {
+            p++;
+        }
+        if (*p == '\0') {
+            /* mapping table is broken! */
+            jio_fprintf(stderr, "tzmappings: Illegal format at near line %d.\n", linecount);
+            break;
+        }
+
+        *p++ = '\0';
+        if ((result = strncmp(temp_tz, sol, temp_tz_len)) == 0) {
+            /*
+             * If this is the current platform zone ID,
+             * take the Java time zone ID (2nd field).
+             */
+            java = p;
+            while (*p != '\0' && *p != '\n') {
+                p++;
+            }
+
+            if (*p == '\0') {
+                /* mapping table is broken! */
+                jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", linecount);
+                break;
+            }
+
+            *p = '\0';
+            javatz = strdup(java);
+            break;
+        } else if (result < 0) {
+            break;
+        }
+    }
+    (void) fclose(tzmapf);
+
+tzerr:
+    if (javatz == NULL) {
+        return getGMTOffsetID();
+    }
+
+    return javatz;
+}
+#endif
+
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java	Wed Jul 05 19:37:28 2017 +0200
@@ -39,6 +39,7 @@
 
 import static sun.awt.shell.Win32ShellFolder2.*;
 import sun.awt.OSInfo;
+import sun.misc.ThreadGroupUtils;
 
 // NOTE: This class supersedes Win32ShellFolderManager, which was removed
 //       from distribution after version 1.4.2.
@@ -503,23 +504,16 @@
                     }
                 }
             };
-            comThread =
-                AccessController.doPrivileged(
-                    new PrivilegedAction<Thread>() {
-                        public Thread run() {
+            comThread =  AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
                             /* The thread must be a member of a thread group
                              * which will not get GCed before VM exit.
                              * Make its parent the top-level thread group.
                              */
-                            ThreadGroup tg = Thread.currentThread().getThreadGroup();
-                            for (ThreadGroup tgn = tg;
-                                 tgn != null;
-                                 tg = tgn, tgn = tg.getParent());
-                            Thread thread = new Thread(tg, comRun, "Swing-Shell");
+                            ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                            Thread thread = new Thread(rootTG, comRun, "Swing-Shell");
                             thread.setDaemon(true);
                             return thread;
                         }
-                    }
                 );
             return comThread;
         }
--- a/jdk/src/windows/classes/sun/awt/windows/WClipboard.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WClipboard.java	Wed Jul 05 19:37:28 2017 +0200
@@ -62,7 +62,6 @@
 
     @Override
     protected void setContentsNative(Transferable contents) {
-
         // Don't use delayed Clipboard rendering for the Transferable's data.
         // If we did that, we would call Transferable.getTransferData on
         // the Toolkit thread, which is a security hole.
@@ -71,7 +70,7 @@
         // translated. Then, for each format, translate the data and post
         // it to the Clipboard.
         Map <Long, DataFlavor> formatMap = WDataTransferer.getInstance().
-            getFormatsForTransferable(contents, flavorMap);
+            getFormatsForTransferable(contents, getDefaultFlavorTable());
 
         openClipboard(this);
 
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java	Wed Jul 05 19:37:28 2017 +0200
@@ -40,6 +40,7 @@
 import sun.awt.AWTPermissions;
 import sun.awt.LightweightFrame;
 import sun.awt.SunToolkit;
+import sun.misc.ThreadGroupUtils;
 import sun.awt.Win32GraphicsDevice;
 import sun.awt.Win32GraphicsEnvironment;
 import sun.awt.datatransfer.DataTransferer;
@@ -224,7 +225,7 @@
 
     private static native void postDispose();
 
-    private static native boolean startToolkitThread(Runnable thread);
+    private static native boolean startToolkitThread(Runnable thread, ThreadGroup rootThreadGroup);
 
     public WToolkit() {
         // Startup toolkit threads
@@ -241,8 +242,11 @@
          */
         AWTAutoShutdown.notifyToolkitThreadBusy();
 
-        if (!startToolkitThread(this)) {
-            Thread toolkitThread = new Thread(this, "AWT-Windows");
+        // Find a root TG and attach Appkit thread to it
+        ThreadGroup rootTG = AccessController.doPrivileged(
+                (PrivilegedAction<ThreadGroup>) ThreadGroupUtils::getRootThreadGroup);
+        if (!startToolkitThread(this, rootTG)) {
+            Thread toolkitThread = new Thread(rootTG, this, "AWT-Windows");
             toolkitThread.setDaemon(true);
             toolkitThread.start();
         }
@@ -268,32 +272,21 @@
     }
 
     private final void registerShutdownHook() {
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            @Override
-            public Void run() {
-                ThreadGroup currentTG =
-                    Thread.currentThread().getThreadGroup();
-                ThreadGroup parentTG = currentTG.getParent();
-                while (parentTG != null) {
-                    currentTG = parentTG;
-                    parentTG = currentTG.getParent();
-                }
-                Thread shutdown = new Thread(currentTG, new Runnable() {
-                    @Override
-                    public void run() {
-                        shutdown();
-                    }
-                });
-                shutdown.setContextClassLoader(null);
-                Runtime.getRuntime().addShutdownHook(shutdown);
-                return null;
-            }
-        });
+        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            Thread shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), this::shutdown);
+            shutdown.setContextClassLoader(null);
+            Runtime.getRuntime().addShutdownHook(shutdown);
+            return null;
+         });
      }
 
     @Override
     public void run() {
-        Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
+        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            Thread.currentThread().setContextClassLoader(null);
+            return null;
+        });
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
         boolean startPump = init();
 
         if (startPump) {
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -36,8 +36,9 @@
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashMap;
-import sun.awt.SunToolkit;
+
 import sun.awt.AWTAccessor;
+import sun.misc.ThreadGroupUtils;
 import sun.awt.Win32GraphicsConfig;
 import sun.awt.windows.WComponentPeer;
 import sun.java2d.InvalidPipeException;
@@ -92,21 +93,12 @@
     public D3DScreenUpdateManager() {
         done = false;
         AccessController.doPrivileged(
-            new PrivilegedAction() {
-                public Object run() {
-                    ThreadGroup currentTG =
-                        Thread.currentThread().getThreadGroup();
-                    ThreadGroup parentTG = currentTG.getParent();
-                    while (parentTG != null) {
-                        currentTG = parentTG;
-                        parentTG = currentTG.getParent();
-                    }
-                    Thread shutdown = new Thread(currentTG, new Runnable() {
-                            public void run() {
-                                done = true;
-                                wakeUpUpdateThread();
-                            }
-                        });
+                (PrivilegedAction<Void>) () -> {
+                    ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                    Thread shutdown = new Thread(rootTG, () -> {
+                        done = true;
+                        wakeUpUpdateThread();
+                    });
                     shutdown.setContextClassLoader(null);
                     try {
                         Runtime.getRuntime().addShutdownHook(shutdown);
@@ -115,7 +107,6 @@
                     }
                     return null;
                 }
-            }
         );
     }
 
@@ -354,21 +345,17 @@
      */
     private synchronized void startUpdateThread() {
         if (screenUpdater == null) {
-            screenUpdater = (Thread)java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction() {
-                    public Object run() {
-                        ThreadGroup tg =
-                            Thread.currentThread().getThreadGroup();
-                        for (ThreadGroup tgn = tg;
-                             tgn != null; tg = tgn, tgn = tg.getParent());
-                        Thread t = new Thread(tg, D3DScreenUpdateManager.this,
-                                              "D3D Screen Updater");
+            screenUpdater = AccessController.doPrivileged(
+                    (PrivilegedAction<Thread>) () -> {
+                        ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+                        Thread t = new Thread(rootTG,
+                                D3DScreenUpdateManager.this,
+                                "D3D Screen Updater");
                         // REMIND: should it be higher?
                         t.setPriority(Thread.NORM_PRIORITY + 2);
                         t.setDaemon(true);
                         return t;
-                    }
-            });
+                    });
             screenUpdater.start();
         } else {
             wakeUpUpdateThread();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/classes/sun/net/www/content-types.properties	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,276 @@
+#sun.net.www MIME content-types table
+#
+# Property fields:
+#
+#   <description> ::= 'description' '=' <descriptive string>
+#    <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
+#         <image> ::= 'icon' '=' <filename of icon image>
+#        <action> ::= 'browser' | 'application' | 'save' | 'unknown'
+#   <application> ::= 'application' '=' <command line template>
+#
+
+#
+# The "we don't know anything about this data" type(s).
+# Used internally to mark unrecognized types.
+#
+content/unknown: description=Unknown Content
+unknown/unknown: description=Unknown Data Type
+
+#
+# The template we should use for temporary files when launching an application
+# to view a document of given type.
+#
+temp.file.template: c:\\temp\\%s
+
+#
+# The "real" types.
+#
+application/octet-stream: \
+	description=Generic Binary Stream;\
+	file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe,.zip,.gz
+
+application/oda: \
+	description=ODA Document;\
+	file_extensions=.oda
+
+application/pdf: \
+	description=Adobe PDF Format;\
+	file_extensions=.pdf
+
+application/postscript: \
+	description=Postscript File;\
+	file_extensions=.eps,.ai,.ps;\
+	icon=ps
+
+application/rtf: \
+	description=Wordpad Document;\
+	file_extensions=.rtf;\
+	action=application;\
+	application=wordpad.exe %s
+
+application/x-dvi: \
+	description=TeX DVI File;\
+	file_extensions=.dvi
+
+application/x-hdf: \
+	description=Hierarchical Data Format;\
+	file_extensions=.hdf;\
+	action=save
+
+application/x-latex: \
+	description=LaTeX Source;\
+	file_extensions=.latex
+
+application/x-netcdf: \
+	description=Unidata netCDF Data Format;\
+	file_extensions=.nc,.cdf;\
+	action=save
+
+application/x-tex: \
+	description=TeX Source;\
+	file_extensions=.tex
+
+application/x-texinfo: \
+	description=Gnu Texinfo;\
+	file_extensions=.texinfo,.texi
+
+application/x-troff: \
+	description=Troff Source;\
+	file_extensions=.t,.tr,.roff
+
+application/x-troff-man: \
+	description=Troff Manpage Source;\
+	file_extensions=.man
+
+application/x-troff-me: \
+	description=Troff ME Macros;\
+	file_extensions=.me
+
+application/x-troff-ms: \
+	description=Troff MS Macros;\
+	file_extensions=.ms
+
+application/x-wais-source: \
+	description=Wais Source;\
+	file_extensions=.src,.wsrc
+
+application/zip: \
+	description=Zip File;\
+	file_extensions=.zip;\
+	icon=zip;\
+	action=save
+
+application/x-bcpio: \
+	description=Old Binary CPIO Archive;\
+	file_extensions=.bcpio;\
+	action=save
+
+application/x-cpio: \
+	description=Unix CPIO Archive;\
+	file_extensions=.cpio;\
+	action=save
+
+application/x-gtar: \
+	description=Gnu Tar Archive;\
+	file_extensions=.gtar;\
+	icon=tar;\
+	action=save
+
+application/x-shar: \
+	description=Shell Archive;\
+	file_extensions=.sh,.shar;\
+	action=save
+
+application/x-sv4cpio: \
+	description=SVR4 CPIO Archive;\
+	file_extensions=.sv4cpio;\
+	action=save
+
+application/x-sv4crc: \
+	description=SVR4 CPIO with CRC;\
+	file_extensions=.sv4crc;\
+	action=save
+
+application/x-tar: \
+	description=Tar Archive;\
+	file_extensions=.tar;\
+	icon=tar;\
+	action=save
+
+application/x-ustar: \
+	description=US Tar Archive;\
+	file_extensions=.ustar;\
+	action=save
+
+audio/basic: \
+	description=Basic Audio;\
+	file_extensions=.snd,.au;\
+	icon=audio
+
+audio/x-aiff: \
+	description=Audio Interchange Format File;\
+	file_extensions=.aifc,.aif,.aiff;\
+	icon=aiff
+
+audio/x-wav: \
+	description=Wav Audio;\
+	file_extensions=.wav;\
+	icon=wav;\
+	action=application;\
+	application=mplayer.exe %s
+
+image/gif: \
+	description=GIF Image;\
+	file_extensions=.gif;\
+	icon=gif;\
+	action=browser
+
+image/ief: \
+	description=Image Exchange Format;\
+	file_extensions=.ief
+
+image/jpeg: \
+	description=JPEG Image;\
+	file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
+	icon=jpeg;\
+	action=browser
+
+image/tiff: \
+	description=TIFF Image;\
+	file_extensions=.tif,.tiff;\
+	icon=tiff
+
+image/vnd.fpx: \
+	description=FlashPix Image;\
+	file_extensions=.fpx,.fpix
+
+image/x-cmu-rast: \
+	description=CMU Raster Image;\
+	file_extensions=.ras
+
+image/x-portable-anymap: \
+	description=PBM Anymap Image;\
+	file_extensions=.pnm
+
+image/x-portable-bitmap: \
+	description=PBM Bitmap Image;\
+	file_extensions=.pbm
+
+image/x-portable-graymap: \
+	description=PBM Graymap Image;\
+	file_extensions=.pgm
+
+image/x-portable-pixmap: \
+	description=PBM Pixmap Image;\
+	file_extensions=.ppm
+
+image/x-rgb: \
+	description=RGB Image;\
+	file_extensions=.rgb
+
+image/x-xbitmap: \
+	description=X Bitmap Image;\
+	file_extensions=.xbm,.xpm
+
+image/x-xwindowdump: \
+	description=X Window Dump Image;\
+	file_extensions=.xwd
+
+image/png: \
+	description=PNG Image;\
+	file_extensions=.png;\
+	icon=png;\
+	action=browser
+
+image/bmp: \
+	description=Bitmap Image;\
+	file_extensions=.bmp;
+
+text/html: \
+	description=HTML Document;\
+	file_extensions=.htm,.html;\
+	icon=html
+
+text/plain: \
+	description=Plain Text;\
+	file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
+	icon=text;\
+	action=browser
+
+text/tab-separated-values: \
+	description=Tab Separated Values Text;\
+	file_extensions=.tsv
+
+text/x-setext: \
+	description=Structure Enhanced Text;\
+	file_extensions=.etx
+
+video/mpeg: \
+	description=MPEG Video Clip;\
+	file_extensions=.mpg,.mpe,.mpeg;\
+	icon=mpeg
+
+video/quicktime: \
+	description=QuickTime Video Clip;\
+	file_extensions=.mov,.qt
+
+application/x-troff-msvideo: \
+	description=AVI Video;\
+	file_extensions=.avi;\
+	icon=avi;\
+	action=application;\
+	application=mplayer.exe %s
+
+video/x-sgi-movie: \
+	description=SGI Movie;\
+	file_extensions=.movie,.mv
+
+message/rfc822: \
+	description=Internet Email Message;\
+	file_extensions=.mime
+
+application/xml: \
+	description=XML document;\
+	file_extensions=.xml
+
+
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java	Wed Jul 05 19:37:28 2017 +0200
@@ -61,7 +61,7 @@
         this.followLinks = followLinks;
     }
 
-    // permision check
+    // permission check
     private void checkAccess(WindowsPath file,
                              boolean checkRead,
                              boolean checkWrite)
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Wed Jul 05 19:37:28 2017 +0200
@@ -94,7 +94,7 @@
     public static final int ERROR_NOT_READY             = 21;
     public static final int ERROR_SHARING_VIOLATION     = 32;
     public static final int ERROR_FILE_EXISTS           = 80;
-    public static final int ERROR_INVALID_PARAMATER     = 87;
+    public static final int ERROR_INVALID_PARAMETER     = 87;
     public static final int ERROR_DISK_FULL             = 112;
     public static final int ERROR_INSUFFICIENT_BUFFER   = 122;
     public static final int ERROR_INVALID_LEVEL         = 124;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java	Wed Jul 05 19:37:28 2017 +0200
@@ -98,9 +98,9 @@
                             lastAccessTime,
                             lastWriteTime);
             } catch (WindowsException x) {
-                // If ERROR_INVALID_PARAMATER is returned and the volume is
+                // If ERROR_INVALID_PARAMETER is returned and the volume is
                 // FAT then adjust to the FAT epoch and retry.
-                if (followLinks && x.lastError() == ERROR_INVALID_PARAMATER) {
+                if (followLinks && x.lastError() == ERROR_INVALID_PARAMETER) {
                     try {
                         if (WindowsFileStore.create(file).type().equals("FAT")) {
                             SetFileTime(handle,
@@ -157,7 +157,7 @@
         private static final String HIDDEN_NAME = "hidden";
         private static final String ATTRIBUTES_NAME = "attributes";
 
-        // the names of the DOS attribtues (includes basic)
+        // the names of the DOS attributes (includes basic)
         static final Set<String> dosAttributeNames =
             Util.newSet(basicAttributeNames,
                         READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME,  HIDDEN_NAME, ATTRIBUTES_NAME);
@@ -223,7 +223,7 @@
         {
             file.checkWrite();
 
-            // GetFileAttribtues & SetFileAttributes do not follow links so when
+            // GetFileAttributes & SetFileAttributes do not follow links so when
             // following links we need the final target
             String path = WindowsLinkSupport.getFinalPath(file, followLinks);
             try {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Wed Jul 05 19:37:28 2017 +0200
@@ -384,7 +384,7 @@
                 file.getPathForExceptionMessage(), null,
                 "Permissions does not allow requested access");
 
-        // for write access we neeed to check if the DOS readonly attribute
+        // for write access we need to check if the DOS readonly attribute
         // and if the volume is read-only
         if (w) {
             try {
@@ -553,7 +553,7 @@
         }
 
         /*
-         * Windows treates symbolic links to directories differently than it
+         * Windows treats symbolic links to directories differently than it
          * does to other file types. For that reason we need to check if the
          * target is a directory (or a directory junction).
          */
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Wed Jul 05 19:37:28 2017 +0200
@@ -917,7 +917,7 @@
         }
     }
     private static native void CreateHardLink0(long newFileBuffer,
-        long existingFiletBuffer) throws WindowsException;
+        long existingFileBuffer) throws WindowsException;
 
     /**
      * GetFullPathName(
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java	Wed Jul 05 19:37:28 2017 +0200
@@ -133,7 +133,7 @@
 
     /**
      * Special implementation with attached/cached attributes (used to quicken
-     * file tree traveral)
+     * file tree traversal)
      */
     private static class WindowsPathWithAttributes
         extends WindowsPath implements BasicFileAttributesHolder
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java	Wed Jul 05 19:37:28 2017 +0200
@@ -129,11 +129,11 @@
         int genericRead, int genericWrite, int genericExecute, int genericAll)
         throws WindowsException
     {
-        int privilegies = TOKEN_QUERY;
-        long hToken = OpenThreadToken(GetCurrentThread(), privilegies, false);
+        int privileges = TOKEN_QUERY;
+        long hToken = OpenThreadToken(GetCurrentThread(), privileges, false);
         if (hToken == 0L && processTokenWithDuplicateAccess != 0L)
             hToken = DuplicateTokenEx(processTokenWithDuplicateAccess,
-                privilegies);
+                privileges);
 
         boolean hasRight = false;
         if (hToken != 0L) {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java	Wed Jul 05 19:37:28 2017 +0200
@@ -200,7 +200,7 @@
     public List<String> list() throws IOException  {
         if (System.getSecurityManager() != null)
             checkAccess(file.getPathForPermissionCheck(), true, false);
-        // use stream APIs on Windwos Server 2003 and newer
+        // use stream APIs on Windows Server 2003 and newer
         if (file.getFileSystem().supportsStreamEnumeration()) {
             return listUsingStreamEnumeration();
         } else {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jul 05 19:37:28 2017 +0200
@@ -556,7 +556,7 @@
                     // ReadDirectoryChangesW failed
                     criticalError = true;
                 } else {
-                    // ERROR_MORE_DATA is a warning about incomplite
+                    // ERROR_MORE_DATA is a warning about incomplete
                     // data transfer over TCP/UDP stack. For the case
                     // [messageSize] is zero in the most of cases.
 
--- a/jdk/src/windows/classes/sun/print/Win32PrintService.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/classes/sun/print/Win32PrintService.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1585,7 +1585,7 @@
 
         if (flavor != null && !isDocFlavorSupported(flavor)) {
             throw new IllegalArgumentException("flavor " + flavor +
-                                               "is not supported");
+                                               " is not supported");
         }
 
         if (attributes == null) {
--- a/jdk/src/windows/lib/content-types.properties	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-#sun.net.www MIME content-types table
-#
-# Property fields:
-#
-#   <description> ::= 'description' '=' <descriptive string>
-#    <extensions> ::= 'file_extensions' '=' <comma-delimited list, include '.'>
-#         <image> ::= 'icon' '=' <filename of icon image>
-#        <action> ::= 'browser' | 'application' | 'save' | 'unknown'
-#   <application> ::= 'application' '=' <command line template>
-#
-
-#
-# The "we don't know anything about this data" type(s).
-# Used internally to mark unrecognized types.
-#
-content/unknown: description=Unknown Content
-unknown/unknown: description=Unknown Data Type
-
-#
-# The template we should use for temporary files when launching an application
-# to view a document of given type.
-#
-temp.file.template: c:\\temp\\%s
-
-#
-# The "real" types.
-#
-application/octet-stream: \
-	description=Generic Binary Stream;\
-	file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe,.zip,.gz
-
-application/oda: \
-	description=ODA Document;\
-	file_extensions=.oda
-
-application/pdf: \
-	description=Adobe PDF Format;\
-	file_extensions=.pdf
-
-application/postscript: \
-	description=Postscript File;\
-	file_extensions=.eps,.ai,.ps;\
-	icon=ps
-
-application/rtf: \
-	description=Wordpad Document;\
-	file_extensions=.rtf;\
-	action=application;\
-	application=wordpad.exe %s
-
-application/x-dvi: \
-	description=TeX DVI File;\
-	file_extensions=.dvi
-
-application/x-hdf: \
-	description=Hierarchical Data Format;\
-	file_extensions=.hdf;\
-	action=save
-
-application/x-latex: \
-	description=LaTeX Source;\
-	file_extensions=.latex
-
-application/x-netcdf: \
-	description=Unidata netCDF Data Format;\
-	file_extensions=.nc,.cdf;\
-	action=save
-
-application/x-tex: \
-	description=TeX Source;\
-	file_extensions=.tex
-
-application/x-texinfo: \
-	description=Gnu Texinfo;\
-	file_extensions=.texinfo,.texi
-
-application/x-troff: \
-	description=Troff Source;\
-	file_extensions=.t,.tr,.roff
-
-application/x-troff-man: \
-	description=Troff Manpage Source;\
-	file_extensions=.man
-
-application/x-troff-me: \
-	description=Troff ME Macros;\
-	file_extensions=.me
-
-application/x-troff-ms: \
-	description=Troff MS Macros;\
-	file_extensions=.ms
-
-application/x-wais-source: \
-	description=Wais Source;\
-	file_extensions=.src,.wsrc
-
-application/zip: \
-	description=Zip File;\
-	file_extensions=.zip;\
-	icon=zip;\
-	action=save
-
-application/x-bcpio: \
-	description=Old Binary CPIO Archive;\
-	file_extensions=.bcpio;\
-	action=save
-
-application/x-cpio: \
-	description=Unix CPIO Archive;\
-	file_extensions=.cpio;\
-	action=save
-
-application/x-gtar: \
-	description=Gnu Tar Archive;\
-	file_extensions=.gtar;\
-	icon=tar;\
-	action=save
-
-application/x-shar: \
-	description=Shell Archive;\
-	file_extensions=.sh,.shar;\
-	action=save
-
-application/x-sv4cpio: \
-	description=SVR4 CPIO Archive;\
-	file_extensions=.sv4cpio;\
-	action=save
-
-application/x-sv4crc: \
-	description=SVR4 CPIO with CRC;\
-	file_extensions=.sv4crc;\
-	action=save
-
-application/x-tar: \
-	description=Tar Archive;\
-	file_extensions=.tar;\
-	icon=tar;\
-	action=save
-
-application/x-ustar: \
-	description=US Tar Archive;\
-	file_extensions=.ustar;\
-	action=save
-
-audio/basic: \
-	description=Basic Audio;\
-	file_extensions=.snd,.au;\
-	icon=audio
-
-audio/x-aiff: \
-	description=Audio Interchange Format File;\
-	file_extensions=.aifc,.aif,.aiff;\
-	icon=aiff
-
-audio/x-wav: \
-	description=Wav Audio;\
-	file_extensions=.wav;\
-	icon=wav;\
-	action=application;\
-	application=mplayer.exe %s
-
-image/gif: \
-	description=GIF Image;\
-	file_extensions=.gif;\
-	icon=gif;\
-	action=browser
-
-image/ief: \
-	description=Image Exchange Format;\
-	file_extensions=.ief
-
-image/jpeg: \
-	description=JPEG Image;\
-	file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
-	icon=jpeg;\
-	action=browser
-
-image/tiff: \
-	description=TIFF Image;\
-	file_extensions=.tif,.tiff;\
-	icon=tiff
-
-image/vnd.fpx: \
-	description=FlashPix Image;\
-	file_extensions=.fpx,.fpix
-
-image/x-cmu-rast: \
-	description=CMU Raster Image;\
-	file_extensions=.ras
-
-image/x-portable-anymap: \
-	description=PBM Anymap Image;\
-	file_extensions=.pnm
-
-image/x-portable-bitmap: \
-	description=PBM Bitmap Image;\
-	file_extensions=.pbm
-
-image/x-portable-graymap: \
-	description=PBM Graymap Image;\
-	file_extensions=.pgm
-
-image/x-portable-pixmap: \
-	description=PBM Pixmap Image;\
-	file_extensions=.ppm
-
-image/x-rgb: \
-	description=RGB Image;\
-	file_extensions=.rgb
-
-image/x-xbitmap: \
-	description=X Bitmap Image;\
-	file_extensions=.xbm,.xpm
-
-image/x-xwindowdump: \
-	description=X Window Dump Image;\
-	file_extensions=.xwd
-
-image/png: \
-	description=PNG Image;\
-	file_extensions=.png;\
-	icon=png;\
-	action=browser
-
-image/bmp: \
-	description=Bitmap Image;\
-	file_extensions=.bmp;
-
-text/html: \
-	description=HTML Document;\
-	file_extensions=.htm,.html;\
-	icon=html
-
-text/plain: \
-	description=Plain Text;\
-	file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el;\
-	icon=text;\
-	action=browser
-
-text/tab-separated-values: \
-	description=Tab Separated Values Text;\
-	file_extensions=.tsv
-
-text/x-setext: \
-	description=Structure Enhanced Text;\
-	file_extensions=.etx
-
-video/mpeg: \
-	description=MPEG Video Clip;\
-	file_extensions=.mpg,.mpe,.mpeg;\
-	icon=mpeg
-
-video/quicktime: \
-	description=QuickTime Video Clip;\
-	file_extensions=.mov,.qt
-
-application/x-troff-msvideo: \
-	description=AVI Video;\
-	file_extensions=.avi;\
-	icon=avi;\
-	action=application;\
-	application=mplayer.exe %s
-
-video/x-sgi-movie: \
-	description=SGI Movie;\
-	file_extensions=.movie,.mv
-
-message/rfc822: \
-	description=Internet Email Message;\
-	file_extensions=.mime
-
-application/xml: \
-	description=XML document;\
-	file_extensions=.xml
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/windows/native/java/net/ExtendedOptionsImpl.c	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <string.h>
+
+#include "net_util.h"
+
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
+  (JNIEnv *env, jclass UNUSED)
+{
+}
+
+/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */
+
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+}
+
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+}
+
+static jboolean flowSupported0()  {
+    return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
+  (JNIEnv *env, jclass UNUSED)
+{
+    return JNI_FALSE;
+}
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Wed Jul 05 19:37:28 2017 +0200
@@ -351,6 +351,7 @@
     HANDLE hCompleted;
 
     jobject thread;
+    jobject threadGroup;
 };
 
 void ToolkitThreadProc(void *param)
@@ -363,7 +364,7 @@
     JavaVMAttachArgs attachArgs;
     attachArgs.version  = JNI_VERSION_1_2;
     attachArgs.name     = "AWT-Windows";
-    attachArgs.group    = NULL;
+    attachArgs.group    = data->threadGroup;
 
     jint res = jvm->AttachCurrentThreadAsDaemon((void **)&env, &attachArgs);
     if (res < 0) {
@@ -402,17 +403,18 @@
 /*
  * Class:     sun_awt_windows_WToolkit
  * Method:    startToolkitThread
- * Signature: (Ljava/lang/Runnable;)Z
+ * Signature: (Ljava/lang/Runnable;Ljava/lang/ThreadGroup)Z
  */
 JNIEXPORT jboolean JNICALL
-Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread)
+Java_sun_awt_windows_WToolkit_startToolkitThread(JNIEnv *env, jclass cls, jobject thread, jobject threadGroup)
 {
     AwtToolkit& tk = AwtToolkit::GetInstance();
 
     ToolkitThreadProc_Data data;
     data.result = false;
     data.thread = env->NewGlobalRef(thread);
-    if (data.thread == NULL) {
+    data.threadGroup = env->NewGlobalRef(threadGroup);
+    if (data.thread == NULL || data.threadGroup == NULL) {
         return JNI_FALSE;
     }
     data.hCompleted = ::CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -430,6 +432,7 @@
     ::CloseHandle(data.hCompleted);
 
     env->DeleteGlobalRef(data.thread);
+    env->DeleteGlobalRef(data.threadGroup);
 
     return result ? JNI_TRUE : JNI_FALSE;
 }
--- a/jdk/test/TEST.groups	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/TEST.groups	Wed Jul 05 19:37:28 2017 +0200
@@ -102,7 +102,8 @@
 jdk_net = \
     java/net \
     com/sun/net/httpserver \
-    sun/net
+    sun/net \
+    jdk/net
 
 jdk_time = \
     java/time
@@ -284,7 +285,7 @@
     javax/accessibility \
     com/sun/java/swing \
     sun/pisces \
-    com/sun/awt  
+    com/sun/awt
 
 
 ###############################################################################
@@ -294,7 +295,7 @@
 # - compact1, compact2, compact3, full JRE, JDK
 #
 # In addition they support testing of the minimal VM on compact1 and compact2.
-# Essentially this defines groups based around the specified API's and VM 
+# Essentially this defines groups based around the specified API's and VM
 # services available in the runtime.
 #
 # The groups are defined hierarchically in two forms:
@@ -506,7 +507,7 @@
  -:needs_jdk
 
 # Tests that require compact2 API's and a full VM
-#  
+#
 needs_full_vm_compact2 =
 
 # Minimal VM on Compact 2 adds in some compact2 tests
@@ -590,7 +591,7 @@
   javax/crypto/Cipher/CipherStreamClose.java \
   sun/misc/URLClassPath/ClassnameCharTest.java \
   sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \
-  sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java 
+  sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
 
 # Compact 1 adds full VM tests
 #
--- a/jdk/test/com/sun/jdi/ShellScaffold.sh	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/com/sun/jdi/ShellScaffold.sh	Wed Jul 05 19:37:28 2017 +0200
@@ -199,30 +199,26 @@
         return 1
     fi
 
-    if [ -z "$isWin98" ] ; then
-        if [ "$osname" = SunOS ] ; then
-            # Solaris and OpenSolaris use pgrep and not ps in psCmd
-            findPidCmd="$psCmd"
-        elif [ "$osname" = AIX ] ; then
-            findPidCmd="$psCmd"
-        else
+    case "$osname" in
+        SunOS | AIX)
+            $psCmd | $grep '^ *'"$1 " > $devnull 2>&1
+            res=$?
+            ;;
+        Windows* | CYGWIN*)
+            # Don't use ps on cygwin since it sometimes misses
+            # some processes (!).
+            tasklist /NH | $grep " $1 " > $devnull 2>&1
+            res=$?
+            ;;
+       *)
             #   Never use plain 'ps', which requires a "controlling terminal"
             #     and will fail  with a "ps: no controlling terminal" error.
             #     Running under 'rsh' will cause this ps error.
-            # cygwin ps puts an I in column 1 for some reason.
-            findPidCmd="$psCmd -e"
-        fi
-        $findPidCmd | $grep '^I* *'"$1 " > $devnull 2>&1
-        return $?
-    fi
-
-    # mks 6.2a on win98 has $! getting a negative
-    # number and in ps, it shows up as 0x...
-    # Thus, we can't search in ps output for 
-    # PIDs gotten via $!
-    # We don't know if it is running or not - assume it is.
-    # We don't really care about win98 anymore.
-    return 0
+            $psCmd -e | $grep '^ *'"$1 " > $devnull 2>&1
+            res=$?
+            ;;
+    esac
+    return $res
 }
 
 setup()
@@ -252,16 +248,10 @@
 
     ulimitCmd=
     osname=`uname -s`
-    isWin98=
     isCygwin=
     case "$osname" in
         Windows* | CYGWIN*)
             devnull=NUL
-            if [ "$osname" = Windows_98 -o "$osname" = Windows_ME ]; then
-                isWin98=1
-                debuggeeKeyword='we_cant_kill_debuggees_on_win98'
-                jdbKeyword='jdb\.exe'
-            fi
             case "$osname" in
                 CYGWIN*)
                     isCygwin=1
@@ -772,7 +762,7 @@
         sleep ${sleep_seconds}
         findPid $topPid
         if [ $? != 0 ] ; then
-            # Top process is dead.  We better die too
+            echo "--Top process ($topPid) is dead.  We better die too" >&2
             dojstack
             exit 1
         fi
@@ -977,19 +967,12 @@
             break
         fi
 
-        if [ ! -z "$isWin98" ] ; then
-            $psCmd | $grep -i 'JDB\.EXE' >$devnull 2>&1
-            if [ $? != 0 ] ; then
-                break
-            fi
-        fi
-
         # (Don't use jdbFailIfPresent here since it is not safe 
         # to call from different processes)
-	$grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1
-	if [ $? = 0 ] ; then
+        $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1
+        if [ $? = 0 ] ; then
             dofail "jdb input stream closed prematurely"
-	fi
+        fi
 
         # If a failure has occured, quit
         if [ -r "$failFile" ] ; then
--- a/jdk/test/demo/zipfs/Basic.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2009, 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.
- *
- * 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.
- */
-
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.nio.file.spi.FileSystemProvider;
-import java.util.*;
-import java.net.URI;
-import java.io.IOException;
-
-/**
- * Basic test for zip provider
- */
-
-public class Basic {
-    public static void main(String[] args) throws Exception {
-        Path zipfile = Paths.get(args[0]);
-
-        // Test: zip should should be returned in provider list
-        boolean found = false;
-
-        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
-            if (provider.getScheme().equalsIgnoreCase("jar")) {
-                found = true;
-                break;
-            }
-        }
-        if (!found)
-            throw new RuntimeException("'jar' provider not installed");
-
-        // Test: FileSystems#newFileSystem(Path)
-        Map<String,?> env = new HashMap<String,Object>();
-        FileSystems.newFileSystem(zipfile, null).close();
-
-        // Test: FileSystems#newFileSystem(URI)
-        URI uri = new URI("jar", zipfile.toUri().toString(), null);
-        FileSystem fs = FileSystems.newFileSystem(uri, env, null);
-
-        // Test: exercise toUri method
-        String expected = uri.toString() + "!/foo";
-        String actual = fs.getPath("/foo").toUri().toString();
-        if (!actual.equals(expected)) {
-            throw new RuntimeException("toUri returned '" + actual +
-                "', expected '" + expected + "'");
-        }
-
-        // Test: exercise directory iterator and retrieval of basic attributes
-        Files.walkFileTree(fs.getPath("/"), new FileTreePrinter());
-
-        // Test: DirectoryStream
-        found = false;
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/"))) {
-            for (Path entry: stream) {
-                found = entry.toString().equals("/META-INF/");
-                if (found) break;
-            }
-        }
-
-        if (!found)
-            throw new RuntimeException("Expected file not found");
-
-        // Test: copy file from zip file to current (scratch) directory
-        Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider");
-        if (Files.exists(source)) {
-            Path target = Paths.get(source.getFileName().toString());
-            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
-            try {
-                long s1 = Files.readAttributes(source, BasicFileAttributes.class).size();
-                long s2 = Files.readAttributes(target, BasicFileAttributes.class).size();
-                if (s2 != s1)
-                    throw new RuntimeException("target size != source size");
-            } finally {
-                Files.delete(target);
-            }
-        }
-
-        // Test: FileStore
-        FileStore store = Files.getFileStore(fs.getPath("/"));
-        if (!store.supportsFileAttributeView("basic"))
-            throw new RuntimeException("BasicFileAttributeView should be supported");
-
-        // Test: ClosedFileSystemException
-        fs.close();
-        if (fs.isOpen())
-            throw new RuntimeException("FileSystem should be closed");
-        try {
-            fs.provider().checkAccess(fs.getPath("/missing"), AccessMode.READ);
-        } catch (ClosedFileSystemException x) { }
-    }
-
-    // FileVisitor that pretty prints a file tree
-    static class FileTreePrinter extends SimpleFileVisitor<Path> {
-        private int indent = 0;
-
-        private void indent() {
-            StringBuilder sb = new StringBuilder(indent);
-            for (int i=0; i<indent; i++) sb.append(" ");
-            System.out.print(sb);
-        }
-
-        @Override
-        public FileVisitResult preVisitDirectory(Path dir,
-                                                 BasicFileAttributes attrs)
-        {
-            if (dir.getFileName() != null) {
-                indent();
-                System.out.println(dir.getFileName() + "/");
-                indent++;
-            }
-            return FileVisitResult.CONTINUE;
-        }
-
-        @Override
-        public FileVisitResult visitFile(Path file,
-                                         BasicFileAttributes attrs)
-        {
-            indent();
-            System.out.print(file.getFileName());
-            if (attrs.isRegularFile())
-                System.out.format(" (%d)", attrs.size());
-            System.out.println();
-            return FileVisitResult.CONTINUE;
-        }
-
-        @Override
-        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
-            throws IOException
-        {
-            if (exc != null)
-                super.postVisitDirectory(dir, exc);
-            if (dir.getFileName() != null)
-                indent--;
-            return FileVisitResult.CONTINUE;
-        }
-    }
-}
--- a/jdk/test/demo/zipfs/PathOps.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,457 +0,0 @@
-/*
- * Copyright (c) 2009, 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.
- *
- * 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.
- */
-
-import java.nio.file.*;
-import java.net.*;
-import java.util.*;
-import java.io.IOException;
-
-/**
- * Tests path operations for zip provider.
- */
-
-public class PathOps {
-
-    static final java.io.PrintStream out = System.out;
-    static FileSystem fs;
-
-    private String input;
-    private Path path;
-    private Exception exc;
-
-    private PathOps(String s) {
-        out.println();
-        input = s;
-        try {
-            path = fs.getPath(s);
-            out.format("%s -> %s", s, path);
-        } catch (Exception x) {
-            exc = x;
-            out.format("%s -> %s", s, x);
-        }
-        out.println();
-    }
-
-    Path path() {
-        return path;
-    }
-
-    void fail() {
-        throw new RuntimeException("PathOps failed");
-    }
-
-    void checkPath() {
-        if (path == null) {
-            throw new InternalError("path is null");
-        }
-    }
-
-    void check(Object result, String expected) {
-        out.format("\tExpected: %s\n", expected);
-        out.format("\tActual: %s\n",  result);
-        if (result == null) {
-            if (expected == null) return;
-        } else {
-            // compare string representations
-            if (expected != null && result.toString().equals(expected.toString()))
-                return;
-        }
-        fail();
-    }
-
-    void check(Object result, boolean expected) {
-        check(result, Boolean.toString(expected));
-    }
-
-    PathOps root(String expected) {
-        out.println("check root");
-        checkPath();
-        check(path.getRoot(), expected);
-        return this;
-    }
-
-    PathOps parent(String expected) {
-        out.println("check parent");
-        checkPath();
-        check(path.getParent(), expected);
-        return this;
-    }
-
-    PathOps name(String expected) {
-        out.println("check name");
-        checkPath();
-        check(path.getFileName(), expected);
-        return this;
-    }
-
-    PathOps element(int index, String expected) {
-        out.format("check element %d\n", index);
-        checkPath();
-        check(path.getName(index), expected);
-        return this;
-    }
-
-    PathOps subpath(int startIndex, int endIndex, String expected) {
-        out.format("test subpath(%d,%d)\n", startIndex, endIndex);
-        checkPath();
-        check(path.subpath(startIndex, endIndex), expected);
-        return this;
-    }
-
-    PathOps starts(String prefix) {
-        out.format("test startsWith with %s\n", prefix);
-        checkPath();
-        Path s = fs.getPath(prefix);
-        check(path.startsWith(s), true);
-        return this;
-    }
-
-    PathOps notStarts(String prefix) {
-        out.format("test not startsWith with %s\n", prefix);
-        checkPath();
-        Path s = fs.getPath(prefix);
-        check(path.startsWith(s), false);
-        return this;
-    }
-
-    PathOps ends(String suffix) {
-        out.format("test endsWith %s\n", suffix);
-        checkPath();
-        Path s = fs.getPath(suffix);
-        check(path.endsWith(s), true);
-        return this;
-    }
-
-    PathOps notEnds(String suffix) {
-        out.format("test not endsWith %s\n", suffix);
-        checkPath();
-        Path s = fs.getPath(suffix);
-        check(path.endsWith(s), false);
-        return this;
-    }
-
-    PathOps absolute() {
-        out.println("check path is absolute");
-        checkPath();
-        check(path.isAbsolute(), true);
-        return this;
-    }
-
-    PathOps notAbsolute() {
-        out.println("check path is not absolute");
-        checkPath();
-        check(path.isAbsolute(), false);
-        return this;
-    }
-
-    PathOps resolve(String other, String expected) {
-        out.format("test resolve %s\n", other);
-        checkPath();
-        check(path.resolve(other), expected);
-        return this;
-    }
-
-    PathOps relativize(String other, String expected) {
-        out.format("test relativize %s\n", other);
-        checkPath();
-        Path that = fs.getPath(other);
-        check(path.relativize(that), expected);
-        return this;
-    }
-
-    PathOps normalize(String expected) {
-        out.println("check normalized path");
-        checkPath();
-        check(path.normalize(), expected);
-        return this;
-    }
-
-    PathOps string(String expected) {
-        out.println("check string representation");
-        checkPath();
-        check(path, expected);
-        return this;
-    }
-
-    PathOps isSameFile(String target) {
-        try {
-            out.println("check two paths are same");
-            checkPath();
-            check(Files.isSameFile(path, test(target).path()), true);
-        } catch (IOException ioe) {
-            fail();
-        }
-        return this;
-    }
-
-    PathOps invalid() {
-        if (!(exc instanceof InvalidPathException)) {
-            out.println("InvalidPathException not thrown as expected");
-            fail();
-        }
-        return this;
-    }
-
-    static PathOps test(String s) {
-        return new PathOps(s);
-    }
-
-    // -- PathOpss --
-
-    static void header(String s) {
-        out.println();
-        out.println();
-        out.println("-- " + s + " --");
-    }
-
-    static void doPathOpTests() {
-        header("Path operations");
-
-        // all components
-        test("/a/b/c")
-            .root("/")
-            .parent("/a/b")
-            .name("c");
-
-        // root component only
-        test("/")
-            .root("/")
-            .parent(null)
-            .name(null);
-
-        // no root component
-        test("a/b")
-            .root(null)
-            .parent("a")
-            .name("b");
-
-        // name component only
-        test("foo")
-            .root(null)
-            .parent(null)
-            .name("foo");
-
-        // startsWith
-        test("")
-            .starts("")
-            .notStarts("/");
-        test("/")
-            .starts("/")
-            .notStarts("/foo");
-        test("/foo")
-            .starts("/")
-            .starts("/foo")
-            .notStarts("/f")
-            .notStarts("");
-        test("/foo/bar")
-            .starts("/")
-            .starts("/foo")
-            .starts("/foo/")
-            .starts("/foo/bar")
-            .notStarts("/f")
-            .notStarts("foo")
-            .notStarts("foo/bar")
-            .notStarts("");
-        test("foo")
-            .starts("foo")
-            .notStarts("f");
-        test("foo/bar")
-            .starts("foo")
-            .starts("foo/")
-            .starts("foo/bar")
-            .notStarts("f")
-            .notStarts("/foo")
-            .notStarts("/foo/bar");
-
-        // endsWith
-        test("")
-            .ends("")
-            .notEnds("/");
-        test("/")
-            .ends("/")
-            .notEnds("foo")
-            .notEnds("/foo");
-        test("/foo")
-            .ends("foo")
-            .ends("/foo")
-            .notEnds("/");
-        test("/foo/bar")
-            .ends("bar")
-            .ends("foo/bar")
-            .ends("foo/bar/")
-            .ends("/foo/bar")
-            .notEnds("/bar");
-        test("/foo/bar/")
-            .ends("bar")
-            .ends("foo/bar")
-            .ends("foo/bar/")
-            .ends("/foo/bar")
-            .notEnds("/bar");
-        test("foo")
-            .ends("foo");
-        test("foo/bar")
-            .ends("bar")
-            .ends("bar/")
-            .ends("foo/bar/")
-            .ends("foo/bar");
-
-
-        // elements
-        test("a/b/c")
-            .element(0,"a")
-            .element(1,"b")
-            .element(2,"c");
-
-        // isAbsolute
-        test("/")
-            .absolute();
-        test("/tmp")
-            .absolute();
-        test("tmp")
-            .notAbsolute();
-        test("")
-            .notAbsolute();
-
-        // resolve
-        test("/tmp")
-            .resolve("foo", "/tmp/foo")
-            .resolve("/foo", "/foo");
-        test("tmp")
-            .resolve("foo", "tmp/foo")
-            .resolve("/foo", "/foo");
-
-        // relativize
-        test("/a/b/c")
-            .relativize("/a/b/c", "")
-            .relativize("/a/b/c/d/e", "d/e")
-            .relativize("/a/x", "../../x");
-
-        // normalize
-        test("/")
-            .normalize("/");
-        test("foo")
-            .normalize("foo");
-        test("/foo")
-            .normalize("/foo");
-        test(".")
-            .normalize("");
-        test("..")
-            .normalize("..");
-        test("/..")
-            .normalize("/");
-        test("/../..")
-            .normalize("/");
-        test("foo/.")
-            .normalize("foo");
-        test("./foo")
-            .normalize("foo");
-        test("foo/..")
-            .normalize("");
-        test("../foo")
-            .normalize("../foo");
-        test("../../foo")
-            .normalize("../../foo");
-        test("foo/bar/..")
-            .normalize("foo");
-        test("foo/bar/gus/../..")
-            .normalize("foo");
-        test("/foo/bar/gus/../..")
-            .normalize("/foo");
-        test("/./.")
-            .normalize("/");
-        test("/.")
-            .normalize("/");
-        test("/./abc")
-            .normalize("/abc");
-        // invalid
-        test("foo\u0000bar")
-            .invalid();
-        test("\u0000foo")
-            .invalid();
-        test("bar\u0000")
-            .invalid();
-        test("//foo\u0000bar")
-            .invalid();
-        test("//\u0000foo")
-            .invalid();
-        test("//bar\u0000")
-            .invalid();
-
-        // normalization
-        test("//foo//bar")
-            .string("/foo/bar")
-            .root("/")
-            .parent("/foo")
-            .name("bar");
-
-        // isSameFile
-        test("/fileDoesNotExist")
-            .isSameFile("/fileDoesNotExist");
-    }
-
-    static void npes() {
-        header("NullPointerException");
-
-        Path path = fs.getPath("foo");
-
-        try {
-            path.resolve((String)null);
-            throw new RuntimeException("NullPointerException not thrown");
-        } catch (NullPointerException npe) {
-        }
-
-        try {
-            path.relativize(null);
-            throw new RuntimeException("NullPointerException not thrown");
-        } catch (NullPointerException npe) {
-        }
-
-        try {
-            path.compareTo(null);
-            throw new RuntimeException("NullPointerException not thrown");
-        } catch (NullPointerException npe) {
-        }
-
-        try {
-            path.startsWith((Path)null);
-            throw new RuntimeException("NullPointerException not thrown");
-        } catch (NullPointerException npe) {
-        }
-
-        try {
-            path.endsWith((Path)null);
-            throw new RuntimeException("NullPointerException not thrown");
-        } catch (NullPointerException npe) {
-        }
-
-    }
-
-    public static void main(String[] args) throws Throwable {
-
-        Path zipfile = Paths.get(args[0]);
-        fs = FileSystems.newFileSystem(zipfile, null);
-        npes();
-        doPathOpTests();
-        fs.close();
-    }
-}
--- a/jdk/test/demo/zipfs/ZFSTests.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- * 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.
- */
-
-/* @test
-   @bug 7156873
-   @summary ZipFileSystem regression tests
- */
-
-
-import java.net.URI;
-import java.nio.file.*;
-import java.util.Map;
-import java.util.HashMap;
-
-public class ZFSTests {
-
-    public static void main(String[] args) throws Throwable {
-        test7156873();
-    }
-
-    static void test7156873() throws Throwable {
-        String DIRWITHSPACE = "testdir with spaces";
-        Path dir = Paths.get(DIRWITHSPACE);
-        Path path = Paths.get(DIRWITHSPACE, "file.zip");
-        try {
-            Files.createDirectory(dir);
-            URI uri = URI.create("jar:" + path.toUri());
-            Map<String, Object> env = new HashMap<String, Object>();
-            env.put("create", "true");
-            try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {}
-        } finally {
-            Files.deleteIfExists(path);
-            Files.deleteIfExists(dir);
-        }
-    }
-}
--- a/jdk/test/demo/zipfs/ZipFSTester.java	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,750 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- *
- * 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.
- */
-
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.spi.*;
-import java.nio.file.attribute.*;
-import java.net.*;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.zip.*;
-
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
-
-/*
- * Tests various zipfs operations.
- */
-
-public class ZipFSTester {
-
-    public static void main(String[] args) throws Throwable {
-
-        try (FileSystem fs = newZipFileSystem(Paths.get(args[0]),
-                                              new HashMap<String, Object>()))
-        {
-            test0(fs);
-            test1(fs);
-            test2(fs);   // more tests
-            testTime(Paths.get(args[0]));
-        }
-    }
-
-    static void test0(FileSystem fs)
-        throws Exception
-    {
-        List<String> list = new LinkedList<>();
-        try (ZipFile zf = new ZipFile(fs.toString())) {
-            Enumeration<? extends ZipEntry> zes = zf.entries();
-            while (zes.hasMoreElements()) {
-                list.add(zes.nextElement().getName());
-            }
-            for (String pname : list) {
-                Path path = fs.getPath(pname);
-                if (!Files.exists(path))
-                    throw new RuntimeException("path existence check failed!");
-                while ((path = path.getParent()) != null) {
-                    if (!Files.exists(path))
-                        throw new RuntimeException("parent existence check failed!");
-                }
-            }
-        }
-    }
-
-    static void test1(FileSystem fs0)
-        throws Exception
-    {
-        Random rdm = new Random();
-        // clone a fs and test on it
-        Path tmpfsPath = getTempPath();
-        Map<String, Object> env = new HashMap<String, Object>();
-        env.put("create", "true");
-        try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) {
-            z2zcopy(fs0, copy, "/", 0);
-        }
-
-        try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) {
-
-            FileSystemProvider provider = fs.provider();
-            // newFileSystem(path...) should not throw exception
-            try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap<String, Object>())){}
-            try (FileSystem fsUri = provider.newFileSystem(
-                     new URI("jar", tmpfsPath.toUri().toString(), null),
-                     new HashMap<String, Object>()))
-            {
-              throw new RuntimeException("newFileSystem(uri...) does not throw exception");
-            } catch (FileSystemAlreadyExistsException fsaee) {}
-
-            // prepare a src
-            Path src = getTempPath();
-            String tmpName = src.toString();
-            OutputStream os = Files.newOutputStream(src);
-            byte[] bits = new byte[12345];
-            rdm.nextBytes(bits);
-            os.write(bits);
-            os.close();
-
-            try {
-                provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(),
-                                       new HashMap<String, Object>());
-                throw new RuntimeException("newFileSystem() opens a directory as zipfs");
-            } catch (UnsupportedOperationException uoe) {}
-
-            try {
-                provider.newFileSystem(src, new HashMap<String, Object>());
-                throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs");
-            } catch (UnsupportedOperationException uoe) {}
-
-
-            // copyin
-            Path dst = getPathWithParents(fs, tmpName);
-            Files.copy(src, dst);
-            checkEqual(src, dst);
-
-            // copy
-            Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
-                                           "/efg" + rdm.nextInt(100) + "/foo.class");
-            Files.copy(dst, dst2);
-            //dst.moveTo(dst2);
-            checkEqual(src, dst2);
-
-            // delete
-            Files.delete(dst);
-            if (Files.exists(dst))
-                throw new RuntimeException("Failed!");
-
-            // moveout
-            Path dst3 = Paths.get(tmpName + "_Tmp");
-            Files.move(dst2, dst3);
-            checkEqual(src, dst3);
-            if (Files.exists(dst2))
-                throw new RuntimeException("Failed!");
-
-            // copyback + move
-            Files.copy(dst3, dst);
-            Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
-            Files.move(dst, dst4);
-            checkEqual(src, dst4);
-
-            // delete
-            Files.delete(dst4);
-            if (Files.exists(dst4))
-                throw new RuntimeException("Failed!");
-            Files.delete(dst3);
-            if (Files.exists(dst3))
-                throw new RuntimeException("Failed!");
-
-            // move (existing entry)
-            Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
-            if (Files.exists(dst5)) {
-                Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
-                Files.move(dst5, dst6);
-                walk(fs.getPath("/"));
-            }
-
-            // newInputStream on dir
-            Path parent = dst2.getParent();
-            try {
-                Files.newInputStream(parent);
-                throw new RuntimeException("Failed");
-            } catch (FileSystemException e) {
-                e.printStackTrace();    // expected fse
-            }
-
-            // rmdirs
-            try {
-                rmdirs(parent);
-            } catch (IOException x) {
-                x.printStackTrace();
-            }
-
-            // newFileChannel() copy in, out and verify via fch
-            fchCopy(src, dst);    // in
-            checkEqual(src, dst);
-            Path tmp = Paths.get(tmpName + "_Tmp");
-            fchCopy(dst, tmp);   //  out
-            checkEqual(src, tmp);
-            Files.delete(tmp);
-
-            // test channels
-            channel(fs, dst);
-            Files.delete(dst);
-            Files.delete(src);
-        } finally {
-            if (Files.exists(tmpfsPath))
-                Files.delete(tmpfsPath);
-        }
-    }
-
-    static void test2(FileSystem fs) throws Exception {
-
-        Path fs1Path = getTempPath();
-        Path fs2Path = getTempPath();
-        Path fs3Path = getTempPath();
-
-        // create a new filesystem, copy everything from fs
-        Map<String, Object> env = new HashMap<String, Object>();
-        env.put("create", "true");
-        FileSystem fs0 = newZipFileSystem(fs1Path, env);
-
-        final FileSystem fs2 = newZipFileSystem(fs2Path, env);
-        final FileSystem fs3 = newZipFileSystem(fs3Path, env);
-
-        System.out.println("copy src: fs -> fs0...");
-        z2zcopy(fs, fs0, "/", 0);   // copy fs -> fs1
-        fs0.close();                // dump to file
-
-        System.out.println("open fs0 as fs1");
-        env = new HashMap<String, Object>();
-        final FileSystem fs1 = newZipFileSystem(fs1Path, env);
-
-        System.out.println("listing...");
-        final ArrayList<String> files = new ArrayList<>();
-        final ArrayList<String> dirs = new ArrayList<>();
-        list(fs1.getPath("/"), files, dirs);
-
-        Thread t0 = new Thread(new Runnable() {
-            public void run() {
-                List<String> list = new ArrayList<>(dirs);
-                Collections.shuffle(list);
-                for (String path : list) {
-                    try {
-                        z2zcopy(fs1, fs2, path, 0);
-                    } catch (Exception x) {
-                        x.printStackTrace();
-                    }
-                }
-            }
-
-        });
-
-        Thread t1 = new Thread(new Runnable() {
-            public void run() {
-                List<String> list = new ArrayList<>(dirs);
-                Collections.shuffle(list);
-                for (String path : list) {
-                    try {
-                        z2zcopy(fs1, fs2, path, 1);
-                    } catch (Exception x) {
-                        x.printStackTrace();
-                    }
-                }
-            }
-
-        });
-
-        Thread t2 = new Thread(new Runnable() {
-            public void run() {
-                List<String> list = new ArrayList<>(dirs);
-                Collections.shuffle(list);
-                for (String path : list) {
-                    try {
-                        z2zcopy(fs1, fs2, path, 2);
-                    } catch (Exception x) {
-                        x.printStackTrace();
-                    }
-                }
-            }
-
-        });
-
-        Thread t3 = new Thread(new Runnable() {
-            public void run() {
-                List<String> list = new ArrayList<>(files);
-                Collections.shuffle(list);
-                while (!list.isEmpty()) {
-                    Iterator<String> itr = list.iterator();
-                    while (itr.hasNext()) {
-                        String path = itr.next();
-                        try {
-                            if (Files.exists(fs2.getPath(path))) {
-                                z2zmove(fs2, fs3, path);
-                                itr.remove();
-                            }
-                        } catch (FileAlreadyExistsException x){
-                            itr.remove();
-                        } catch (Exception x) {
-                            x.printStackTrace();
-                        }
-                    }
-                }
-            }
-
-        });
-
-        System.out.println("copying/removing...");
-        t0.start(); t1.start(); t2.start(); t3.start();
-        t0.join(); t1.join(); t2.join(); t3.join();
-
-        System.out.println("closing: fs1, fs2");
-        fs1.close();
-        fs2.close();
-
-        int failed = 0;
-        System.out.println("checkEqual: fs vs fs3");
-        for (String path : files) {
-            try {
-                checkEqual(fs.getPath(path), fs3.getPath(path));
-            } catch (IOException x) {
-                //x.printStackTrace();
-                failed++;
-            }
-        }
-        System.out.println("closing: fs3");
-        fs3.close();
-
-        System.out.println("opening: fs3 as fs4");
-        FileSystem fs4 = newZipFileSystem(fs3Path, env);
-
-
-        ArrayList<String> files2 = new ArrayList<>();
-        ArrayList<String> dirs2 = new ArrayList<>();
-        list(fs4.getPath("/"), files2, dirs2);
-
-        System.out.println("checkEqual: fs vs fs4");
-        for (String path : files2) {
-            checkEqual(fs.getPath(path), fs4.getPath(path));
-        }
-        System.out.println("walking: fs4");
-        walk(fs4.getPath("/"));
-        System.out.println("closing: fs4");
-        fs4.close();
-        System.out.printf("failed=%d%n", failed);
-
-        Files.delete(fs1Path);
-        Files.delete(fs2Path);
-        Files.delete(fs3Path);
-    }
-
-    // test file stamp
-    static void testTime(Path src) throws Exception {
-        BasicFileAttributes attrs = Files
-                        .getFileAttributeView(src, BasicFileAttributeView.class)
-                        .readAttributes();
-        // create a new filesystem, copy this file into it
-        Map<String, Object> env = new HashMap<String, Object>();
-        env.put("create", "true");
-        Path fsPath = getTempPath();
-        FileSystem fs = newZipFileSystem(fsPath, env);
-
-        System.out.println("test copy with timestamps...");
-        // copyin
-        Path dst = getPathWithParents(fs, "me");
-        Files.copy(src, dst, COPY_ATTRIBUTES);
-        checkEqual(src, dst);
-        System.out.println("mtime: " + attrs.lastModifiedTime());
-        System.out.println("ctime: " + attrs.creationTime());
-        System.out.println("atime: " + attrs.lastAccessTime());
-        System.out.println(" ==============>");
-        BasicFileAttributes dstAttrs = Files
-                        .getFileAttributeView(dst, BasicFileAttributeView.class)
-                        .readAttributes();
-        System.out.println("mtime: " + dstAttrs.lastModifiedTime());
-        System.out.println("ctime: " + dstAttrs.creationTime());
-        System.out.println("atime: " + dstAttrs.lastAccessTime());
-
-        // 1-second granularity
-        if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) !=
-            dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) ||
-            attrs.lastAccessTime().to(TimeUnit.SECONDS) !=
-            dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) ||
-            attrs.creationTime().to(TimeUnit.SECONDS) !=
-            dstAttrs.creationTime().to(TimeUnit.SECONDS)) {
-            throw new RuntimeException("Timestamp Copy Failed!");
-        }
-        Files.delete(fsPath);
-    }
-
-    private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
-        throws Exception
-    {
-        return FileSystems.newFileSystem(
-            new URI("jar", path.toUri().toString(), null), env, null);
-    }
-
-    private static Path getTempPath() throws IOException
-    {
-        File tmp = File.createTempFile("testzipfs_", "zip");
-        tmp.delete();    // we need a clean path, no file
-        return tmp.toPath();
-    }
-
-    private static void list(Path path, List<String> files, List<String> dirs )
-        throws IOException
-    {
-        if (Files.isDirectory(path)) {
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
-                for (Path child : ds)
-                    list(child, files, dirs);
-            }
-            dirs.add(path.toString());
-        } else {
-            files.add(path.toString());
-        }
-    }
-
-    private static void z2zcopy(FileSystem src, FileSystem dst, String path,
-                                int method)
-        throws IOException
-    {
-        Path srcPath = src.getPath(path);
-        Path dstPath = dst.getPath(path);
-
-        if (Files.isDirectory(srcPath)) {
-            if (!Files.exists(dstPath)) {
-                try {
-                    mkdirs(dstPath);
-                } catch (FileAlreadyExistsException x) {}
-            }
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
-                for (Path child : ds) {
-                    z2zcopy(src, dst,
-                           path + (path.endsWith("/")?"":"/") + child.getFileName(),
-                           method);
-                }
-            }
-        } else {
-            try {
-                if (Files.exists(dstPath))
-                    return;
-                switch (method) {
-                case 0:
-                    Files.copy(srcPath, dstPath);
-                    break;
-                case 1:
-                    chCopy(srcPath, dstPath);
-                    break;
-                case 2:
-                    //fchCopy(srcPath, dstPath);
-                    streamCopy(srcPath, dstPath);
-                    break;
-                }
-            } catch (FileAlreadyExistsException x) {}
-        }
-    }
-
-    private static void z2zmove(FileSystem src, FileSystem dst, String path)
-        throws IOException
-    {
-        Path srcPath = src.getPath(path);
-        Path dstPath = dst.getPath(path);
-
-        if (Files.isDirectory(srcPath)) {
-            if (!Files.exists(dstPath))
-                mkdirs(dstPath);
-            try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
-                for (Path child : ds) {
-                    z2zmove(src, dst,
-                            path + (path.endsWith("/")?"":"/") + child.getFileName());
-                }
-            }
-        } else {
-            //System.out.println("moving..." + path);
-            Path parent = dstPath.getParent();
-            if (parent != null && Files.notExists(parent))
-                mkdirs(parent);
-            Files.move(srcPath, dstPath);
-        }
-    }
-
-    private static void walk(Path path) throws IOException
-    {
-        Files.walkFileTree(
-            path,
-            new SimpleFileVisitor<Path>() {
-                private int indent = 0;
-                private void indent() {
-                    int n = 0;
-                    while (n++ < indent)
-                        System.out.printf(" ");
-                }
-
-                @Override
-                public FileVisitResult visitFile(Path file,
-                                                 BasicFileAttributes attrs)
-                {
-                    indent();
-                    System.out.printf("%s%n", file.getFileName().toString());
-                    return FileVisitResult.CONTINUE;
-                }
-
-                @Override
-                public FileVisitResult preVisitDirectory(Path dir,
-                                                         BasicFileAttributes attrs)
-                {
-                    indent();
-                    System.out.printf("[%s]%n", dir.toString());
-                    indent += 2;
-                    return FileVisitResult.CONTINUE;
-                }
-
-                @Override
-                public FileVisitResult postVisitDirectory(Path dir,
-                                                          IOException ioe)
-                    throws IOException
-                {
-                    indent -= 2;
-                    return FileVisitResult.CONTINUE;
-                }
-        });
-    }
-
-    private static void mkdirs(Path path) throws IOException {
-        if (Files.exists(path))
-            return;
-        path = path.toAbsolutePath();
-        Path parent = path.getParent();
-        if (parent != null) {
-            if (Files.notExists(parent))
-                mkdirs(parent);
-        }
-        Files.createDirectory(path);
-    }
-
-    private static void rmdirs(Path path) throws IOException {
-        while (path != null && path.getNameCount() != 0) {
-            Files.delete(path);
-            path = path.getParent();
-        }
-    }
-
-    // check the content of two paths are equal
-    private static void checkEqual(Path src, Path dst) throws IOException
-    {
-        //System.out.printf("checking <%s> vs <%s>...%n",
-        //                  src.toString(), dst.toString());
-
-        //streams
-        byte[] bufSrc = new byte[8192];
-        byte[] bufDst = new byte[8192];
-        try (InputStream isSrc = Files.newInputStream(src);
-             InputStream isDst = Files.newInputStream(dst))
-        {
-            int nSrc = 0;
-            while ((nSrc = isSrc.read(bufSrc)) != -1) {
-                int nDst = 0;
-                while (nDst < nSrc) {
-                    int n = isDst.read(bufDst, nDst, nSrc - nDst);
-                    if (n == -1) {
-                        System.out.printf("checking <%s> vs <%s>...%n",
-                                          src.toString(), dst.toString());
-                        throw new RuntimeException("CHECK FAILED!");
-                    }
-                    nDst += n;
-                }
-                while (--nSrc >= 0) {
-                    if (bufSrc[nSrc] != bufDst[nSrc]) {
-                        System.out.printf("checking <%s> vs <%s>...%n",
-                                          src.toString(), dst.toString());
-                        throw new RuntimeException("CHECK FAILED!");
-                    }
-                    nSrc--;
-                }
-            }
-        }
-
-        // channels
-        try (SeekableByteChannel chSrc = Files.newByteChannel(src);
-             SeekableByteChannel chDst = Files.newByteChannel(dst))
-        {
-            if (chSrc.size() != chDst.size()) {
-                System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
-                                  chSrc.toString(), chSrc.size(),
-                                  chDst.toString(), chDst.size());
-                throw new RuntimeException("CHECK FAILED!");
-            }
-            ByteBuffer bbSrc = ByteBuffer.allocate(8192);
-            ByteBuffer bbDst = ByteBuffer.allocate(8192);
-
-            int nSrc = 0;
-            while ((nSrc = chSrc.read(bbSrc)) != -1) {
-                int nDst = chDst.read(bbDst);
-                if (nSrc != nDst) {
-                    System.out.printf("checking <%s> vs <%s>...%n",
-                                      src.toString(), dst.toString());
-                    throw new RuntimeException("CHECK FAILED!");
-                }
-                while (--nSrc >= 0) {
-                    if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
-                        System.out.printf("checking <%s> vs <%s>...%n",
-                                          src.toString(), dst.toString());
-                        throw new RuntimeException("CHECK FAILED!");
-                    }
-                    nSrc--;
-                }
-                bbSrc.flip();
-                bbDst.flip();
-            }
-
-            // Check if source read position is at the end
-            if (chSrc.position() != chSrc.size()) {
-                System.out.printf("src[%s]: size=%d, position=%d%n",
-                                  chSrc.toString(), chSrc.size(), chSrc.position());
-                throw new RuntimeException("CHECK FAILED!");
-            }
-
-            // Check if destination read position is at the end
-            if (chDst.position() != chDst.size()) {
-                System.out.printf("dst[%s]: size=%d, position=%d%n",
-                                  chDst.toString(), chDst.size(), chDst.position());
-                throw new RuntimeException("CHECK FAILED!");
-            }
-        } catch (IOException x) {
-            x.printStackTrace();
-        }
-    }
-
-    private static void fchCopy(Path src, Path dst) throws IOException
-    {
-        Set<OpenOption> read = new HashSet<>();
-        read.add(READ);
-        Set<OpenOption> openwrite = new HashSet<>();
-        openwrite.add(CREATE_NEW);
-        openwrite.add(WRITE);
-
-        try (FileChannel srcFc = src.getFileSystem()
-                                    .provider()
-                                    .newFileChannel(src, read);
-             FileChannel dstFc = dst.getFileSystem()
-                                    .provider()
-                                    .newFileChannel(dst, openwrite))
-        {
-            ByteBuffer bb = ByteBuffer.allocate(8192);
-            while (srcFc.read(bb) >= 0) {
-                bb.flip();
-                dstFc.write(bb);
-                bb.clear();
-            }
-        }
-    }
-
-    private static void chCopy(Path src, Path dst) throws IOException
-    {
-        Set<OpenOption> read = new HashSet<>();
-        read.add(READ);
-        Set<OpenOption> openwrite = new HashSet<>();
-        openwrite.add(CREATE_NEW);
-        openwrite.add(WRITE);
-
-        try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
-             SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
-        {
-
-            ByteBuffer bb = ByteBuffer.allocate(8192);
-            while (srcCh.read(bb) >= 0) {
-                bb.flip();
-                dstCh.write(bb);
-                bb.clear();
-            }
-
-            // Check if source read position is at the end
-            if (srcCh.position() != srcCh.size()) {
-                System.out.printf("src[%s]: size=%d, position=%d%n",
-                                  srcCh.toString(), srcCh.size(), srcCh.position());
-                throw new RuntimeException("CHECK FAILED!");
-            }
-
-            // Check if destination write position is at the end
-            if (dstCh.position() != dstCh.size()) {
-                System.out.printf("dst[%s]: size=%d, position=%d%n",
-                                  dstCh.toString(), dstCh.size(), dstCh.position());
-                throw new RuntimeException("CHECK FAILED!");
-            }
-        }
-    }
-
-    private static void streamCopy(Path src, Path dst) throws IOException
-    {
-        byte[] buf = new byte[8192];
-        try (InputStream isSrc = Files.newInputStream(src);
-             OutputStream osDst = Files.newOutputStream(dst))
-        {
-            int n = 0;
-            while ((n = isSrc.read(buf)) != -1) {
-                osDst.write(buf, 0, n);
-            }
-        }
-    }
-
-    static void channel(FileSystem fs, Path path)
-        throws Exception
-    {
-        System.out.println("test ByteChannel...");
-        Set<OpenOption> read = new HashSet<>();
-        read.add(READ);
-        int n = 0;
-        ByteBuffer bb = null;
-        ByteBuffer bb2 = null;
-        int N = 120;
-
-        try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
-            System.out.printf("   sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
-            if (sbc.position() != 0) {
-                throw new RuntimeException("CHECK FAILED!");
-            }
-
-            bb = ByteBuffer.allocate((int)sbc.size());
-            n = sbc.read(bb);
-            System.out.printf("   sbc[1]: read=%d, pos=%d, size=%d%n",
-                              n, sbc.position(), sbc.size());
-            if (sbc.position() != sbc.size()) {
-                throw new RuntimeException("CHECK FAILED!");
-            }
-            bb2 = ByteBuffer.allocate((int)sbc.size());
-        }
-
-        // sbc.position(pos) is not supported in current version
-        // try the FileChannel
-        try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) {
-            sbc.position(N);
-            System.out.printf("   sbc[2]: pos=%d, size=%d%n",
-                              sbc.position(), sbc.size());
-            if (sbc.position() != N) {
-                throw new RuntimeException("CHECK FAILED!");
-            }
-            bb2.limit(100);
-            n = sbc.read(bb2);
-            System.out.printf("   sbc[3]: read=%d, pos=%d, size=%d%n",
-                              n, sbc.position(), sbc.size());
-            if (n < 0 || sbc.position() != (N + n)) {
-                throw new RuntimeException("CHECK FAILED!");
-            }
-            System.out.printf("   sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
-                              N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
-        }
-    }
-
-    // create parents if does not exist
-    static Path getPathWithParents(FileSystem fs, String name)
-        throws Exception
-    {
-        Path path = fs.getPath(name);
-        Path parent = path.getParent();
-        if (parent != null && Files.notExists(parent))
-            mkdirs(parent);
-        return path;
-    }
-}
--- a/jdk/test/demo/zipfs/basic.sh	Thu Apr 17 15:22:07 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#
-# Copyright (c) 2009, 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.
-# 
-# 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.
-#
-# @test
-# @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
-# 7157656 8002390 7012868 7012856 8015728
-# @summary Test ZipFileSystem demo
-# @build Basic PathOps ZipFSTester
-# @run shell basic.sh
-
-if [ -z "${TESTJAVA}" ]; then
-    echo "Test must be run with jtreg"
-    exit 0
-fi
-
-ZIPFS="${TESTJAVA}/demo/nio/zipfs/zipfs.jar"
-if [ ! -r "${ZIPFS}" ]; then
-    echo "${ZIPFS} not found"
-    exit 0
-fi
-
-OS=`uname -s`
-case "$OS" in
-    Windows_* | CYGWIN* )
-        CLASSPATH="${TESTCLASSES};${ZIPFS}"
-        ;;
-    * )
-        CLASSPATH="${TESTCLASSES}:${ZIPFS}"
-        ;;
-esac
-export CLASSPATH
-
-failures=0
-
-go() {
-    echo ""
-    ${TESTJAVA}/bin/java ${TESTVMOPTS} $1 $2 $3 2>&1
-    if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
-}
-
-# Run the tests
-
-go Basic "${ZIPFS}"
-go PathOps "${ZIPFS}"
-go ZipFSTester "${ZIPFS}"
-
-#
-# Results
-#
-
-if [ $failures -gt 0 ];
-then echo "$failures tests failed";
-else echo "All tests passed";
-fi
-exit $failures
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Toolkit/LoadAWTCrashTest/LoadAWTCrashTest.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+  @test
+  @bug 8031477
+  @summary Crash while awt starting
+  @author Petr Pchelko
+  @run main/othervm LoadAWTCrashTest
+*/
+
+public class LoadAWTCrashTest {
+    public static void main(String[] args) {
+        System.loadLibrary("awt");
+        // If the bug is present JVM would crash or deadlock
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/TextLayout/TestAATMorxFont.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+/* @test
+ * @summary verify rendering of MORX fonts on OS X.
+ * @bug 8031462
+ */
+
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+
+public class TestAATMorxFont extends JComponent {
+    public static void main(String[] args) {
+        String osName = System.getProperty("os.name");
+        System.out.println("OS is " + osName);
+        osName = osName.toLowerCase();
+        if (!osName.startsWith("mac")) {
+            return;
+        }
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                JFrame frame = new JFrame("Test Morx");
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+                TestAATMorxFont  panel = new TestAATMorxFont();
+                frame.add(panel);
+                frame.pack();
+                frame.setVisible(true);
+            }
+        });
+    }
+
+    public Dimension getPreferredSize() {
+        return new Dimension(1200, 400);
+    }
+
+    public void paintComponent(Graphics g) {
+        Graphics2D g2d = (Graphics2D)g;
+        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+                             RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+        int y = 50;
+        g.setFont(new Font("Gujarati MT", Font.PLAIN, 40));
+        System.out.println(g.getFont());
+        g.drawString("\u0A95\u0ACD \u0A95\u0A95\u0A95 \u0A95\u0ACD\u0A95\u0ACD\u0A95", 20, y);
+        y += 50;
+        g.setFont(new Font("Tamil Sangam MN", Font.PLAIN, 40));
+        System.out.println(g.getFont());
+        g.drawString("\u0b95\u0bCD \u0b95\u0b95\u0b95 \u0b95\u0bCD\u0b95\u0bCD\u0b95", 20, y);
+        y += 50;
+        g.setFont(new Font("Telugu Sangam MN", Font.PLAIN, 40));
+        System.out.println(g.getFont());
+        g.drawString("\u0c15\u0c4D \u0c15\u0c15\u0c15 \u0c15\u0c4D\u0c15\u0c4D\u0c15", 20, y);
+        y += 50;
+        g.setFont(new Font("Devanagari Sangam MN", Font.PLAIN, 40));
+        System.out.println(g.getFont());
+        g.drawString("\u0915\u0940 \u0915\u0947 \u0915\u0942", 20, y);
+        y += 50;
+        g.drawString("\u0907\u0930\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915", 20, y);
+        y += 50;
+        g.drawString("\u0930\u093F\u0935\u094D\u092F\u0942 \u0915\u0947 \u092C\u093E\u0926 \u0935\u093F\u0915\u093E\u0938 \u0913\u0932\u0902\u092A\u093F\u0915 \u0938\u0947 \u092C\u093E\u0939\u0930 (\u0926\u0947\u0935\u0928\u093E\u0917\u0930\u0940) (\u0939\u093F\u0928\u094D\u0926\u0940) \u0907\u0930\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915", 20, y);
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 8039396
+ * @run main UnresolvableObjectStreamClass serialize
+ * @clean MySerializable
+ * @run main UnresolvableObjectStreamClass deserialize
+ *
+ * @summary NPE when writing a class descriptor object to a custom
+ *          ObjectOutputStream
+ */
+
+import java.io.*;
+
+public class UnresolvableObjectStreamClass {
+    public static void main(String[] args) throws Throwable {
+        if (args.length > 0 && args[0].equals("serialize")) {
+            try (FileOutputStream fos = new FileOutputStream("temp1.ser");
+                 ObjectOutputStream oos = new ObjectOutputStream(fos)) {
+                ObjectStreamClass osc =
+                         ObjectStreamClass.lookup(MySerializable.class);
+                oos.writeObject(osc);
+            }
+        } else if (args.length > 0 && args[0].equals("deserialize")) {
+            try (FileInputStream fis = new FileInputStream("temp1.ser");
+                 ObjectInputStream ois = new ObjectInputStream(fis);
+                 FileOutputStream fos = new FileOutputStream("temp2.ser");
+                 ObjectOutputStream oos = new ObjectOutputStream(fos) {
+                         /*must be subclassed*/}) {
+                ObjectStreamClass osc = (ObjectStreamClass)ois.readObject();
+                // serialize it again
+                try {
+                    oos.writeObject(osc);
+                } catch (NullPointerException e) {
+                    throw new RuntimeException("Failed to write" +
+                            " unresolvable ObjectStreamClass", e);
+                }
+            }
+        } else {
+            throw new RuntimeException("The command line option must be" +
+                                       " one of: serialize or deserialize");
+        }
+    }
+}
+
+class MySerializable implements Serializable {
+}
--- a/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	Wed Jul 05 19:37:28 2017 +0200
@@ -30,11 +30,9 @@
  *
  * @author  Mandy Chung
  *
- * @build CollectionUsageThreshold MemoryUtil
- * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseSerialGC CollectionUsageThreshold
- * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseParallelGC CollectionUsageThreshold
- * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseG1GC CollectionUsageThreshold
- * @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC CollectionUsageThreshold
+ * @library /lib/testlibrary/
+ * @build CollectionUsageThreshold MemoryUtil RunUtil
+ * @run main/timeout=300 CollectionUsageThreshold
  */
 
 import java.util.*;
@@ -61,6 +59,20 @@
     // finishes checking the low memory notification result
     private static final CyclicBarrier barrier = new CyclicBarrier(2);
 
+    /**
+     * Run the test multiple times with different GC versions.
+     * First with default command line specified by the framework.
+     * Then with GC versions specified by the test.
+     */
+    public static void main(String a[]) throws Throwable {
+        final String main = "CollectionUsageThreshold$TestMain";
+        RunUtil.runTestKeepGcOpts(main);
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC");
+    }
+
     static class PoolRecord {
         private final MemoryPoolMXBean pool;
         private final AtomicInteger listenerInvoked = new AtomicInteger(0);
@@ -110,88 +122,90 @@
         }
     }
 
-    public static void main(String args[]) throws Exception {
-        if (args.length > 0 && args[0].equals("trace")) {
-            trace = true;
-        }
+    private static class TestMain {
+        public static void main(String args[]) throws Exception {
+            if (args.length > 0 && args[0].equals("trace")) {
+                trace = true;
+            }
 
-        List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();
-        List<MemoryManagerMXBean> managers = getMemoryManagerMXBeans();
+            List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();
+            List<MemoryManagerMXBean> managers = getMemoryManagerMXBeans();
 
-        if (trace) {
-            MemoryUtil.printMemoryPools(pools);
-            MemoryUtil.printMemoryManagers(managers);
-        }
+            if (trace) {
+                MemoryUtil.printMemoryPools(pools);
+                MemoryUtil.printMemoryManagers(managers);
+            }
 
-        // Find the Old generation which supports low memory detection
-        for (MemoryPoolMXBean p : pools) {
-            if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) {
-                if (p.getName().toLowerCase().contains("perm")) {
-                    // if we have a "perm gen" pool increase the number of expected
-                    // memory pools by one.
-                    numMemoryPools++;
-                }
-                PoolRecord pr = new PoolRecord(p);
-                result.put(p.getName(), pr);
-                if (result.size() == numMemoryPools) {
-                    break;
+            // Find the Old generation which supports low memory detection
+            for (MemoryPoolMXBean p : pools) {
+                if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) {
+                    if (p.getName().toLowerCase().contains("perm")) {
+                        // if we have a "perm gen" pool increase the number of expected
+                        // memory pools by one.
+                        numMemoryPools++;
+                    }
+                    PoolRecord pr = new PoolRecord(p);
+                    result.put(p.getName(), pr);
+                    if (result.size() == numMemoryPools) {
+                        break;
+                    }
                 }
             }
-        }
-        if (result.size() != numMemoryPools) {
-            throw new RuntimeException("Unexpected number of selected pools");
+            if (result.size() != numMemoryPools) {
+                throw new RuntimeException("Unexpected number of selected pools");
+            }
+
+            try {
+                // This test creates a checker thread responsible for checking
+                // the low memory notifications.  It blocks until a permit
+                // from the signals semaphore is available.
+                Checker checker = new Checker("Checker thread");
+                checker.setDaemon(true);
+                checker.start();
+
+                for (PoolRecord pr : result.values()) {
+                    pr.getPool().setCollectionUsageThreshold(THRESHOLD);
+                    System.out.println("Collection usage threshold of " +
+                        pr.getPool().getName() + " set to " + THRESHOLD);
+                }
+
+                SensorListener listener = new SensorListener();
+                NotificationEmitter emitter = (NotificationEmitter) mm;
+                emitter.addNotificationListener(listener, null, null);
+
+                // The main thread invokes GC to trigger the VM to perform
+                // low memory detection and then waits until the checker thread
+                // finishes its work to check for a low-memory notification.
+                //
+                // At GC time, VM will issue low-memory notification and invoke
+                // the listener which will release a permit to the signals semaphore.
+                // When the checker thread acquires the permit and finishes
+                // checking the low-memory notification, it will also call
+                // barrier.await() to signal the main thread to resume its work.
+                for (int i = 0; i < NUM_GCS; i++) {
+                    invokeGC();
+                    barrier.await();
+                }
+            } finally {
+                // restore the default
+                for (PoolRecord pr : result.values()) {
+                    pr.getPool().setCollectionUsageThreshold(0);
+                }
+            }
+            System.out.println(RunUtil.successMessage);
         }
 
-        try {
-            // This test creates a checker thread responsible for checking
-            // the low memory notifications.  It blocks until a permit
-            // from the signals semaphore is available.
-            Checker checker = new Checker("Checker thread");
-            checker.setDaemon(true);
-            checker.start();
 
-            for (PoolRecord pr : result.values()) {
-                pr.getPool().setCollectionUsageThreshold(THRESHOLD);
-                System.out.println("Collection usage threshold of " +
-                    pr.getPool().getName() + " set to " + THRESHOLD);
-            }
-
-            SensorListener listener = new SensorListener();
-            NotificationEmitter emitter = (NotificationEmitter) mm;
-            emitter.addNotificationListener(listener, null, null);
+        private static void invokeGC() {
+            System.out.println("Calling System.gc()");
+            numGCs++;
+            mm.gc();
 
-            // The main thread invokes GC to trigger the VM to perform
-            // low memory detection and then waits until the checker thread
-            // finishes its work to check for a low-memory notification.
-            //
-            // At GC time, VM will issue low-memory notification and invoke
-            // the listener which will release a permit to the signals semaphore.
-            // When the checker thread acquires the permit and finishes
-            // checking the low-memory notification, it will also call
-            // barrier.await() to signal the main thread to resume its work.
-            for (int i = 0; i < NUM_GCS; i++) {
-                invokeGC();
-                barrier.await();
-            }
-        } finally {
-            // restore the default
-            for (PoolRecord pr : result.values()) {
-                pr.getPool().setCollectionUsageThreshold(0);
-            }
-        }
-        System.out.println("Test passed.");
-    }
-
-
-    private static void invokeGC() {
-        System.out.println("Calling System.gc()");
-        numGCs++;
-        mm.gc();
-
-        if (trace) {
-            for (PoolRecord pr : result.values()) {
-                System.out.println("Usage after GC for: " + pr.getPool().getName());
-                MemoryUtil.printMemoryUsage(pr.getPool().getUsage());
+            if (trace) {
+                for (PoolRecord pr : result.values()) {
+                    System.out.println("Usage after GC for: " + pr.getPool().getName());
+                    MemoryUtil.printMemoryUsage(pr.getPool().getUsage());
+                }
             }
         }
     }
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java	Wed Jul 05 19:37:28 2017 +0200
@@ -30,11 +30,9 @@
  *
  * @author  Mandy Chung
  *
- * @build LowMemoryTest MemoryUtil
- * @run main/othervm/timeout=600 LowMemoryTest
- * @run main/othervm/timeout=600 -XX:+UseConcMarkSweepGC LowMemoryTest
- * @run main/othervm/timeout=600 -XX:+UseParallelGC LowMemoryTest
- * @run main/othervm/timeout=600 -XX:+UseSerialGC LowMemoryTest
+ * @library /lib/testlibrary/
+ * @build LowMemoryTest MemoryUtil RunUtil
+ * @run main/timeout=600 LowMemoryTest
  */
 
 import java.lang.management.*;
@@ -54,6 +52,20 @@
     private static final int NUM_CHUNKS = 2;
     private static long chunkSize;
 
+    /**
+     * Run the test multiple times with different GC versions.
+     * First with default command line specified by the framework.
+     * Then with GC versions specified by the test.
+     */
+    public static void main(String a[]) throws Throwable {
+        final String main = "LowMemoryTest$TestMain";
+        RunUtil.runTestKeepGcOpts(main);
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");
+        RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC");
+    }
+
     private static volatile boolean listenerInvoked = false;
     static class SensorListener implements NotificationListener {
         @Override
@@ -107,77 +119,80 @@
     }
 
     private static long newThreshold;
-    public static void main(String args[]) throws Exception {
-        if (args.length > 0 && args[0].equals("trace")) {
-            trace = true;
-        }
 
-        // Find the Old generation which supports low memory detection
-        ListIterator iter = pools.listIterator();
-        while (iter.hasNext()) {
-            MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
-            if (p.getType() == MemoryType.HEAP &&
-                    p.isUsageThresholdSupported()) {
-                mpool = p;
-                if (trace) {
-                    System.out.println("Selected memory pool for low memory " +
-                        "detection.");
-                    MemoryUtil.printMemoryPool(mpool);
-                }
-                break;
+    private static class TestMain {
+        public static void main(String args[]) throws Exception {
+            if (args.length > 0 && args[0].equals("trace")) {
+                trace = true;
             }
-        }
 
-        TestListener listener = new TestListener();
-        SensorListener l2 = new SensorListener();
-        NotificationEmitter emitter = (NotificationEmitter) mm;
-        emitter.addNotificationListener(listener, null, null);
-        emitter.addNotificationListener(l2, null, null);
-
-        Thread allocator = new AllocatorThread();
-        Thread sweeper = new SweeperThread();
+            // Find the Old generation which supports low memory detection
+            ListIterator iter = pools.listIterator();
+            while (iter.hasNext()) {
+                MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
+                if (p.getType() == MemoryType.HEAP &&
+                    p.isUsageThresholdSupported()) {
+                    mpool = p;
+                    if (trace) {
+                        System.out.println("Selected memory pool for low memory " +
+                            "detection.");
+                        MemoryUtil.printMemoryPool(mpool);
+                    }
+                    break;
+                }
+            }
 
-        // Now set threshold
-        MemoryUsage mu = mpool.getUsage();
-        chunkSize = (mu.getMax() - mu.getUsed()) / 20;
-        newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
+            TestListener listener = new TestListener();
+            SensorListener l2 = new SensorListener();
+            NotificationEmitter emitter = (NotificationEmitter) mm;
+            emitter.addNotificationListener(listener, null, null);
+            emitter.addNotificationListener(l2, null, null);
+
+            Thread allocator = new AllocatorThread();
+            Thread sweeper = new SweeperThread();
 
-        System.out.println("Setting threshold for " + mpool.getName() +
-            " from " + mpool.getUsageThreshold() + " to " + newThreshold +
-            ".  Current used = " + mu.getUsed());
-        mpool.setUsageThreshold(newThreshold);
+            // Now set threshold
+            MemoryUsage mu = mpool.getUsage();
+            chunkSize = (mu.getMax() - mu.getUsed()) / 20;
+            newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
 
-        if (mpool.getUsageThreshold() != newThreshold) {
-            throw new RuntimeException("TEST FAILED: " +
+            System.out.println("Setting threshold for " + mpool.getName() +
+                " from " + mpool.getUsageThreshold() + " to " + newThreshold +
+                ".  Current used = " + mu.getUsed());
+            mpool.setUsageThreshold(newThreshold);
+
+            if (mpool.getUsageThreshold() != newThreshold) {
+                throw new RuntimeException("TEST FAILED: " +
                 "Threshold for Memory pool " + mpool.getName() +
                 "is " + mpool.getUsageThreshold() + " but expected to be" +
                 newThreshold);
-        }
+            }
 
 
-        allocator.start();
-        // Force Allocator start first
-        phaser.arriveAndAwaitAdvance();
-        sweeper.start();
+            allocator.start();
+            // Force Allocator start first
+            phaser.arriveAndAwaitAdvance();
+            sweeper.start();
 
 
-        try {
-            allocator.join();
-            // Wait until AllocatorThread's done
-            phaser.arriveAndAwaitAdvance();
-            sweeper.join();
-        } catch (InterruptedException e) {
-            System.out.println("Unexpected exception:" + e);
-            testFailed = true;
+            try {
+                allocator.join();
+                // Wait until AllocatorThread's done
+                phaser.arriveAndAwaitAdvance();
+                sweeper.join();
+            } catch (InterruptedException e) {
+                System.out.println("Unexpected exception:" + e);
+                testFailed = true;
+            }
+
+            listener.checkResult();
+
+            if (testFailed)
+                throw new RuntimeException("TEST FAILED.");
+
+            System.out.println(RunUtil.successMessage);
+
         }
-
-        listener.checkResult();
-
-        if (testFailed)
-            throw new RuntimeException("TEST FAILED.");
-
-        System.out.println("Test passed.");
-
     }
 
     private static void goSleep(long ms) {
--- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java	Wed Jul 05 19:37:28 2017 +0200
@@ -32,11 +32,9 @@
  * @summary Basic Test for MemoryPool.resetPeakUsage()
  * @author  Mandy Chung
  *
- * @build ResetPeakMemoryUsage MemoryUtil
- * @run main/othervm -XX:+PrintGCDetails -XX:+UseSerialGC -Xms256m -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
- * @run main/othervm -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -Xms256m -Xmn8m ResetPeakMemoryUsage
- * @run main/othervm -XX:+PrintGCDetails -XX:+UseParallelGC -Xms256m -Xmn8m ResetPeakMemoryUsage
- * @run main/othervm -XX:+PrintGCDetails -XX:+UseG1GC -Xms256m -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
+ * @library /lib/testlibrary/
+ * @build ResetPeakMemoryUsage MemoryUtil RunUtil
+ * @run main ResetPeakMemoryUsage
  */
 
 import java.lang.management.*;
@@ -47,24 +45,42 @@
     // make public so that it can't be optimized away easily
     public static Object[] obj;
 
-    public static void main(String[] argv) {
-        List pools = ManagementFactory.getMemoryPoolMXBeans();
-        ListIterator iter = pools.listIterator();
-        boolean found = false;
-        while (iter.hasNext()) {
-            MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
-            // only check heap pools that support usage threshold
-            // this is typically only the old generation space
-            // since the other spaces are expected to get filled up
-            if (p.getType() == MemoryType.HEAP &&
-                p.isUsageThresholdSupported())
-            {
-                found = true;
-                testPool(p);
+    /**
+     * Run the test multiple times with different GC versions.
+     * First with default command line specified by the framework.
+     * Then with all GC versions specified by the test.
+     */
+    public static void main(String a[]) throws Throwable {
+        final String main = "ResetPeakMemoryUsage$TestMain";
+        final String ms = "-Xms256m";
+        final String mn = "-Xmn8m";
+        RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseConcMarkSweepGC");
+        RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseParallelGC");
+        RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1m");
+        RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseSerialGC",
+                "-XX:MarkSweepAlwaysCompactCount=1");
+    }
+
+    private static class TestMain {
+        public static void main(String[] argv) {
+            List pools = ManagementFactory.getMemoryPoolMXBeans();
+            ListIterator iter = pools.listIterator();
+            boolean found = false;
+            while (iter.hasNext()) {
+                MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
+                // only check heap pools that support usage threshold
+                // this is typically only the old generation space
+                // since the other spaces are expected to get filled up
+                if (p.getType() == MemoryType.HEAP &&
+                    p.isUsageThresholdSupported())
+                {
+                    found = true;
+                    testPool(p);
+                }
             }
-        }
-        if (!found) {
-            throw new RuntimeException("No heap pool found");
+            if (!found) {
+                throw new RuntimeException("No heap pool found");
+            }
         }
     }
 
@@ -142,7 +158,7 @@
                 formatSize("previous peak", peak2.getUsed()));
         }
 
-        System.out.println("Test passed.");
+        System.out.println(RunUtil.successMessage);
     }
 
     private static String INDENT = "    ";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/management/MemoryMXBean/RunUtil.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * Utility class for launching a test in a separate JVM.
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.Utils;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JDKToolFinder;
+
+public class RunUtil {
+
+    // Used to mark that the test has passed successfully.
+    public static final String successMessage = "Test passed.";
+
+    public static void runTestClearGcOpts(String main, String... testOpts) throws Throwable {
+        runTest(main, true, testOpts);
+    }
+
+    public static void runTestKeepGcOpts(String main, String... testOpts) throws Throwable {
+        runTest(main, false, testOpts);
+    }
+
+    /**
+     * Runs a test in a separate JVM.
+     * command line like:
+     * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main
+     *
+     * {defaultopts} are the default java options set by the framework.
+     * Default GC options in {defaultopts} may be removed.
+     * This is used when the test specifies its own GC options.
+     *
+     * @param main Name of the main class.
+     * @param clearGcOpts true if the default GC options should be removed.
+     * @param testOpts java options specified by the test.
+     */
+    private static void runTest(String main, boolean clearGcOpts, String... testOpts)
+                throws Throwable {
+        List<String> opts = new ArrayList<>();
+        opts.add(JDKToolFinder.getJDKTool("java"));
+        opts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
+        opts.add("-cp");
+        opts.add(System.getProperty("test.class.path", "test.class.path"));
+        opts.add("-XX:+PrintGCDetails");
+
+        if (clearGcOpts) {
+            opts = Utils.removeGcOpts(opts);
+        }
+        opts.addAll(Arrays.asList(testOpts));
+        opts.add(main);
+
+        OutputAnalyzer output = ProcessTools.executeProcess(opts.toArray(new String[0]));
+        output.shouldHaveExitValue(0);
+        if (output.getStdout().indexOf(successMessage) < 0) {
+            throw new Exception("output missing '" + successMessage + "'");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/SocketOption/OptionsTest.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8036979
+ * @run main/othervm -Xcheck:jni OptionsTest
+ */
+
+import java.net.*;
+import java.util.*;
+
+public class OptionsTest {
+
+    static class Test {
+        Test(SocketOption<?> option, Object testValue) {
+            this.option = option;
+            this.testValue = testValue;
+        }
+        static Test create (SocketOption<?> option, Object testValue) {
+            return new Test(option, testValue);
+        }
+        Object option;
+        Object testValue;
+    };
+
+    // The tests set the option using the new API, read back the set value
+    // which could be diferent, and then use the legacy get API to check
+    // these values are the same
+
+    static Test[] socketTests = new Test[] {
+        Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE),
+        Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
+        Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+        Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+        Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)),
+        Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
+    };
+
+    static Test[] serverSocketTests = new Test[] {
+        Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+        Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE)
+    };
+
+    static Test[] dgSocketTests = new Test[] {
+        Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
+        Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+        Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+        Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
+    };
+
+    static Test[] mcSocketTests = new Test[] {
+        Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()),
+        Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)),
+        Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE)
+    };
+
+    static NetworkInterface getNetworkInterface() {
+        try {
+            Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
+            if (nifs.hasMoreElements()) {
+                return (NetworkInterface)nifs.nextElement();
+            }
+        } catch (Exception e) {
+        }
+        return null;
+    }
+
+    static void doSocketTests() throws Exception {
+        try (
+            ServerSocket srv = new ServerSocket(0);
+            Socket c = new Socket("127.0.0.1", srv.getLocalPort());
+            Socket s = srv.accept();
+        ) {
+            for (int i=0; i<socketTests.length; i++) {
+                Test test = socketTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(Socket.class, c,test.option);
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("S Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+        }
+    }
+
+    static void doDgSocketTests() throws Exception {
+        try (
+            DatagramSocket c = new DatagramSocket(0);
+        ) {
+            for (int i=0; i<dgSocketTests.length; i++) {
+                Test test = dgSocketTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option);
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("DG Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+        }
+    }
+
+    static void doMcSocketTests() throws Exception {
+        try (
+            MulticastSocket c = new MulticastSocket(0);
+        ) {
+            for (int i=0; i<mcSocketTests.length; i++) {
+                Test test = mcSocketTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(MulticastSocket.class, c,test.option);
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("MC Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+        }
+    }
+
+    static void doServerSocketTests() throws Exception {
+        try (
+            ServerSocket c = new ServerSocket(0);
+        ) {
+            for (int i=0; i<serverSocketTests.length; i++) {
+                Test test = serverSocketTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(
+                    ServerSocket.class, c, test.option
+                );
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("SS Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+        }
+    }
+
+    static Object legacyGetOption(
+        Class<?> type, Object s, Object option)
+
+        throws Exception
+    {
+        if (type.equals(Socket.class)) {
+            Socket socket = (Socket)s;
+
+            if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) {
+                return Boolean.valueOf(socket.getKeepAlive());
+            } else if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_LINGER)) {
+                return Integer.valueOf(socket.getSoLinger());
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return Integer.valueOf(socket.getTrafficClass());
+            } else if (option.equals(StandardSocketOptions.TCP_NODELAY)) {
+                return Boolean.valueOf(socket.getTcpNoDelay());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        } else if  (type.equals(ServerSocket.class)) {
+            ServerSocket socket = (ServerSocket)s;
+            if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        } else if  (type.equals(DatagramSocket.class)) {
+            DatagramSocket socket = (DatagramSocket)s;
+
+            if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return Integer.valueOf(socket.getTrafficClass());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+
+        } else if  (type.equals(MulticastSocket.class)) {
+            MulticastSocket socket = (MulticastSocket)s;
+
+            if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return Integer.valueOf(socket.getTrafficClass());
+            } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) {
+                return socket.getNetworkInterface();
+            } else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) {
+                return Integer.valueOf(socket.getTimeToLive());
+            } else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) {
+                return Boolean.valueOf(socket.getLoopbackMode());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        }
+        throw new RuntimeException("unexecpted socket type");
+    }
+
+    public static void main(String args[]) throws Exception {
+        doSocketTests();
+        doServerSocketTests();
+        doDgSocketTests();
+        doMcSocketTests();
+    }
+}
--- a/jdk/test/java/net/URLPermission/nstest/lookup.sh	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/java/net/URLPermission/nstest/lookup.sh	Wed Jul 05 19:37:28 2017 +0200
@@ -26,6 +26,7 @@
 # @library /lib/testlibrary
 # @compile -XDignore.symbol.file=true SimpleNameService.java
 #            LookupTest.java SimpleNameServiceDescriptor.java
+# @build jdk.testlibrary.Utils
 # @run shell/timeout=50 lookup.sh
 #
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Provider/NewInstance.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8039853
+ * @summary Provider.Service.newInstance() does not work with current
+            JDK JGSS Mechanisms
+ */
+
+import java.security.*;
+import java.util.*;
+
+public class NewInstance {
+
+    public static void main(String[] args) throws Exception {
+        for (Provider p : Security.getProviders()) {
+            System.out.println("---------");
+            System.out.println(p.getName() + ":" + p.getInfo());
+            if (p.getName().equals("SunPCSC")) {
+                System.out.println("A smartcard might not be installed. Skip test.");
+                continue;
+            }
+            Set<Provider.Service> set = p.getServices();
+            Iterator<Provider.Service> i = set.iterator();
+
+            while (i.hasNext()) {
+                Provider.Service s = i.next();
+                System.out.println(s.getType() + "." + s.getAlgorithm());
+                try {
+                    s.newInstance(null);
+                } catch (NoSuchAlgorithmException e) {
+                    System.out.println("  check");
+                    Throwable t = e.getCause();
+                    if (!(t instanceof InvalidAlgorithmParameterException)) {
+                        // Some engines require certain parameters to be
+                        // present on creation. Calling newInstance(null) will
+                        // trigger this exception and it's OK.
+                        throw e;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/jpeg/TruncatedImageWarningTest.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug     8032370
+ *
+ * @summary Test verifies that Image I/O jpeg reader correctly handles
+ *          and warns of a truncated image stream.
+ *
+ * @run     main TruncatedImageWarningTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.event.IIOReadWarningListener;
+import javax.imageio.stream.ImageInputStream;
+
+public class TruncatedImageWarningTest implements IIOReadWarningListener {
+
+    private static String fileName = "truncated.jpg";
+    boolean receivedWarning = false;
+
+    public static void main(String[] args) throws IOException {
+
+        String sep = System.getProperty("file.separator");
+        String dir = System.getProperty("test.src", ".");
+        String filePath = dir+sep+fileName;
+        System.out.println("Test file: " + filePath);
+        File f = new File(filePath);
+        ImageInputStream in = ImageIO.createImageInputStream(f);
+        ImageReader reader = ImageIO.getImageReaders(in).next();
+        TruncatedImageWarningTest twt = new TruncatedImageWarningTest();
+        reader.addIIOReadWarningListener(twt);
+        reader.setInput(in);
+        reader.read(0);
+        if (!twt.receivedWarning) {
+            throw new RuntimeException("No expected warning");
+        }
+    }
+
+    public void warningOccurred(ImageReader source, String warning) {
+        System.out.println("Expected warning: " + warning);
+        receivedWarning = true;
+    }
+}
Binary file jdk/test/javax/imageio/plugins/jpeg/truncated.jpg has changed
--- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Wed Jul 05 19:37:28 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4635230 6283345 6303830 6824440 6867348 7094155
+ * @bug 4635230 6283345 6303830 6824440 6867348 7094155 8038184
  * @summary Basic unit tests for generating XML Signatures with JSR 105
  * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
  *     X509KeySelector.java GenerationTests.java
@@ -135,6 +135,7 @@
         test_create_signature_enveloping_sha512_rsa_sha512();
         test_create_signature_reference_dependency();
         test_create_signature_with_attr_in_no_namespace();
+        test_create_signature_with_empty_id();
     }
 
     private static void setup() throws Exception {
@@ -509,6 +510,30 @@
         System.out.println();
     }
 
+    static void test_create_signature_with_empty_id() throws Exception {
+        System.out.println("* Generating signature-with-empty-id.xml");
+
+        // create references
+        List<Reference> refs = Collections.singletonList
+            (fac.newReference("#", sha1));
+
+        // create SignedInfo
+        SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs);
+
+        // create object with empty id
+        Document doc = db.newDocument();
+        XMLObject obj = fac.newXMLObject(Collections.singletonList
+            (new DOMStructure(doc.createTextNode("I am the text."))),
+            "", "text/plain", null);
+
+        // create XMLSignature
+        XMLSignature sig = fac.newXMLSignature(si, rsa,
+                                               Collections.singletonList(obj),
+                                               "signature", null);
+        DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA"), doc);
+        sig.sign(dsc);
+    }
+
     static void test_create_signature() throws Exception {
         System.out.println("* Generating signature.xml");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/net/Sockets/Test.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8032808
+ * @run main/othervm -Xcheck:jni Test
+ * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
+ * @run main/othervm/policy=policy.success -Xcheck:jni Test success
+ */
+
+import java.net.*;
+import java.nio.channels.*;
+import java.util.concurrent.*;
+import jdk.net.*;
+
+public class Test {
+
+    static boolean security;
+    static boolean success;
+
+    interface Runner {
+        public void run() throws Exception;
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        // quick check to see if supportedOptions() working before
+        // creating any sockets and libnet loaded
+
+        Sockets.supportedOptions(Socket.class);
+
+        security = System.getSecurityManager() != null;
+        success = security && args[0].equals("success");
+
+        // Main thing is to check for JNI problems
+        // Doesn't matter if current system does not support the option
+        // and currently setting the option with the loopback interface
+        // doesn't work either
+
+        System.out.println ("Security Manager enabled: " + security);
+        if (security) {
+            System.out.println ("Success expected: " + success);
+        }
+
+        final SocketFlow flowIn = SocketFlow.create()
+            .bandwidth(1000)
+            .priority(SocketFlow.HIGH_PRIORITY);
+
+        ServerSocket ss = new ServerSocket(0);
+        int tcp_port = ss.getLocalPort();
+        final InetAddress loop = InetAddress.getByName("127.0.0.1");
+        final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
+
+        DatagramSocket dg = new DatagramSocket(0);
+        final int udp_port = dg.getLocalPort();
+
+        final Socket s = new Socket("127.0.0.1", tcp_port);
+        final SocketChannel sc = SocketChannel.open();
+        sc.connect (new InetSocketAddress("127.0.0.1", tcp_port));
+
+        doTest(()->{
+            Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+        });
+        doTest(()->{
+            Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
+        });
+        doTest(()->{
+            sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+        });
+        doTest(()->{
+            sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA);
+        });
+        doTest(()->{
+            DatagramSocket dg1 = new DatagramSocket(0);
+            dg1.connect(loop, udp_port);
+            Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+        });
+        doTest(()->{
+            DatagramChannel dg2 = DatagramChannel.open();
+            dg2.bind(new InetSocketAddress(loop, 0));
+            dg2.connect(new InetSocketAddress(loop, udp_port));
+            dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+        });
+        doTest(()->{
+            MulticastSocket mc1 = new MulticastSocket(0);
+            mc1.connect(loop, udp_port);
+            Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+        });
+        doTest(()->{
+            AsynchronousSocketChannel asc = AsynchronousSocketChannel.open();
+            Future<Void> f = asc.connect(loopad);
+            f.get();
+            asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+        });
+    }
+
+    static void doTest(Runner func) throws Exception {
+        try {
+            func.run();
+            if (security && !success) {
+                throw new RuntimeException("Test failed");
+            }
+        } catch (SecurityException e) {
+            if (success) {
+                throw new RuntimeException("Test failed");
+            }
+        } catch (UnsupportedOperationException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/net/Sockets/policy.fail	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,4 @@
+grant {
+    permission java.net.SocketPermission "127.0.0.1", "connect,accept" ;
+    permission java.net.SocketPermission "localhost", "listen" ;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/net/Sockets/policy.success	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,6 @@
+grant {
+    permission java.net.SocketPermission "127.0.0.1", "connect,accept" ;
+    permission java.net.SocketPermission "localhost", "listen" ;
+    permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA";
+    permission jdk.net.NetworkPermission "getOption.SO_FLOW_SLA";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/Basic.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009, 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.
+ *
+ * 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.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.*;
+import java.net.URI;
+import java.io.IOException;
+
+/**
+ *
+ * @test
+ * @bug 8038500
+ * @summary Basic test for zip provider
+ */
+
+public class Basic {
+    public static void main(String[] args) throws Exception {
+        Path zipfile = Paths.get(System.getProperty("test.jdk"),
+                                 "jre/lib/ext/zipfs.jar");
+        // Test: zip should should be returned in provider list
+        boolean found = false;
+
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (provider.getScheme().equalsIgnoreCase("jar")) {
+                found = true;
+                break;
+            }
+        }
+        if (!found)
+            throw new RuntimeException("'jar' provider not installed");
+
+        // Test: FileSystems#newFileSystem(Path)
+        Map<String,?> env = new HashMap<String,Object>();
+        FileSystems.newFileSystem(zipfile, null).close();
+
+        // Test: FileSystems#newFileSystem(URI)
+        URI uri = new URI("jar", zipfile.toUri().toString(), null);
+        FileSystem fs = FileSystems.newFileSystem(uri, env, null);
+
+        // Test: exercise toUri method
+        String expected = uri.toString() + "!/foo";
+        String actual = fs.getPath("/foo").toUri().toString();
+        if (!actual.equals(expected)) {
+            throw new RuntimeException("toUri returned '" + actual +
+                "', expected '" + expected + "'");
+        }
+
+        // Test: exercise directory iterator and retrieval of basic attributes
+        Files.walkFileTree(fs.getPath("/"), new FileTreePrinter());
+
+        // Test: DirectoryStream
+        found = false;
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/"))) {
+            for (Path entry: stream) {
+                found = entry.toString().equals("/META-INF/");
+                if (found) break;
+            }
+        }
+
+        if (!found)
+            throw new RuntimeException("Expected file not found");
+
+        // Test: copy file from zip file to current (scratch) directory
+        Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider");
+        if (Files.exists(source)) {
+            Path target = Paths.get(source.getFileName().toString());
+            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+            try {
+                long s1 = Files.readAttributes(source, BasicFileAttributes.class).size();
+                long s2 = Files.readAttributes(target, BasicFileAttributes.class).size();
+                if (s2 != s1)
+                    throw new RuntimeException("target size != source size");
+            } finally {
+                Files.delete(target);
+            }
+        }
+
+        // Test: FileStore
+        FileStore store = Files.getFileStore(fs.getPath("/"));
+        if (!store.supportsFileAttributeView("basic"))
+            throw new RuntimeException("BasicFileAttributeView should be supported");
+
+        // Test: ClosedFileSystemException
+        fs.close();
+        if (fs.isOpen())
+            throw new RuntimeException("FileSystem should be closed");
+        try {
+            fs.provider().checkAccess(fs.getPath("/missing"), AccessMode.READ);
+        } catch (ClosedFileSystemException x) { }
+    }
+
+    // FileVisitor that pretty prints a file tree
+    static class FileTreePrinter extends SimpleFileVisitor<Path> {
+        private int indent = 0;
+
+        private void indent() {
+            StringBuilder sb = new StringBuilder(indent);
+            for (int i=0; i<indent; i++) sb.append(" ");
+            System.out.print(sb);
+        }
+
+        @Override
+        public FileVisitResult preVisitDirectory(Path dir,
+                                                 BasicFileAttributes attrs)
+        {
+            if (dir.getFileName() != null) {
+                indent();
+                System.out.println(dir.getFileName() + "/");
+                indent++;
+            }
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult visitFile(Path file,
+                                         BasicFileAttributes attrs)
+        {
+            indent();
+            System.out.print(file.getFileName());
+            if (attrs.isRegularFile())
+                System.out.format(" (%d)", attrs.size());
+            System.out.println();
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+            throws IOException
+        {
+            if (exc != null)
+                super.postVisitDirectory(dir, exc);
+            if (dir.getFileName() != null)
+                indent--;
+            return FileVisitResult.CONTINUE;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/Demo.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,693 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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.
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.spi.*;
+import java.nio.file.attribute.*;
+import java.net.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/*
+ * ZipFileSystem usage demo
+ *
+ * java Demo action ZipfileName [...]
+ *
+ * @author Xueming Shen
+ */
+
+public class Demo {
+
+    static enum Action {
+        rename,          // <java Demo rename zipfile src dst>
+                         // rename entry src to dst inside zipfile
+
+        movein,          // <java Demo movein zipfile src dst>
+                         // move an external src file into zipfile
+                         // as entry dst
+
+        moveout,         // <java Demo moveout zipfile src dst>
+                         // move a zipfile entry src out to dst
+
+        copy,            // <java Demo copy zipfile src dst>
+                         // copy entry src to dst inside zipfile
+
+        copyin,          // <java Demo copyin zipfile src dst>
+                         // copy an external src file into zipfile
+                         // as entry dst
+
+        copyin_attrs,    // <java Demo copyin_attrs zipfile src dst>
+                         // copy an external src file into zipfile
+                         // as entry dst, with attributes (timestamp)
+
+        copyout,         // <java Demo copyout zipfile src dst>
+                         // copy zipfile entry src" out to file dst
+
+        copyout_attrs,   // <java Demo copyout_attrs zipfile src dst>
+
+        zzmove,          // <java Demo zzmove zfsrc zfdst path>
+                         // move entry path/dir from zfsrc to zfdst
+
+        zzcopy,          // <java Demo zzcopy zfsrc zfdst path>
+                         // copy path from zipfile zfsrc to zipfile
+                         // zfdst
+
+        attrs,           // <java Demo attrs zipfile path>
+                         // printout the attributes of entry path
+
+        attrsspace,      // <java Demo attrsspace zipfile path>
+                         // printout the storespace attrs of entry path
+
+        setmtime,        // <java Demo setmtime zipfile "MM/dd/yy-HH:mm:ss" path...>
+                         // set the lastModifiedTime of entry path
+
+        setatime,        // <java Demo setatime zipfile "MM/dd/yy-HH:mm:ss" path...>
+        setctime,        // <java Demo setctime zipfile "MM/dd/yy-HH:mm:ss" path...>
+
+        lsdir,           // <java Demo lsdir zipfile dir>
+                         // list dir's direct child files/dirs
+
+        mkdir,           // <java Demo mkdir zipfile dir>
+
+        mkdirs,          // <java Demo mkdirs zipfile dir>
+
+        rmdirs,          // <java Demo rmdirs zipfile dir>
+
+        list,            // <java Demo list zipfile [dir]>
+                         // recursively list all entries of dir
+                         // via DirectoryStream
+
+        tlist,           // <java Demo tlist zipfile [dir]>
+                         // list with buildDirTree=true
+
+        vlist,           // <java Demo vlist zipfile [dir]>
+                         // recursively verbose list all entries of
+                         // dir via DirectoryStream
+
+        walk,            // <java Demo walk zipfile [dir]>
+                         // recursively walk all entries of dir
+                         // via Files.walkFileTree
+
+        twalk,           // <java Demo twalk zipfile [dir]>
+                         // walk with buildDirTree=true
+
+        extract,         // <java Demo extract zipfile file [...]>
+
+        update,          // <java Demo extract zipfile file [...]>
+
+        delete,          // <java Demo delete zipfile file [...]>
+
+        add,             // <java Demo add zipfile file [...]>
+
+        create,          // <java Demo create zipfile file [...]>
+                         // create a new zipfile if it doesn't exit
+                         // and then add the file(s) into it.
+
+        attrs2,          // <java Demo attrs2 zipfile file [...]>
+                         // test different ways to print attrs
+
+        prof,
+    }
+
+    public static void main(String[] args) throws Throwable {
+        FileSystemProvider provider = getZipFSProvider();
+        if (provider == null) {
+            System.err.println("ZIP filesystem provider is not installed");
+            System.exit(1);
+        }
+
+        Action action = Action.valueOf(args[0]);
+        Map<String, Object> env = env = new HashMap<>();
+        if (action == Action.create)
+            env.put("create", "true");
+        try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) {
+            Path path, src, dst;
+            switch (action) {
+            case rename:
+                src = fs.getPath(args[2]);
+                dst = fs.getPath(args[3]);
+                Files.move(src, dst);
+                break;
+            case moveout:
+                src = fs.getPath(args[2]);
+                dst = Paths.get(args[3]);
+                Files.move(src, dst);
+                break;
+            case movein:
+                src = Paths.get(args[2]);
+                dst = fs.getPath(args[3]);
+                Files.move(src, dst);
+                break;
+            case copy:
+                src = fs.getPath(args[2]);
+                dst = fs.getPath(args[3]);
+                Files.copy(src, dst);
+                break;
+            case copyout:
+                src = fs.getPath(args[2]);
+                dst = Paths.get(args[3]);
+                Files.copy(src, dst);
+                break;
+            case copyin:
+                src = Paths.get(args[2]);
+                dst = fs.getPath(args[3]);
+                Files.copy(src, dst);
+                break;
+            case copyin_attrs:
+                src = Paths.get(args[2]);
+                dst = fs.getPath(args[3]);
+                Files.copy(src, dst, COPY_ATTRIBUTES);
+                break;
+            case copyout_attrs:
+                src = fs.getPath(args[2]);
+                dst = Paths.get(args[3]);
+                Files.copy(src, dst, COPY_ATTRIBUTES);
+                break;
+            case zzmove:
+                try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
+                    z2zmove(fs, fs2, args[3]);
+                }
+                break;
+            case zzcopy:
+                try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
+                    z2zcopy(fs, fs2, args[3]);
+                }
+                break;
+            case attrs:
+                for (int i = 2; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    System.out.println(path);
+                    System.out.println(
+                        Files.readAttributes(path, BasicFileAttributes.class).toString());
+                }
+                break;
+            case setmtime:
+                DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
+                Date newDatetime = df.parse(args[2]);
+                for (int i = 3; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    Files.setAttribute(path, "lastModifiedTime",
+                                       FileTime.fromMillis(newDatetime.getTime()));
+                    System.out.println(
+                        Files.readAttributes(path, BasicFileAttributes.class).toString());
+                }
+                break;
+            case setctime:
+                df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
+                newDatetime = df.parse(args[2]);
+                for (int i = 3; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    Files.setAttribute(path, "creationTime",
+                                       FileTime.fromMillis(newDatetime.getTime()));
+                    System.out.println(
+                        Files.readAttributes(path, BasicFileAttributes.class).toString());
+                }
+                break;
+            case setatime:
+                df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
+                newDatetime = df.parse(args[2]);
+                for (int i = 3; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    Files.setAttribute(path, "lastAccessTime",
+                                       FileTime.fromMillis(newDatetime.getTime()));
+                    System.out.println(
+                        Files.readAttributes(path, BasicFileAttributes.class).toString());
+                }
+                break;
+            case attrsspace:
+                path = fs.getPath("/");
+                FileStore fstore = Files.getFileStore(path);
+                System.out.printf("filestore[%s]%n", fstore.name());
+                System.out.printf("    totalSpace: %d%n",
+                                  (Long)fstore.getAttribute("totalSpace"));
+                System.out.printf("   usableSpace: %d%n",
+                                  (Long)fstore.getAttribute("usableSpace"));
+                System.out.printf("  unallocSpace: %d%n",
+                                  (Long)fstore.getAttribute("unallocatedSpace"));
+                break;
+            case list:
+            case tlist:
+                if (args.length < 3)
+                    list(fs.getPath("/"), false);
+                else
+                    list(fs.getPath(args[2]), false);
+                break;
+            case vlist:
+                if (args.length < 3)
+                    list(fs.getPath("/"), true);
+                else
+                    list(fs.getPath(args[2]), true);
+                break;
+            case twalk:
+            case walk:
+                walk(fs.getPath((args.length > 2)? args[2] : "/"));
+                break;
+            case extract:
+                if (args.length == 2) {
+                     extract(fs, "/");
+                } else {
+                    for (int i = 2; i < args.length; i++) {
+                        extract(fs, args[i]);
+                    }
+                }
+                break;
+            case delete:
+                for (int i = 2; i < args.length; i++)
+                    Files.delete(fs.getPath(args[i]));
+                break;
+            case create:
+            case add:
+            case update:
+                for (int i = 2; i < args.length; i++) {
+                    update(fs, args[i]);
+                }
+                break;
+            case lsdir:
+                path = fs.getPath(args[2]);
+                final String fStr = (args.length > 3)?args[3]:"";
+                try (DirectoryStream<Path> ds = Files.newDirectoryStream(path,
+                    new DirectoryStream.Filter<Path>() {
+                        @Override
+                        public boolean accept(Path path) {
+                            return path.toString().contains(fStr);
+                        }
+                    }))
+                {
+                    for (Path p : ds)
+                        System.out.println(p);
+                }
+                break;
+            case mkdir:
+                Files.createDirectory(fs.getPath(args[2]));
+                break;
+            case mkdirs:
+                mkdirs(fs.getPath(args[2]));
+                break;
+            case attrs2:
+                for (int i = 2; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    System.out.printf("%n%s%n", path);
+                    System.out.println("-------(1)---------");
+                    System.out.println(
+                        Files.readAttributes(path, BasicFileAttributes.class).toString());
+                    System.out.println("-------(2)---------");
+                    Map<String, Object> map = Files.readAttributes(path, "zip:*");
+                    for (Map.Entry<String, Object> e : map.entrySet()) {
+                        System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
+                    }
+                    System.out.println("-------(3)---------");
+                    map = Files.readAttributes(path, "size,lastModifiedTime,isDirectory");
+                    for (Map.Entry<String, ?> e : map.entrySet()) {
+                        System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
+                    }
+                }
+                break;
+            case prof:
+                list(fs.getPath("/"), false);
+                while (true) {
+                    Thread.sleep(10000);
+                    //list(fs.getPath("/"), true);
+                    System.out.println("sleeping...");
+                }
+            }
+        } catch (Exception x) {
+            x.printStackTrace();
+        }
+    }
+
+    private static FileSystemProvider getZipFSProvider() {
+        for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
+            if ("jar".equals(provider.getScheme()))
+                return provider;
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unused")
+    /**
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    private static byte[] getBytes(String name) {
+        return name.getBytes();
+    }
+
+    @SuppressWarnings("unused")
+    /**
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    private static String getString(byte[] name) {
+        return new String(name);
+    }
+
+    private static void walk(Path path) throws IOException
+    {
+        Files.walkFileTree(
+            path,
+            new SimpleFileVisitor<Path>() {
+                private int indent = 0;
+                private void indent() {
+                    int n = 0;
+                    while (n++ < indent)
+                        System.out.printf(" ");
+                }
+
+                @Override
+                public FileVisitResult visitFile(Path file,
+                                                 BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("%s%n", file.getFileName().toString());
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir,
+                                                         BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("[%s]%n", dir.toString());
+                    indent += 2;
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir,
+                                                          IOException ioe)
+                {
+                    indent -= 2;
+                    return FileVisitResult.CONTINUE;
+                }
+        });
+    }
+
+    private static void update(FileSystem fs, String path) throws Throwable{
+        Path src = FileSystems.getDefault().getPath(path);
+        if (Files.isDirectory(src)) {
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
+                for (Path child : ds)
+                    update(fs, child.toString());
+            }
+        } else {
+            Path dst = fs.getPath(path);
+            Path parent = dst.getParent();
+            if (parent != null && Files.notExists(parent))
+                mkdirs(parent);
+            Files.copy(src, dst, REPLACE_EXISTING);
+        }
+    }
+
+    private static void extract(FileSystem fs, String path) throws Throwable{
+        Path src = fs.getPath(path);
+        if (Files.isDirectory(src)) {
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
+                for (Path child : ds)
+                    extract(fs, child.toString());
+            }
+        } else {
+            if (path.startsWith("/"))
+                path = path.substring(1);
+            Path dst = FileSystems.getDefault().getPath(path);
+            Path parent = dst.getParent();
+            if (Files.notExists(parent))
+                mkdirs(parent);
+            Files.copy(src, dst, REPLACE_EXISTING);
+        }
+    }
+
+    // use DirectoryStream
+    private static void z2zcopy(FileSystem src, FileSystem dst, String path)
+        throws IOException
+    {
+        Path srcPath = src.getPath(path);
+        Path dstPath = dst.getPath(path);
+
+        if (Files.isDirectory(srcPath)) {
+            if (!Files.exists(dstPath)) {
+                try {
+                    mkdirs(dstPath);
+                } catch (FileAlreadyExistsException x) {}
+            }
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
+                for (Path child : ds) {
+                    z2zcopy(src, dst,
+                            path + (path.endsWith("/")?"":"/") + child.getFileName());
+                }
+            }
+        } else {
+            //System.out.println("copying..." + path);
+            Files.copy(srcPath, dstPath);
+        }
+    }
+
+    // use TreeWalk to move
+    private static void z2zmove(FileSystem src, FileSystem dst, String path)
+        throws IOException
+    {
+        final Path srcPath = src.getPath(path).toAbsolutePath();
+        final Path dstPath = dst.getPath(path).toAbsolutePath();
+
+        Files.walkFileTree(srcPath, new SimpleFileVisitor<Path>() {
+
+            @Override
+            public FileVisitResult visitFile(Path file,
+                                            BasicFileAttributes attrs)
+            {
+                Path dst = srcPath.relativize(file);
+                dst = dstPath.resolve(dst);
+                try {
+                    Path parent = dstPath.getParent();
+                    if (parent != null && Files.notExists(parent))
+                        mkdirs(parent);
+                    Files.move(file, dst);
+                } catch (IOException x) {
+                    x.printStackTrace();
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir,
+                                                     BasicFileAttributes attrs)
+            {
+                Path dst = srcPath.relativize(dir);
+                dst = dstPath.resolve(dst);
+                try {
+
+                    if (Files.notExists(dst))
+                        mkdirs(dst);
+                } catch (IOException x) {
+                    x.printStackTrace();
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir,
+                                                      IOException ioe)
+                throws IOException
+            {
+                try {
+                    Files.delete(dir);
+                } catch (IOException x) {
+                    //x.printStackTrace();
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+
+    }
+
+    private static void mkdirs(Path path) throws IOException {
+        path = path.toAbsolutePath();
+        Path parent = path.getParent();
+        if (parent != null) {
+            if (Files.notExists(parent))
+                mkdirs(parent);
+        }
+        Files.createDirectory(path);
+    }
+
+    @SuppressWarnings("unused")
+    /**
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    private static void rmdirs(Path path) throws IOException {
+        while (path != null && path.getNameCount() != 0) {
+            Files.delete(path);
+            path = path.getParent();
+        }
+    }
+
+    private static void list(Path path, boolean verbose ) throws IOException {
+        if (!"/".equals(path.toString())) {
+           System.out.printf("  %s%n", path.toString());
+           if (verbose)
+                System.out.println(Files.readAttributes(path, BasicFileAttributes.class).toString());
+        }
+        if (Files.notExists(path))
+            return;
+        if (Files.isDirectory(path)) {
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
+                for (Path child : ds)
+                    list(child, verbose);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    /**
+     * Checks that the content of two paths are equal.
+     * Not used in demo, but included for demonstrational purposes.
+     */
+    private static void checkEqual(Path src, Path dst) throws IOException
+    {
+        //System.out.printf("checking <%s> vs <%s>...%n",
+        //                  src.toString(), dst.toString());
+
+        //streams
+        byte[] bufSrc = new byte[8192];
+        byte[] bufDst = new byte[8192];
+        try (InputStream isSrc = Files.newInputStream(src);
+             InputStream isDst = Files.newInputStream(dst))
+        {
+            int nSrc = 0;
+            while ((nSrc = isSrc.read(bufSrc)) != -1) {
+                int nDst = 0;
+                while (nDst < nSrc) {
+                    int n = isDst.read(bufDst, nDst, nSrc - nDst);
+                    if (n == -1) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nDst += n;
+                }
+                while (--nSrc >= 0) {
+                    if (bufSrc[nSrc] != bufDst[nSrc]) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+            }
+        }
+
+        // channels
+
+        try (SeekableByteChannel chSrc = Files.newByteChannel(src);
+             SeekableByteChannel chDst = Files.newByteChannel(dst))
+        {
+            if (chSrc.size() != chDst.size()) {
+                System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
+                                  chSrc.toString(), chSrc.size(),
+                                  chDst.toString(), chDst.size());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+            ByteBuffer bbSrc = ByteBuffer.allocate(8192);
+            ByteBuffer bbDst = ByteBuffer.allocate(8192);
+
+            int nSrc = 0;
+            while ((nSrc = chSrc.read(bbSrc)) != -1) {
+                int nDst = chDst.read(bbDst);
+                if (nSrc != nDst) {
+                    System.out.printf("checking <%s> vs <%s>...%n",
+                                      src.toString(), dst.toString());
+                    throw new RuntimeException("CHECK FAILED!");
+                }
+                while (--nSrc >= 0) {
+                    if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+                bbSrc.flip();
+                bbDst.flip();
+            }
+        } catch (IOException x) {
+            x.printStackTrace();
+        }
+    }
+
+    private static void fchCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        try (FileChannel srcFc = src.getFileSystem().provider().newFileChannel(src, read);
+             FileChannel dstFc = dst.getFileSystem().provider().newFileChannel(dst, openwrite))
+        {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcFc.read(bb) >= 0) {
+                bb.flip();
+                dstFc.write(bb);
+                bb.clear();
+            }
+        }
+    }
+
+    private static void chCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
+             SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
+        {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcCh.read(bb) >= 0) {
+                bb.flip();
+                dstCh.write(bb);
+                bb.clear();
+            }
+        }
+    }
+
+    private static void streamCopy(Path src, Path dst) throws IOException
+    {
+        byte[] buf = new byte[8192];
+        try (InputStream isSrc = Files.newInputStream(src);
+             OutputStream osDst = Files.newOutputStream(dst))
+        {
+            int n = 0;
+            while ((n = isSrc.read(buf)) != -1) {
+                osDst.write(buf, 0, n);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/PathOps.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2009, 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.
+ *
+ * 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.
+ */
+
+import java.nio.file.*;
+import java.net.*;
+import java.util.*;
+import java.io.IOException;
+
+/**
+ *
+ * @test
+ * @bug 8038500
+ * @summary Tests path operations for zip provider.
+ */
+
+public class PathOps {
+
+    static final java.io.PrintStream out = System.out;
+    static FileSystem fs;
+
+    private String input;
+    private Path path;
+    private Exception exc;
+
+    private PathOps(String s) {
+        out.println();
+        input = s;
+        try {
+            path = fs.getPath(s);
+            out.format("%s -> %s", s, path);
+        } catch (Exception x) {
+            exc = x;
+            out.format("%s -> %s", s, x);
+        }
+        out.println();
+    }
+
+    Path path() {
+        return path;
+    }
+
+    void fail() {
+        throw new RuntimeException("PathOps failed");
+    }
+
+    void checkPath() {
+        if (path == null) {
+            throw new InternalError("path is null");
+        }
+    }
+
+    void check(Object result, String expected) {
+        out.format("\tExpected: %s\n", expected);
+        out.format("\tActual: %s\n",  result);
+        if (result == null) {
+            if (expected == null) return;
+        } else {
+            // compare string representations
+            if (expected != null && result.toString().equals(expected.toString()))
+                return;
+        }
+        fail();
+    }
+
+    void check(Object result, boolean expected) {
+        check(result, Boolean.toString(expected));
+    }
+
+    PathOps root(String expected) {
+        out.println("check root");
+        checkPath();
+        check(path.getRoot(), expected);
+        return this;
+    }
+
+    PathOps parent(String expected) {
+        out.println("check parent");
+        checkPath();
+        check(path.getParent(), expected);
+        return this;
+    }
+
+    PathOps name(String expected) {
+        out.println("check name");
+        checkPath();
+        check(path.getFileName(), expected);
+        return this;
+    }
+
+    PathOps element(int index, String expected) {
+        out.format("check element %d\n", index);
+        checkPath();
+        check(path.getName(index), expected);
+        return this;
+    }
+
+    PathOps subpath(int startIndex, int endIndex, String expected) {
+        out.format("test subpath(%d,%d)\n", startIndex, endIndex);
+        checkPath();
+        check(path.subpath(startIndex, endIndex), expected);
+        return this;
+    }
+
+    PathOps starts(String prefix) {
+        out.format("test startsWith with %s\n", prefix);
+        checkPath();
+        Path s = fs.getPath(prefix);
+        check(path.startsWith(s), true);
+        return this;
+    }
+
+    PathOps notStarts(String prefix) {
+        out.format("test not startsWith with %s\n", prefix);
+        checkPath();
+        Path s = fs.getPath(prefix);
+        check(path.startsWith(s), false);
+        return this;
+    }
+
+    PathOps ends(String suffix) {
+        out.format("test endsWith %s\n", suffix);
+        checkPath();
+        Path s = fs.getPath(suffix);
+        check(path.endsWith(s), true);
+        return this;
+    }
+
+    PathOps notEnds(String suffix) {
+        out.format("test not endsWith %s\n", suffix);
+        checkPath();
+        Path s = fs.getPath(suffix);
+        check(path.endsWith(s), false);
+        return this;
+    }
+
+    PathOps absolute() {
+        out.println("check path is absolute");
+        checkPath();
+        check(path.isAbsolute(), true);
+        return this;
+    }
+
+    PathOps notAbsolute() {
+        out.println("check path is not absolute");
+        checkPath();
+        check(path.isAbsolute(), false);
+        return this;
+    }
+
+    PathOps resolve(String other, String expected) {
+        out.format("test resolve %s\n", other);
+        checkPath();
+        check(path.resolve(other), expected);
+        return this;
+    }
+
+    PathOps relativize(String other, String expected) {
+        out.format("test relativize %s\n", other);
+        checkPath();
+        Path that = fs.getPath(other);
+        check(path.relativize(that), expected);
+        return this;
+    }
+
+    PathOps normalize(String expected) {
+        out.println("check normalized path");
+        checkPath();
+        check(path.normalize(), expected);
+        return this;
+    }
+
+    PathOps string(String expected) {
+        out.println("check string representation");
+        checkPath();
+        check(path, expected);
+        return this;
+    }
+
+    PathOps isSameFile(String target) {
+        try {
+            out.println("check two paths are same");
+            checkPath();
+            check(Files.isSameFile(path, test(target).path()), true);
+        } catch (IOException ioe) {
+            fail();
+        }
+        return this;
+    }
+
+    PathOps invalid() {
+        if (!(exc instanceof InvalidPathException)) {
+            out.println("InvalidPathException not thrown as expected");
+            fail();
+        }
+        return this;
+    }
+
+    static PathOps test(String s) {
+        return new PathOps(s);
+    }
+
+    // -- PathOpss --
+
+    static void header(String s) {
+        out.println();
+        out.println();
+        out.println("-- " + s + " --");
+    }
+
+    static void doPathOpTests() {
+        header("Path operations");
+
+        // all components
+        test("/a/b/c")
+            .root("/")
+            .parent("/a/b")
+            .name("c");
+
+        // root component only
+        test("/")
+            .root("/")
+            .parent(null)
+            .name(null);
+
+        // no root component
+        test("a/b")
+            .root(null)
+            .parent("a")
+            .name("b");
+
+        // name component only
+        test("foo")
+            .root(null)
+            .parent(null)
+            .name("foo");
+
+        // startsWith
+        test("")
+            .starts("")
+            .notStarts("/");
+        test("/")
+            .starts("/")
+            .notStarts("/foo");
+        test("/foo")
+            .starts("/")
+            .starts("/foo")
+            .notStarts("/f")
+            .notStarts("");
+        test("/foo/bar")
+            .starts("/")
+            .starts("/foo")
+            .starts("/foo/")
+            .starts("/foo/bar")
+            .notStarts("/f")
+            .notStarts("foo")
+            .notStarts("foo/bar")
+            .notStarts("");
+        test("foo")
+            .starts("foo")
+            .notStarts("f");
+        test("foo/bar")
+            .starts("foo")
+            .starts("foo/")
+            .starts("foo/bar")
+            .notStarts("f")
+            .notStarts("/foo")
+            .notStarts("/foo/bar");
+
+        // endsWith
+        test("")
+            .ends("")
+            .notEnds("/");
+        test("/")
+            .ends("/")
+            .notEnds("foo")
+            .notEnds("/foo");
+        test("/foo")
+            .ends("foo")
+            .ends("/foo")
+            .notEnds("/");
+        test("/foo/bar")
+            .ends("bar")
+            .ends("foo/bar")
+            .ends("foo/bar/")
+            .ends("/foo/bar")
+            .notEnds("/bar");
+        test("/foo/bar/")
+            .ends("bar")
+            .ends("foo/bar")
+            .ends("foo/bar/")
+            .ends("/foo/bar")
+            .notEnds("/bar");
+        test("foo")
+            .ends("foo");
+        test("foo/bar")
+            .ends("bar")
+            .ends("bar/")
+            .ends("foo/bar/")
+            .ends("foo/bar");
+
+
+        // elements
+        test("a/b/c")
+            .element(0,"a")
+            .element(1,"b")
+            .element(2,"c");
+
+        // isAbsolute
+        test("/")
+            .absolute();
+        test("/tmp")
+            .absolute();
+        test("tmp")
+            .notAbsolute();
+        test("")
+            .notAbsolute();
+
+        // resolve
+        test("/tmp")
+            .resolve("foo", "/tmp/foo")
+            .resolve("/foo", "/foo");
+        test("tmp")
+            .resolve("foo", "tmp/foo")
+            .resolve("/foo", "/foo");
+
+        // relativize
+        test("/a/b/c")
+            .relativize("/a/b/c", "")
+            .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/x", "../../x");
+
+        // normalize
+        test("/")
+            .normalize("/");
+        test("foo")
+            .normalize("foo");
+        test("/foo")
+            .normalize("/foo");
+        test(".")
+            .normalize("");
+        test("..")
+            .normalize("..");
+        test("/..")
+            .normalize("/");
+        test("/../..")
+            .normalize("/");
+        test("foo/.")
+            .normalize("foo");
+        test("./foo")
+            .normalize("foo");
+        test("foo/..")
+            .normalize("");
+        test("../foo")
+            .normalize("../foo");
+        test("../../foo")
+            .normalize("../../foo");
+        test("foo/bar/..")
+            .normalize("foo");
+        test("foo/bar/gus/../..")
+            .normalize("foo");
+        test("/foo/bar/gus/../..")
+            .normalize("/foo");
+        test("/./.")
+            .normalize("/");
+        test("/.")
+            .normalize("/");
+        test("/./abc")
+            .normalize("/abc");
+        // invalid
+        test("foo\u0000bar")
+            .invalid();
+        test("\u0000foo")
+            .invalid();
+        test("bar\u0000")
+            .invalid();
+        test("//foo\u0000bar")
+            .invalid();
+        test("//\u0000foo")
+            .invalid();
+        test("//bar\u0000")
+            .invalid();
+
+        // normalization
+        test("//foo//bar")
+            .string("/foo/bar")
+            .root("/")
+            .parent("/foo")
+            .name("bar");
+
+        // isSameFile
+        test("/fileDoesNotExist")
+            .isSameFile("/fileDoesNotExist");
+    }
+
+    static void npes() {
+        header("NullPointerException");
+
+        Path path = fs.getPath("foo");
+
+        try {
+            path.resolve((String)null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.relativize(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.compareTo(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.startsWith((Path)null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.endsWith((Path)null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+    }
+
+    public static void main(String[] args) throws Throwable {
+        Path zipfile = Paths.get(System.getProperty("test.jdk"),
+                                 "jre/lib/ext/zipfs.jar");
+        fs = FileSystems.newFileSystem(zipfile, null);
+        npes();
+        doPathOpTests();
+        fs.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/* @test
+   @bug 7156873
+   @summary ZipFileSystem regression tests
+ */
+
+
+import java.net.URI;
+import java.nio.file.*;
+import java.util.Map;
+import java.util.HashMap;
+
+public class ZFSTests {
+
+    public static void main(String[] args) throws Throwable {
+        test7156873();
+    }
+
+    static void test7156873() throws Throwable {
+        String DIRWITHSPACE = "testdir with spaces";
+        Path dir = Paths.get(DIRWITHSPACE);
+        Path path = Paths.get(DIRWITHSPACE, "file.zip");
+        try {
+            Files.createDirectory(dir);
+            URI uri = URI.create("jar:" + path.toUri());
+            Map<String, Object> env = new HashMap<String, Object>();
+            env.put("create", "true");
+            try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {}
+        } finally {
+            Files.deleteIfExists(path);
+            Files.deleteIfExists(dir);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2010, 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.
+ *
+ * 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.
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.spi.*;
+import java.nio.file.attribute.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.*;
+
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/*
+ * Tests various zipfs operations.
+ *
+ * @test
+ * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
+ *      7157656 8002390 7012868 7012856 8015728 8038500
+ * @summary Test Zip filesystem provider
+ */
+
+public class ZipFSTester {
+
+    public static void main(String[] args) throws Throwable {
+        try (FileSystem fs = newZipFileSystem(
+                 Paths.get(System.getProperty("test.jdk"), "jre/lib/ext/zipfs.jar"),
+                 new HashMap<String, Object>()))
+        {
+            test0(fs);
+            test1(fs);
+            test2(fs);   // more tests
+        }
+        testTime(Paths.get(System.getProperty("test.jdk"), "jre/lib/ext/zipfs.jar"));
+    }
+
+    static void test0(FileSystem fs)
+        throws Exception
+    {
+        List<String> list = new LinkedList<>();
+        try (ZipFile zf = new ZipFile(fs.toString())) {
+            Enumeration<? extends ZipEntry> zes = zf.entries();
+            while (zes.hasMoreElements()) {
+                list.add(zes.nextElement().getName());
+            }
+            for (String pname : list) {
+                Path path = fs.getPath(pname);
+                if (!Files.exists(path))
+                    throw new RuntimeException("path existence check failed!");
+                while ((path = path.getParent()) != null) {
+                    if (!Files.exists(path))
+                        throw new RuntimeException("parent existence check failed!");
+                }
+            }
+        }
+    }
+
+    static void test1(FileSystem fs0)
+        throws Exception
+    {
+        Random rdm = new Random();
+        // clone a fs and test on it
+        Path tmpfsPath = getTempPath();
+        Map<String, Object> env = new HashMap<String, Object>();
+        env.put("create", "true");
+        try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) {
+            z2zcopy(fs0, copy, "/", 0);
+        }
+
+        try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) {
+
+            FileSystemProvider provider = fs.provider();
+            // newFileSystem(path...) should not throw exception
+            try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap<String, Object>())){}
+            try (FileSystem fsUri = provider.newFileSystem(
+                     new URI("jar", tmpfsPath.toUri().toString(), null),
+                     new HashMap<String, Object>()))
+            {
+              throw new RuntimeException("newFileSystem(uri...) does not throw exception");
+            } catch (FileSystemAlreadyExistsException fsaee) {}
+
+            // prepare a src
+            Path src = getTempPath();
+            String tmpName = src.toString();
+            OutputStream os = Files.newOutputStream(src);
+            byte[] bits = new byte[12345];
+            rdm.nextBytes(bits);
+            os.write(bits);
+            os.close();
+
+            try {
+                provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(),
+                                       new HashMap<String, Object>());
+                throw new RuntimeException("newFileSystem() opens a directory as zipfs");
+            } catch (UnsupportedOperationException uoe) {}
+
+            try {
+                provider.newFileSystem(src, new HashMap<String, Object>());
+                throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs");
+            } catch (UnsupportedOperationException uoe) {}
+
+
+            // copyin
+            Path dst = getPathWithParents(fs, tmpName);
+            Files.copy(src, dst);
+            checkEqual(src, dst);
+
+            // copy
+            Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
+                                           "/efg" + rdm.nextInt(100) + "/foo.class");
+            Files.copy(dst, dst2);
+            //dst.moveTo(dst2);
+            checkEqual(src, dst2);
+
+            // delete
+            Files.delete(dst);
+            if (Files.exists(dst))
+                throw new RuntimeException("Failed!");
+
+            // moveout
+            Path dst3 = Paths.get(tmpName + "_Tmp");
+            Files.move(dst2, dst3);
+            checkEqual(src, dst3);
+            if (Files.exists(dst2))
+                throw new RuntimeException("Failed!");
+
+            // copyback + move
+            Files.copy(dst3, dst);
+            Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
+            Files.move(dst, dst4);
+            checkEqual(src, dst4);
+
+            // delete
+            Files.delete(dst4);
+            if (Files.exists(dst4))
+                throw new RuntimeException("Failed!");
+            Files.delete(dst3);
+            if (Files.exists(dst3))
+                throw new RuntimeException("Failed!");
+
+            // move (existing entry)
+            Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
+            if (Files.exists(dst5)) {
+                Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
+                Files.move(dst5, dst6);
+                walk(fs.getPath("/"));
+            }
+
+            // newInputStream on dir
+            Path parent = dst2.getParent();
+            try {
+                Files.newInputStream(parent);
+                throw new RuntimeException("Failed");
+            } catch (FileSystemException e) {
+                e.printStackTrace();    // expected fse
+            }
+
+            // rmdirs
+            try {
+                rmdirs(parent);
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+
+            // newFileChannel() copy in, out and verify via fch
+            fchCopy(src, dst);    // in
+            checkEqual(src, dst);
+            Path tmp = Paths.get(tmpName + "_Tmp");
+            fchCopy(dst, tmp);   //  out
+            checkEqual(src, tmp);
+            Files.delete(tmp);
+
+            // test channels
+            channel(fs, dst);
+            Files.delete(dst);
+            Files.delete(src);
+        } finally {
+            if (Files.exists(tmpfsPath))
+                Files.delete(tmpfsPath);
+        }
+    }
+
+    static void test2(FileSystem fs) throws Exception {
+
+        Path fs1Path = getTempPath();
+        Path fs2Path = getTempPath();
+        Path fs3Path = getTempPath();
+
+        // create a new filesystem, copy everything from fs
+        Map<String, Object> env = new HashMap<String, Object>();
+        env.put("create", "true");
+        FileSystem fs0 = newZipFileSystem(fs1Path, env);
+
+        final FileSystem fs2 = newZipFileSystem(fs2Path, env);
+        final FileSystem fs3 = newZipFileSystem(fs3Path, env);
+
+        System.out.println("copy src: fs -> fs0...");
+        z2zcopy(fs, fs0, "/", 0);   // copy fs -> fs1
+        fs0.close();                // dump to file
+
+        System.out.println("open fs0 as fs1");
+        env = new HashMap<String, Object>();
+        final FileSystem fs1 = newZipFileSystem(fs1Path, env);
+
+        System.out.println("listing...");
+        final ArrayList<String> files = new ArrayList<>();
+        final ArrayList<String> dirs = new ArrayList<>();
+        list(fs1.getPath("/"), files, dirs);
+
+        Thread t0 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(dirs);
+                Collections.shuffle(list);
+                for (String path : list) {
+                    try {
+                        z2zcopy(fs1, fs2, path, 0);
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+
+        });
+
+        Thread t1 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(dirs);
+                Collections.shuffle(list);
+                for (String path : list) {
+                    try {
+                        z2zcopy(fs1, fs2, path, 1);
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+
+        });
+
+        Thread t2 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(dirs);
+                Collections.shuffle(list);
+                for (String path : list) {
+                    try {
+                        z2zcopy(fs1, fs2, path, 2);
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+
+        });
+
+        Thread t3 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(files);
+                Collections.shuffle(list);
+                while (!list.isEmpty()) {
+                    Iterator<String> itr = list.iterator();
+                    while (itr.hasNext()) {
+                        String path = itr.next();
+                        try {
+                            if (Files.exists(fs2.getPath(path))) {
+                                z2zmove(fs2, fs3, path);
+                                itr.remove();
+                            }
+                        } catch (FileAlreadyExistsException x){
+                            itr.remove();
+                        } catch (Exception x) {
+                            x.printStackTrace();
+                        }
+                    }
+                }
+            }
+
+        });
+
+        System.out.println("copying/removing...");
+        t0.start(); t1.start(); t2.start(); t3.start();
+        t0.join(); t1.join(); t2.join(); t3.join();
+
+        System.out.println("closing: fs1, fs2");
+        fs1.close();
+        fs2.close();
+
+        int failed = 0;
+        System.out.println("checkEqual: fs vs fs3");
+        for (String path : files) {
+            try {
+                checkEqual(fs.getPath(path), fs3.getPath(path));
+            } catch (IOException x) {
+                //x.printStackTrace();
+                failed++;
+            }
+        }
+        System.out.println("closing: fs3");
+        fs3.close();
+
+        System.out.println("opening: fs3 as fs4");
+        FileSystem fs4 = newZipFileSystem(fs3Path, env);
+
+
+        ArrayList<String> files2 = new ArrayList<>();
+        ArrayList<String> dirs2 = new ArrayList<>();
+        list(fs4.getPath("/"), files2, dirs2);
+
+        System.out.println("checkEqual: fs vs fs4");
+        for (String path : files2) {
+            checkEqual(fs.getPath(path), fs4.getPath(path));
+        }
+        System.out.println("walking: fs4");
+        walk(fs4.getPath("/"));
+        System.out.println("closing: fs4");
+        fs4.close();
+        System.out.printf("failed=%d%n", failed);
+
+        Files.delete(fs1Path);
+        Files.delete(fs2Path);
+        Files.delete(fs3Path);
+    }
+
+    // test file stamp
+    static void testTime(Path src) throws Exception {
+        BasicFileAttributes attrs = Files
+                        .getFileAttributeView(src, BasicFileAttributeView.class)
+                        .readAttributes();
+        // create a new filesystem, copy this file into it
+        Map<String, Object> env = new HashMap<String, Object>();
+        env.put("create", "true");
+        Path fsPath = getTempPath();
+        FileSystem fs = newZipFileSystem(fsPath, env);
+
+        System.out.println("test copy with timestamps...");
+        // copyin
+        Path dst = getPathWithParents(fs, "me");
+        Files.copy(src, dst, COPY_ATTRIBUTES);
+        checkEqual(src, dst);
+        System.out.println("mtime: " + attrs.lastModifiedTime());
+        System.out.println("ctime: " + attrs.creationTime());
+        System.out.println("atime: " + attrs.lastAccessTime());
+        System.out.println(" ==============>");
+        BasicFileAttributes dstAttrs = Files
+                        .getFileAttributeView(dst, BasicFileAttributeView.class)
+                        .readAttributes();
+        System.out.println("mtime: " + dstAttrs.lastModifiedTime());
+        System.out.println("ctime: " + dstAttrs.creationTime());
+        System.out.println("atime: " + dstAttrs.lastAccessTime());
+
+        // 1-second granularity
+        if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) !=
+            dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) ||
+            attrs.lastAccessTime().to(TimeUnit.SECONDS) !=
+            dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) ||
+            attrs.creationTime().to(TimeUnit.SECONDS) !=
+            dstAttrs.creationTime().to(TimeUnit.SECONDS)) {
+            throw new RuntimeException("Timestamp Copy Failed!");
+        }
+        Files.delete(fsPath);
+    }
+
+    private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
+        throws Exception
+    {
+        return FileSystems.newFileSystem(
+            new URI("jar", path.toUri().toString(), null), env, null);
+    }
+
+    private static Path getTempPath() throws IOException
+    {
+        File tmp = File.createTempFile("testzipfs_", "zip");
+        tmp.delete();    // we need a clean path, no file
+        return tmp.toPath();
+    }
+
+    private static void list(Path path, List<String> files, List<String> dirs )
+        throws IOException
+    {
+        if (Files.isDirectory(path)) {
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
+                for (Path child : ds)
+                    list(child, files, dirs);
+            }
+            dirs.add(path.toString());
+        } else {
+            files.add(path.toString());
+        }
+    }
+
+    private static void z2zcopy(FileSystem src, FileSystem dst, String path,
+                                int method)
+        throws IOException
+    {
+        Path srcPath = src.getPath(path);
+        Path dstPath = dst.getPath(path);
+
+        if (Files.isDirectory(srcPath)) {
+            if (!Files.exists(dstPath)) {
+                try {
+                    mkdirs(dstPath);
+                } catch (FileAlreadyExistsException x) {}
+            }
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
+                for (Path child : ds) {
+                    z2zcopy(src, dst,
+                           path + (path.endsWith("/")?"":"/") + child.getFileName(),
+                           method);
+                }
+            }
+        } else {
+            try {
+                if (Files.exists(dstPath))
+                    return;
+                switch (method) {
+                case 0:
+                    Files.copy(srcPath, dstPath);
+                    break;
+                case 1:
+                    chCopy(srcPath, dstPath);
+                    break;
+                case 2:
+                    //fchCopy(srcPath, dstPath);
+                    streamCopy(srcPath, dstPath);
+                    break;
+                }
+            } catch (FileAlreadyExistsException x) {}
+        }
+    }
+
+    private static void z2zmove(FileSystem src, FileSystem dst, String path)
+        throws IOException
+    {
+        Path srcPath = src.getPath(path);
+        Path dstPath = dst.getPath(path);
+
+        if (Files.isDirectory(srcPath)) {
+            if (!Files.exists(dstPath))
+                mkdirs(dstPath);
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
+                for (Path child : ds) {
+                    z2zmove(src, dst,
+                            path + (path.endsWith("/")?"":"/") + child.getFileName());
+                }
+            }
+        } else {
+            //System.out.println("moving..." + path);
+            Path parent = dstPath.getParent();
+            if (parent != null && Files.notExists(parent))
+                mkdirs(parent);
+            Files.move(srcPath, dstPath);
+        }
+    }
+
+    private static void walk(Path path) throws IOException
+    {
+        Files.walkFileTree(
+            path,
+            new SimpleFileVisitor<Path>() {
+                private int indent = 0;
+                private void indent() {
+                    int n = 0;
+                    while (n++ < indent)
+                        System.out.printf(" ");
+                }
+
+                @Override
+                public FileVisitResult visitFile(Path file,
+                                                 BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("%s%n", file.getFileName().toString());
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir,
+                                                         BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("[%s]%n", dir.toString());
+                    indent += 2;
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir,
+                                                          IOException ioe)
+                    throws IOException
+                {
+                    indent -= 2;
+                    return FileVisitResult.CONTINUE;
+                }
+        });
+    }
+
+    private static void mkdirs(Path path) throws IOException {
+        if (Files.exists(path))
+            return;
+        path = path.toAbsolutePath();
+        Path parent = path.getParent();
+        if (parent != null) {
+            if (Files.notExists(parent))
+                mkdirs(parent);
+        }
+        Files.createDirectory(path);
+    }
+
+    private static void rmdirs(Path path) throws IOException {
+        while (path != null && path.getNameCount() != 0) {
+            Files.delete(path);
+            path = path.getParent();
+        }
+    }
+
+    // check the content of two paths are equal
+    private static void checkEqual(Path src, Path dst) throws IOException
+    {
+        //System.out.printf("checking <%s> vs <%s>...%n",
+        //                  src.toString(), dst.toString());
+
+        //streams
+        byte[] bufSrc = new byte[8192];
+        byte[] bufDst = new byte[8192];
+        try (InputStream isSrc = Files.newInputStream(src);
+             InputStream isDst = Files.newInputStream(dst))
+        {
+            int nSrc = 0;
+            while ((nSrc = isSrc.read(bufSrc)) != -1) {
+                int nDst = 0;
+                while (nDst < nSrc) {
+                    int n = isDst.read(bufDst, nDst, nSrc - nDst);
+                    if (n == -1) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nDst += n;
+                }
+                while (--nSrc >= 0) {
+                    if (bufSrc[nSrc] != bufDst[nSrc]) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+            }
+        }
+
+        // channels
+        try (SeekableByteChannel chSrc = Files.newByteChannel(src);
+             SeekableByteChannel chDst = Files.newByteChannel(dst))
+        {
+            if (chSrc.size() != chDst.size()) {
+                System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
+                                  chSrc.toString(), chSrc.size(),
+                                  chDst.toString(), chDst.size());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+            ByteBuffer bbSrc = ByteBuffer.allocate(8192);
+            ByteBuffer bbDst = ByteBuffer.allocate(8192);
+
+            int nSrc = 0;
+            while ((nSrc = chSrc.read(bbSrc)) != -1) {
+                int nDst = chDst.read(bbDst);
+                if (nSrc != nDst) {
+                    System.out.printf("checking <%s> vs <%s>...%n",
+                                      src.toString(), dst.toString());
+                    throw new RuntimeException("CHECK FAILED!");
+                }
+                while (--nSrc >= 0) {
+                    if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+                bbSrc.flip();
+                bbDst.flip();
+            }
+
+            // Check if source read position is at the end
+            if (chSrc.position() != chSrc.size()) {
+                System.out.printf("src[%s]: size=%d, position=%d%n",
+                                  chSrc.toString(), chSrc.size(), chSrc.position());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+
+            // Check if destination read position is at the end
+            if (chDst.position() != chDst.size()) {
+                System.out.printf("dst[%s]: size=%d, position=%d%n",
+                                  chDst.toString(), chDst.size(), chDst.position());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+        } catch (IOException x) {
+            x.printStackTrace();
+        }
+    }
+
+    private static void fchCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        try (FileChannel srcFc = src.getFileSystem()
+                                    .provider()
+                                    .newFileChannel(src, read);
+             FileChannel dstFc = dst.getFileSystem()
+                                    .provider()
+                                    .newFileChannel(dst, openwrite))
+        {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcFc.read(bb) >= 0) {
+                bb.flip();
+                dstFc.write(bb);
+                bb.clear();
+            }
+        }
+    }
+
+    private static void chCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
+             SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
+        {
+
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcCh.read(bb) >= 0) {
+                bb.flip();
+                dstCh.write(bb);
+                bb.clear();
+            }
+
+            // Check if source read position is at the end
+            if (srcCh.position() != srcCh.size()) {
+                System.out.printf("src[%s]: size=%d, position=%d%n",
+                                  srcCh.toString(), srcCh.size(), srcCh.position());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+
+            // Check if destination write position is at the end
+            if (dstCh.position() != dstCh.size()) {
+                System.out.printf("dst[%s]: size=%d, position=%d%n",
+                                  dstCh.toString(), dstCh.size(), dstCh.position());
+                throw new RuntimeException("CHECK FAILED!");
+            }
+        }
+    }
+
+    private static void streamCopy(Path src, Path dst) throws IOException
+    {
+        byte[] buf = new byte[8192];
+        try (InputStream isSrc = Files.newInputStream(src);
+             OutputStream osDst = Files.newOutputStream(dst))
+        {
+            int n = 0;
+            while ((n = isSrc.read(buf)) != -1) {
+                osDst.write(buf, 0, n);
+            }
+        }
+    }
+
+    static void channel(FileSystem fs, Path path)
+        throws Exception
+    {
+        System.out.println("test ByteChannel...");
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        int n = 0;
+        ByteBuffer bb = null;
+        ByteBuffer bb2 = null;
+        int N = 120;
+
+        try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
+            System.out.printf("   sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
+            if (sbc.position() != 0) {
+                throw new RuntimeException("CHECK FAILED!");
+            }
+
+            bb = ByteBuffer.allocate((int)sbc.size());
+            n = sbc.read(bb);
+            System.out.printf("   sbc[1]: read=%d, pos=%d, size=%d%n",
+                              n, sbc.position(), sbc.size());
+            if (sbc.position() != sbc.size()) {
+                throw new RuntimeException("CHECK FAILED!");
+            }
+            bb2 = ByteBuffer.allocate((int)sbc.size());
+        }
+
+        // sbc.position(pos) is not supported in current version
+        // try the FileChannel
+        try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) {
+            sbc.position(N);
+            System.out.printf("   sbc[2]: pos=%d, size=%d%n",
+                              sbc.position(), sbc.size());
+            if (sbc.position() != N) {
+                throw new RuntimeException("CHECK FAILED!");
+            }
+            bb2.limit(100);
+            n = sbc.read(bb2);
+            System.out.printf("   sbc[3]: read=%d, pos=%d, size=%d%n",
+                              n, sbc.position(), sbc.size());
+            if (n < 0 || sbc.position() != (N + n)) {
+                throw new RuntimeException("CHECK FAILED!");
+            }
+            System.out.printf("   sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
+                              N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
+        }
+    }
+
+    // create parents if does not exist
+    static Path getPathWithParents(FileSystem fs, String name)
+        throws Exception
+    {
+        Path path = fs.getPath(name);
+        Path parent = path.getParent();
+        if (parent != null && Files.notExists(parent))
+            mkdirs(parent);
+        return path;
+    }
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java	Wed Jul 05 19:37:28 2017 +0200
@@ -120,6 +120,26 @@
     }
 
     /**
+     * Removes any options specifying which GC to use, for example "-XX:+UseG1GC".
+     * Removes any options matching: -XX:(+/-)Use*GC
+     * Used when a test need to set its own GC version. Then any
+     * GC specified by the framework must first be removed.
+     * @return A copy of given opts with all GC options removed.
+     */
+    private static final Pattern useGcPattern = Pattern.compile("\\-XX\\:[\\+\\-]Use.+GC");
+    public static List<String> removeGcOpts(List<String> opts) {
+        List<String> optsWithoutGC = new ArrayList<String>();
+        for (String opt : opts) {
+            if (useGcPattern.matcher(opt).matches()) {
+                System.out.println("removeGcOpts: removed " + opt);
+            } else {
+                optsWithoutGC.add(opt);
+            }
+        }
+        return optsWithoutGC;
+    }
+
+    /**
      * Splits a string by white space.
      * Works like String.split(), but returns an empty array
      * if the string is null or empty.
--- a/jdk/test/sun/nio/cs/TestUTF8.java	Thu Apr 17 15:22:07 2014 -0700
+++ b/jdk/test/sun/nio/cs/TestUTF8.java	Wed Jul 05 19:37:28 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4486841 7040220 7096080
+ * @bug 4486841 7040220 7096080 8039751
  * @summary Test UTF-8 charset
  */
 
@@ -291,14 +291,18 @@
         {1, (byte)0xE0, (byte)0xC0, (byte)0xBF }, // invalid second byte
         {2, (byte)0xE0, (byte)0xA0, (byte)0x7F }, // invalid third byte
         {2, (byte)0xE0, (byte)0xA0, (byte)0xC0 }, // invalid third byte
+        {2, (byte)0xE1, (byte)0x80, (byte)0x42},  // invalid third byte
+
         {1, (byte)0xFF, (byte)0xFF, (byte)0xFF }, // all ones
         {1, (byte)0xE0, (byte)0xC0, (byte)0x80 }, // invalid second byte
         {1, (byte)0xE0, (byte)0x80, (byte)0xC0 }, // invalid first byte
         {1, (byte)0xE0, (byte)0x41,},             // invalid second byte & 2 bytes
+        {1, (byte)0xE1, (byte)0x40,},             // invalid second byte & 2 bytes
         {3, (byte)0xED, (byte)0xAE, (byte)0x80 }, // 3 bytes surrogate
         {3, (byte)0xED, (byte)0xB0, (byte)0x80 }, // 3 bytes surrogate
 
 
+
         // Four-byte sequences
         {1, (byte)0xF0, (byte)0x80, (byte)0x80, (byte)0x80 }, // U+0000 zero-padded
         {1, (byte)0xF0, (byte)0x80, (byte)0x81, (byte)0xBF }, // U+007F zero-padded
@@ -323,6 +327,32 @@
         {1, (byte)0xF4, (byte)0xC0, (byte)0x80, (byte)0xC0 }, // out-range 4-byte
         {1, (byte)0xF5, (byte)0x80, (byte)0x80, (byte)0xC0 }, // out-range 4-byte
 
+        // #8039751
+        {1, (byte)0xF6, (byte)0x80, (byte)0x80, (byte)0x80 }, // out-range 1st byte
+        {1, (byte)0xF6, (byte)0x80, (byte)0x80,  },
+        {1, (byte)0xF6, (byte)0x80, },
+        {1, (byte)0xF6, },
+        {1, (byte)0xF5, (byte)0x80, (byte)0x80, (byte)0x80 }, // out-range 1st byte
+        {1, (byte)0xF5, (byte)0x80, (byte)0x80,  },
+        {1, (byte)0xF5, (byte)0x80,  },
+        {1, (byte)0xF5  },
+
+        {1, (byte)0xF4, (byte)0x90, (byte)0x80, (byte)0x80 }, // out-range 2nd byte
+        {1, (byte)0xF4, (byte)0x90, (byte)0x80 },
+        {1, (byte)0xF4, (byte)0x90 },
+
+        {1, (byte)0xF4, (byte)0x7f, (byte)0x80, (byte)0x80 }, // out-range/ascii 2nd byte
+        {1, (byte)0xF4, (byte)0x7f, (byte)0x80 },
+        {1, (byte)0xF4, (byte)0x7f },
+
+        {1, (byte)0xF0, (byte)0x80, (byte)0x80, (byte)0x80 }, // out-range 2nd byte
+        {1, (byte)0xF0, (byte)0x80, (byte)0x80 },
+        {1, (byte)0xF0, (byte)0x80 },
+
+        {1, (byte)0xF0, (byte)0xc0, (byte)0x80, (byte)0x80 }, // out-range 2nd byte
+        {1, (byte)0xF0, (byte)0xc0, (byte)0x80 },
+        {1, (byte)0xF0, (byte)0xc0 },
+
         // Five-byte sequences
         {1, (byte)0xF8, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80},  // invalid first byte
         {1, (byte)0xF8, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80 }, // U+0000 zero-padded
@@ -553,7 +583,6 @@
         check4ByteSurrs("UTF-8");
         checkMalformed("UTF-8", malformed);
         checkUnderOverflow("UTF-8");
-
         checkRoundtrip("CESU-8");
         check6ByteSurrs("CESU-8");
         checkMalformed("CESU-8", malformed_cesu8);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java	Wed Jul 05 19:37:28 2017 +0200
@@ -0,0 +1,342 @@
+/*
+ * 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.
+ */
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+import sun.tools.jinfo.JInfo;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8039080
+ * @run testng JInfoLauncherTest
+ * @summary Test JInfo launcher argument parsing
+ */
+@Test
+public class JInfoLauncherTest {
+    public static final String VALIDATION_EXCEPTION_CLSNAME =
+                                IllegalArgumentException.class.getName();
+
+    private Constructor<JInfo> jInfoConstructor;
+    private Field fldUseSA;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        jInfoConstructor = JInfo.class.getDeclaredConstructor(String[].class);
+        jInfoConstructor.setAccessible(true);
+        fldUseSA = JInfo.class.getDeclaredField("useSA");
+        fldUseSA.setAccessible(true);
+    }
+
+    private JInfo newJInfo(String[] args) throws Exception {
+        try {
+            return jInfoConstructor.newInstance((Object) args);
+        } catch (Exception e) {
+            if (isValidationException(e.getCause())) {
+                throw (Exception)e.getCause();
+            }
+            throw e;
+        }
+    }
+
+    private boolean getUseSA(JInfo jinfo) throws Exception {
+        return fldUseSA.getBoolean(jinfo);
+    }
+
+    private void cmdPID(String cmd, String ... params) throws Exception {
+        int offset = (cmd != null ? 1 : 0);
+        String[] args = new String[offset + params.length];
+        args[0] = cmd;
+        System.arraycopy(params, 0, args, offset, params.length);
+        JInfo j = newJInfo(args);
+        assertFalse(getUseSA(j), "Local jinfo must not forward to SA");
+    }
+
+    private void cmdCore(String cmd, String ... params) throws Exception {
+        int offset = (cmd != null ? 1 : 0);
+        String[] args = new String[offset + params.length];
+        args[0] = cmd;
+        System.arraycopy(params, 0, args, offset, params.length);
+        JInfo j = newJInfo(args);
+        assertTrue(getUseSA(j), "Core jinfo must forward to SA");
+    }
+
+    private void cmdRemote(String cmd, String ... params) throws Exception {
+        int offset = (cmd != null ? 1 : 0);
+        String[] args = new String[offset + params.length];
+        args[0] = cmd;
+        System.arraycopy(params, 0, args, offset, params.length);
+        JInfo j = newJInfo(args);
+        assertTrue(getUseSA(j), "Remote jinfo must forward to SA");
+    }
+
+    private void cmdExtraArgs(String cmd, int argsLen) throws Exception {
+        String[] args = new String[argsLen + 1 + (cmd != null ? 1 : 0)];
+        Arrays.fill(args, "a");
+        if (cmd != null) {
+            args[0] = cmd;
+        } else {
+            cmd = "default";
+        }
+        try {
+            JInfo j = newJInfo(args);
+            fail("\"" + cmd + "\" does not support more than " + argsLen +
+                 " arguments");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    private void cmdMissingArgs(String cmd, int reqArgs) throws Exception {
+        String[] args = new String[reqArgs - 1 + (cmd != null ? 1 : 0)];
+        Arrays.fill(args, "a");
+        if (cmd != null) {
+            args[0] = cmd;
+        } else {
+            cmd = "default";
+        }
+        try {
+            JInfo j = newJInfo(args);
+            fail("\"" + cmd + "\" requires at least " + reqArgs + " argument");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testDefaultPID() throws Exception {
+        cmdPID(null, "1234");
+    }
+
+    public void testFlagsPID() throws Exception {
+        cmdPID("-flags", "1234");
+    }
+
+    public void testSyspropsPID() throws Exception {
+        cmdPID("-sysprops", "1234");
+    }
+
+    public void testReadFlagPID() throws Exception {
+        cmdPID("-flag", "SomeManagementFlag", "1234");
+    }
+
+    public void testSetFlag1PID() throws Exception {
+        cmdPID("-flag", "+SomeManagementFlag", "1234");
+    }
+
+    public void testSetFlag2PID() throws Exception {
+        cmdPID("-flag", "-SomeManagementFlag", "1234");
+    }
+
+    public void testSetFlag3PID() throws Exception {
+        cmdPID("-flag", "SomeManagementFlag=314", "1234");
+    }
+
+    public void testDefaultCore() throws Exception {
+        cmdCore(null, "myapp.exe", "my.core");
+    }
+
+    public void testFlagsCore() throws Exception {
+        cmdCore("-flags", "myapp.exe", "my.core");
+    }
+
+    public void testSyspropsCore() throws Exception {
+        cmdCore("-sysprops", "myapp.exe", "my.core");
+    }
+
+    public void testReadFlagCore() throws Exception {
+        try {
+            cmdCore("-flag", "SomeManagementFlag", "myapp.exe", "my.core");
+            fail("Flags can not be read from core files");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testSetFlag1Core() throws Exception {
+        try {
+            cmdCore("-flag", "+SomeManagementFlag", "myapp.exe", "my.core");
+            fail("Flags can not be set in core files");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testSetFlag2Core() throws Exception {
+        try {
+            cmdCore("-flag", "-SomeManagementFlag", "myapp.exe", "my.core");
+            fail("Flags can not be set in core files");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testSetFlag3Core() throws Exception {
+        try {
+            cmdCore("-flag", "SomeManagementFlag=314", "myapp.exe", "my.core");
+            fail("Flags can not be set in core files");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testDefaultRemote() throws Exception {
+        cmdRemote(null, "serverid@host");
+    }
+
+    public void testFlagsRemote() throws Exception {
+        cmdRemote("-flags", "serverid@host");
+    }
+
+    public void testSyspropsRemote() throws Exception {
+        cmdRemote("-sysprops", "serverid@host");
+    }
+
+    public void testReadFlagRemote() throws Exception {
+        try {
+            cmdCore("-flag", "SomeManagementFlag", "serverid@host");
+            fail("Flags can not be read from SA server");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testSetFlag1Remote() throws Exception {
+        try {
+            cmdCore("-flag", "+SomeManagementFlag","serverid@host");
+            fail("Flags can not be set on SA server");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testSetFlag2Remote() throws Exception {
+        try {
+            cmdCore("-flag", "-SomeManagementFlag", "serverid@host");
+            fail("Flags can not be read set on SA server");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testSetFlag3Remote() throws Exception {
+        try {
+            cmdCore("-flag", "SomeManagementFlag=314", "serverid@host");
+            fail("Flags can not be read set on SA server");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    public void testDefaultExtraArgs() throws Exception {
+        cmdExtraArgs(null, 2);
+    }
+
+    public void testFlagsExtraArgs() throws Exception {
+        cmdExtraArgs("-flags", 2);
+    }
+
+    public void testSyspropsExtraArgs() throws Exception {
+        cmdExtraArgs("-sysprops", 2);
+    }
+
+    public void testFlagExtraArgs() throws Exception {
+        cmdExtraArgs("-flag", 2);
+    }
+
+    public void testHelp1ExtraArgs() throws Exception {
+        cmdExtraArgs("-h", 0);
+    }
+
+    public void testHelp2ExtraArgs() throws Exception {
+        cmdExtraArgs("-help", 0);
+    }
+
+    public void testDefaultMissingArgs() throws Exception {
+        cmdMissingArgs(null, 1);
+    }
+
+    public void testFlagsMissingArgs() throws Exception {
+        cmdMissingArgs("-flags", 1);
+    }
+
+    public void testSyspropsMissingArgs() throws Exception {
+        cmdMissingArgs("-sysprops", 1);
+    }
+
+    public void testFlagMissingArgs() throws Exception {
+        cmdMissingArgs("-flag", 2);
+    }
+
+    public void testUnknownCommand() throws Exception {
+        try {
+            JInfo j = newJInfo(new String[]{"-unknown_command"});
+            fail("JInfo accepts unknown commands");
+        } catch (Exception e) {
+            if (!isValidationException(e)) {
+                throw e;
+            }
+            // ignore
+        }
+    }
+
+    private static boolean isValidationException(Throwable e) {
+        return e.getClass().getName().equals(VALIDATION_EXCEPTION_CLSNAME);
+    }
+}
--- a/make/Javadoc.gmk	Thu Apr 17 15:22:07 2014 -0700
+++ b/make/Javadoc.gmk	Wed Jul 05 19:37:28 2017 +0200
@@ -72,6 +72,7 @@
 TREEAPI_FIRST_COPYRIGHT_YEAR = 2005
 JNLP_FIRST_COPYRIGHT_YEAR = 1998
 PLUGIN2_FIRST_COPYRIGHT_YEAR = 2007
+JDKNET_FIRST_COPYRIGHT_YEAR = 2014
 
 # Oracle name
 FULL_COMPANY_NAME = Oracle and/or its affiliates
@@ -1160,6 +1161,57 @@
 
 #############################################################
 #
+# jdk.net docs
+#
+
+ALL_OTHER_TARGETS += jdknetdocs
+
+JDKNET_DOCDIR := $(JRE_API_DOCSDIR)/net/socketoptions/spec
+JDKNET2COREAPI := ../../../$(JDKJRE2COREAPI)
+JDKNET_DOCTITLE := jdk.net API
+JDKNET_WINDOWTITLE := jdk.net API
+JDKNET_HEADER := <strong>jdk.net API</strong>
+JDKNET_BOTTOM := $(call CommonBottom,$(JDKNET_FIRST_COPYRIGHT_YEAR))
+JDKNET_PKGS := jdk.net
+
+JDKNET_INDEX_HTML = $(JDKNET_DOCDIR)/index.html
+JDKNET_OPTIONS_FILE = $(DOCSTMPDIR)/jdknet.options
+JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages
+
+jdknetdocs: $(JDKNET_INDEX_HTML)
+
+# Set relative location to core api document root
+$(JDKNET_INDEX_HTML): GET2DOCSDIR=$(JDKNET2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JDKNET_INDEX_HTML): $(JDKNET_OPTIONS_FILE) $(JDKNET_PACKAGES_FILE) coredocs
+	$(prep-javadoc)
+	$(call JavadocSummary,$(JDKNET_OPTIONS_FILE),$(JDKNET_PACKAGES_FILE))
+	$(JAVADOC_CMD) -d $(@D) \
+	    @$(JDKNET_OPTIONS_FILE) @$(JDKNET_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JDKNET_OPTIONS_FILE):
+	$(prep-target)
+	@($(call OptionOnly,$(COMMON_JAVADOCFLAGS)) ; \
+	  $(call OptionOnly,-Xdoclint:none) ; \
+	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+	  $(call OptionPair,-encoding,ascii) ; \
+	  $(call OptionOnly,-nodeprecatedlist) ; \
+	  $(call OptionPair,-doctitle,$(JDKNET_DOCTITLE)) ; \
+	  $(call OptionPair,-windowtitle,$(JDKNET_WINDOWTITLE) $(DRAFT_WINTITLE)); \
+	  $(call OptionPair,-header,$(JDKNET_HEADER)$(DRAFT_HEADER)); \
+	  $(call OptionPair,-bottom,$(JDKNET_BOTTOM)$(DRAFT_BOTTOM)); \
+	  $(call OptionTrip,-linkoffline,$(JDKNET2COREAPI),$(COREAPI_DOCSDIR)/); \
+	) >> $@
+
+# Create a file with the package names in it
+$(JDKNET_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JDKNET_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(JDKNET_PKGS))
+
+#############################################################
+#
 # Get a cache of all the directories
 
 $(DIRECTORY_CACHE): $(ALL_EXISTING_SOURCE_DIRS)
--- a/make/common/NON_CORE_PKGS.gmk	Thu Apr 17 15:22:07 2014 -0700
+++ b/make/common/NON_CORE_PKGS.gmk	Wed Jul 05 19:37:28 2017 +0200
@@ -94,7 +94,8 @@
       com.apple.eio
 endif
 
-JDK_PKGS = jdk
+JDK_PKGS = jdk \
+      jdk.net
 
 # non-core packages in rt.jar
 NON_CORE_PKGS = $(DOMAPI_PKGS) \