Merge
authorduke
Wed, 05 Jul 2017 17:17:57 +0200
changeset 6015 edb08297ecba
parent 6014 f15aef32e2b3 (current diff)
parent 6010 ea74537ab2de (diff)
child 6021 dff6a1dc93b2
Merge
hotspot/src/os/linux/vm/vtune_linux.cpp
hotspot/src/os/solaris/vm/vtune_solaris.cpp
hotspot/src/os/windows/vm/vtune_windows.cpp
hotspot/src/share/vm/runtime/vtune.hpp
jdk/test/java/nio/channels/ServerSocketChannel/AcceptAddress.java
jdk/test/java/nio/charset/coders/Surrogate.java
jdk/test/tools/launcher/Makefile.SolarisRunpath
jdk/test/tools/launcher/lib/i386/lib32/lib32/liblibrary.so
jdk/test/tools/launcher/lib/i386/lib32/liblibrary.so
jdk/test/tools/launcher/lib/sparc/lib32/lib32/liblibrary.so
jdk/test/tools/launcher/lib/sparc/lib32/liblibrary.so
jdk/test/tools/launcher/lib/sparc/lib64/lib64/liblibrary.so
jdk/test/tools/launcher/lib/sparc/lib64/liblibrary.so
--- a/.hgtags-top-repo	Tue Jul 20 22:17:28 2010 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 17:17:57 2017 +0200
@@ -75,3 +75,4 @@
 6cea9984d73d74de0cd01f30d07ac0a1ed196117 jdk7-b98
 e7f18db469a3e947b7096bfd12e87380e5a042cd jdk7-b99
 b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100
+4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101
--- a/hotspot/.hgtags	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 17:17:57 2017 +0200
@@ -104,3 +104,5 @@
 8a045b3f5c13eaad92ff4baf15ca671845fcad1a jdk7-b98
 6a236384a379642b5a2398e2819db9ab4e711e9b jdk7-b99
 ad1977f08c4d69162a0775fe3f9576b9fd521d10 jdk7-b100
+6c3a919105b68c15b7db923ec9a00006e9560910 jdk7-b101
+ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Wed Jul 05 17:17:57 2017 +0200
@@ -35,7 +35,6 @@
 
 public class NMethod extends CodeBlob {
   private static long          pcDescSize;
-  private static CIntegerField zombieInstructionSizeField;
   private static sun.jvm.hotspot.types.OopField methodField;
   /** != InvocationEntryBci if this nmethod is an on-stack replacement method */
   private static CIntegerField entryBCIField;
@@ -88,7 +87,6 @@
   private static void initialize(TypeDataBase db) {
     Type type = db.lookupType("nmethod");
 
-    zombieInstructionSizeField  = type.getCIntegerField("_zombie_instruction_size");
     methodField                 = type.getOopField("_method");
     entryBCIField               = type.getCIntegerField("_entry_bci");
     osrLinkField                = type.getAddressField("_osr_link");
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeDisassembler.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeDisassembler.java	Wed Jul 05 17:17:57 2017 +0200
@@ -72,6 +72,7 @@
       addBytecodeClass(Bytecodes._invokestatic, BytecodeInvoke.class);
       addBytecodeClass(Bytecodes._invokespecial, BytecodeInvoke.class);
       addBytecodeClass(Bytecodes._invokeinterface, BytecodeInvoke.class);
+      addBytecodeClass(Bytecodes._invokedynamic, BytecodeInvoke.class);
       addBytecodeClass(Bytecodes._jsr, BytecodeJsr.class);
       addBytecodeClass(Bytecodes._jsr_w, BytecodeJsrW.class);
       addBytecodeClass(Bytecodes._iload, BytecodeLoad.class);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeInvoke.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeInvoke.java	Wed Jul 05 17:17:57 2017 +0200
@@ -54,15 +54,31 @@
   // returns the name of the invoked method
   public Symbol name() {
     ConstantPool cp = method().getConstants();
+    if (isInvokedynamic()) {
+       int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod());
+       return cp.getSymbolAt(nt[0]);
+    }
     return cp.getNameRefAt(index());
   }
 
   // returns the signature of the invoked method
   public Symbol signature() {
     ConstantPool cp = method().getConstants();
+    if (isInvokedynamic()) {
+       int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod());
+       return cp.getSymbolAt(nt[1]);
+    }
     return cp.getSignatureRefAt(index());
   }
 
+  public int getSecondaryIndex() {
+    if (isInvokedynamic()) {
+      // change byte-ordering of 4-byte integer
+      return VM.getVM().getBytes().swapInt(javaSignedWordAt(1));
+    }
+    return super.getSecondaryIndex();  // throw an error
+  }
+
   public Method getInvokedMethod() {
     return method().getConstants().getMethodRefAt(index());
   }
@@ -87,6 +103,7 @@
   public boolean isInvokevirtual()   { return adjustedInvokeCode() == Bytecodes._invokevirtual;   }
   public boolean isInvokestatic()    { return adjustedInvokeCode() == Bytecodes._invokestatic;    }
   public boolean isInvokespecial()   { return adjustedInvokeCode() == Bytecodes._invokespecial;   }
+  public boolean isInvokedynamic()   { return adjustedInvokeCode() == Bytecodes._invokedynamic; }
 
   public boolean isValid()           { return isInvokeinterface() ||
                                               isInvokevirtual()   ||
@@ -104,6 +121,11 @@
     buf.append(spaces);
     buf.append('#');
     buf.append(Integer.toString(indexForFieldOrMethod()));
+    if (isInvokedynamic()) {
+       buf.append('(');
+       buf.append(Integer.toString(getSecondaryIndex()));
+       buf.append(')');
+    }
     buf.append(" [Method ");
     StringBuffer sigBuf = new StringBuffer();
     new SignatureConverter(signature(), sigBuf).iterateReturntype();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,6 +25,7 @@
 package sun.jvm.hotspot.interpreter;
 
 import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.utilities.*;
 
 public class BytecodeLoadConstant extends BytecodeWithCPIndex {
@@ -32,10 +33,47 @@
     super(method, bci);
   }
 
+  public boolean hasCacheIndex() {
+    // normal ldc uses CP index, but fast_aldc uses swapped CP cache index
+    return javaCode() != code();
+  }
+
   public int index() {
-    return javaCode() == Bytecodes._ldc ?
+    int i = javaCode() == Bytecodes._ldc ?
                  (int) (0xFF & javaByteAt(1))
                : (int) (0xFFFF & javaShortAt(1));
+    if (hasCacheIndex()) {
+      return (0xFFFF & VM.getVM().getBytes().swapShort((short) i));
+    } else {
+      return i;
+    }
+  }
+
+  public int poolIndex() {
+    int i = index();
+    if (hasCacheIndex()) {
+      ConstantPoolCache cpCache = method().getConstants().getCache();
+      return cpCache.getEntryAt(i).getConstantPoolIndex();
+    } else {
+      return i;
+    }
+  }
+
+  public int cacheIndex() {
+    if (hasCacheIndex()) {
+      return index();
+    } else {
+      return -1;  // no cache index
+    }
+  }
+
+  private Oop getCachedConstant() {
+    int i = cacheIndex();
+    if (i >= 0) {
+      ConstantPoolCache cpCache = method().getConstants().getCache();
+      return cpCache.getEntryAt(i).getF1();
+    }
+    return null;
   }
 
   public void verify() {
@@ -58,6 +96,7 @@
        // has to be int or float or String or Klass
        return (ctag.isUnresolvedString() || ctag.isString()
                || ctag.isUnresolvedKlass() || ctag.isKlass()
+               || ctag.isMethodHandle() || ctag.isMethodType()
                || ctag.isInt() || ctag.isFloat())? true: false;
     }
   }
@@ -112,7 +151,7 @@
 
   public String getConstantValue() {
     ConstantPool cpool = method().getConstants();
-    int cpIndex = index();
+    int cpIndex = poolIndex();
     ConstantTag ctag = cpool.getTagAt(cpIndex);
     if (ctag.isInt()) {
        return "<int " + Integer.toString(cpool.getIntAt(cpIndex)) +">";
@@ -149,6 +188,18 @@
        } else {
           throw new RuntimeException("should not reach here");
        }
+    } else if (ctag.isMethodHandle() || ctag.isMethodType()) {
+       Oop x = getCachedConstant();
+       int refidx = cpool.getMethodHandleIndexAt(cpIndex);
+       int refkind = cpool.getMethodHandleRefKindAt(cpIndex);
+       return "<MethodHandle kind=" + Integer.toString(refkind) +
+           " ref=" + Integer.toString(refidx)
+           + (x == null ? "" : " @" + x.getHandle()) + ">";
+    } else if (ctag.isMethodType()) {
+       Oop x = getCachedConstant();
+       int refidx = cpool.getMethodTypeIndexAt(cpIndex);
+       return "<MethodType " + cpool.getSymbolAt(refidx).asString()
+           + (x == null ? "" : " @" + x.getHandle()) + ">";
     } else {
        if (Assert.ASSERTS_ENABLED) {
          Assert.that(false, "invalid load constant type");
@@ -162,7 +213,12 @@
     buf.append(getJavaBytecodeName());
     buf.append(spaces);
     buf.append('#');
-    buf.append(Integer.toString(index()));
+    buf.append(Integer.toString(poolIndex()));
+    if (hasCacheIndex()) {
+       buf.append('(');
+       buf.append(Integer.toString(cacheIndex()));
+       buf.append(')');
+    }
     buf.append(spaces);
     buf.append(getConstantValue());
     if (code() != javaCode()) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java	Wed Jul 05 17:17:57 2017 +0200
@@ -37,12 +37,19 @@
   // the constant pool index for this bytecode
   public int index() { return 0xFFFF & javaShortAt(1); }
 
+  public int getSecondaryIndex() {
+     throw new IllegalArgumentException("must be invokedynamic");
+  }
+
   protected int indexForFieldOrMethod() {
      ConstantPoolCache cpCache = method().getConstants().getCache();
      // get ConstantPool index from ConstantPoolCacheIndex at given bci
      int cpCacheIndex = index();
      if (cpCache == null) {
         return cpCacheIndex;
+     } else if (code() == Bytecodes._invokedynamic) {
+        int secondaryIndex = getSecondaryIndex();
+        return cpCache.getMainEntryAt(secondaryIndex).getConstantPoolIndex();
      } else {
         // change byte-ordering and go via cache
         return cpCache.getEntryAt((int) (0xFFFF & VM.getVM().getBytes().swapShort((short) cpCacheIndex))).getConstantPoolIndex();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java	Wed Jul 05 17:17:57 2017 +0200
@@ -222,7 +222,7 @@
   public static final int _invokespecial        = 183; // 0xb7
   public static final int _invokestatic         = 184; // 0xb8
   public static final int _invokeinterface      = 185; // 0xb9
-  public static final int _xxxunusedxxx         = 186; // 0xba
+  public static final int _invokedynamic        = 186; // 0xba
   public static final int _new                  = 187; // 0xbb
   public static final int _newarray             = 188; // 0xbc
   public static final int _anewarray            = 189; // 0xbd
@@ -269,9 +269,12 @@
   public static final int _fast_invokevfinal    = 226;
   public static final int _fast_linearswitch    = 227;
   public static final int _fast_binaryswitch    = 228;
-  public static final int _shouldnotreachhere   = 229; // For debugging
+  public static final int _fast_aldc            = 229;
+  public static final int _fast_aldc_w          = 230;
+  public static final int _return_register_finalizer = 231;
+  public static final int _shouldnotreachhere   = 232; // For debugging
 
-  public static final int number_of_codes       = 230;
+  public static final int number_of_codes       = 233;
 
   public static int specialLengthAt(Method method, int bci) {
     int code = codeAt(method, bci);
@@ -458,9 +461,9 @@
     def(_dconst_1            , "dconst_1"            , "b"    , null    , BasicType.getTDouble() ,  2, false);
     def(_bipush              , "bipush"              , "bc"   , null    , BasicType.getTInt()    ,  1, false);
     def(_sipush              , "sipush"              , "bcc"  , null    , BasicType.getTInt()    ,  1, false);
-    def(_ldc                 , "ldc"                 , "bi"   , null    , BasicType.getTIllegal(),  1, true );
-    def(_ldc_w               , "ldc_w"               , "bii"  , null    , BasicType.getTIllegal(),  1, true );
-    def(_ldc2_w              , "ldc2_w"              , "bii"  , null    , BasicType.getTIllegal(),  2, true );
+    def(_ldc                 , "ldc"                 , "bk"   , null    , BasicType.getTIllegal(),  1, true );
+    def(_ldc_w               , "ldc_w"               , "bkk"  , null    , BasicType.getTIllegal(),  1, true );
+    def(_ldc2_w              , "ldc2_w"              , "bkk"  , null    , BasicType.getTIllegal(),  2, true );
     def(_iload               , "iload"               , "bi"   , "wbii"  , BasicType.getTInt()    ,  1, false);
     def(_lload               , "lload"               , "bi"   , "wbii"  , BasicType.getTLong()   ,  2, false);
     def(_fload               , "fload"               , "bi"   , "wbii"  , BasicType.getTFloat()  ,  1, false);
@@ -618,26 +621,26 @@
     def(_dreturn             , "dreturn"             , "b"    , null    , BasicType.getTDouble() , -2, true );
     def(_areturn             , "areturn"             , "b"    , null    , BasicType.getTObject() , -1, true );
     def(_return              , "return"              , "b"    , null    , BasicType.getTVoid()   ,  0, true );
-    def(_getstatic           , "getstatic"           , "bjj"  , null    , BasicType.getTIllegal(),  1, true );
-    def(_putstatic           , "putstatic"           , "bjj"  , null    , BasicType.getTIllegal(), -1, true );
-    def(_getfield            , "getfield"            , "bjj"  , null    , BasicType.getTIllegal(),  0, true );
-    def(_putfield            , "putfield"            , "bjj"  , null    , BasicType.getTIllegal(), -2, true );
-    def(_invokevirtual       , "invokevirtual"       , "bjj"  , null    , BasicType.getTIllegal(), -1, true );
-    def(_invokespecial       , "invokespecial"       , "bjj"  , null    , BasicType.getTIllegal(), -1, true );
-    def(_invokestatic        , "invokestatic"        , "bjj"  , null    , BasicType.getTIllegal(),  0, true );
-    def(_invokeinterface     , "invokeinterface"     , "bjj__", null    , BasicType.getTIllegal(), -1, true );
-    def(_xxxunusedxxx        , "xxxunusedxxx"        , null   , null    , BasicType.getTVoid()   ,  0, false);
-    def(_new                 , "new"                 , "bii"  , null    , BasicType.getTObject() ,  1, true );
+    def(_getstatic           , "getstatic"           , "bJJ"  , null    , BasicType.getTIllegal(),  1, true );
+    def(_putstatic           , "putstatic"           , "bJJ"  , null    , BasicType.getTIllegal(), -1, true );
+    def(_getfield            , "getfield"            , "bJJ"  , null    , BasicType.getTIllegal(),  0, true );
+    def(_putfield            , "putfield"            , "bJJ"  , null    , BasicType.getTIllegal(), -2, true );
+    def(_invokevirtual       , "invokevirtual"       , "bJJ"  , null    , BasicType.getTIllegal(), -1, true );
+    def(_invokespecial       , "invokespecial"       , "bJJ"  , null    , BasicType.getTIllegal(), -1, true );
+    def(_invokestatic        , "invokestatic"        , "bJJ"  , null    , BasicType.getTIllegal(),  0, true );
+    def(_invokeinterface     , "invokeinterface"     , "bJJ__", null    , BasicType.getTIllegal(), -1, true );
+    def(_invokedynamic       , "invokedynamic"       , "bJJJJ", null    , BasicType.getTIllegal(), -1, true );
+    def(_new                 , "new"                 , "bkk"  , null    , BasicType.getTObject() ,  1, true );
     def(_newarray            , "newarray"            , "bc"   , null    , BasicType.getTObject() ,  0, true );
-    def(_anewarray           , "anewarray"           , "bii"  , null    , BasicType.getTObject() ,  0, true );
+    def(_anewarray           , "anewarray"           , "bkk"  , null    , BasicType.getTObject() ,  0, true );
     def(_arraylength         , "arraylength"         , "b"    , null    , BasicType.getTVoid()   ,  0, true );
     def(_athrow              , "athrow"              , "b"    , null    , BasicType.getTVoid()   , -1, true );
-    def(_checkcast           , "checkcast"           , "bii"  , null    , BasicType.getTObject() ,  0, true );
-    def(_instanceof          , "instanceof"          , "bii"  , null    , BasicType.getTInt()    ,  0, true );
+    def(_checkcast           , "checkcast"           , "bkk"  , null    , BasicType.getTObject() ,  0, true );
+    def(_instanceof          , "instanceof"          , "bkk"  , null    , BasicType.getTInt()    ,  0, true );
     def(_monitorenter        , "monitorenter"        , "b"    , null    , BasicType.getTVoid()   , -1, true );
     def(_monitorexit         , "monitorexit"         , "b"    , null    , BasicType.getTVoid()   , -1, true );
     def(_wide                , "wide"                , ""     , null    , BasicType.getTVoid()   ,  0, false);
-    def(_multianewarray      , "multianewarray"      , "biic" , null    , BasicType.getTObject() ,  1, true );
+    def(_multianewarray      , "multianewarray"      , "bkkc" , null    , BasicType.getTObject() ,  1, true );
     def(_ifnull              , "ifnull"              , "boo"  , null    , BasicType.getTVoid()   , -1, false);
     def(_ifnonnull           , "ifnonnull"           , "boo"  , null    , BasicType.getTVoid()   , -1, false);
     def(_goto_w              , "goto_w"              , "boooo", null    , BasicType.getTVoid()   ,  0, false);
@@ -646,38 +649,44 @@
 
     //  JVM bytecodes
     //  bytecode               bytecode name           format   wide f.   result tp               stk traps  std code
-    def(_fast_agetfield      , "fast_agetfield"      , "bjj"  , null    , BasicType.getTObject() ,  0, true , _getfield       );
-    def(_fast_bgetfield      , "fast_bgetfield"      , "bjj"  , null    , BasicType.getTInt()    ,  0, true , _getfield       );
-    def(_fast_cgetfield      , "fast_cgetfield"      , "bjj"  , null    , BasicType.getTChar()   ,  0, true , _getfield       );
-    def(_fast_dgetfield      , "fast_dgetfield"      , "bjj"  , null    , BasicType.getTDouble() ,  0, true , _getfield       );
-    def(_fast_fgetfield      , "fast_fgetfield"      , "bjj"  , null    , BasicType.getTFloat()  ,  0, true , _getfield       );
-    def(_fast_igetfield      , "fast_igetfield"      , "bjj"  , null    , BasicType.getTInt()    ,  0, true , _getfield       );
-    def(_fast_lgetfield      , "fast_lgetfield"      , "bjj"  , null    , BasicType.getTLong()   ,  0, true , _getfield       );
-    def(_fast_sgetfield      , "fast_sgetfield"      , "bjj"  , null    , BasicType.getTShort()  ,  0, true , _getfield       );
+    def(_fast_agetfield      , "fast_agetfield"      , "bJJ"  , null    , BasicType.getTObject() ,  0, true , _getfield       );
+    def(_fast_bgetfield      , "fast_bgetfield"      , "bJJ"  , null    , BasicType.getTInt()    ,  0, true , _getfield       );
+    def(_fast_cgetfield      , "fast_cgetfield"      , "bJJ"  , null    , BasicType.getTChar()   ,  0, true , _getfield       );
+    def(_fast_dgetfield      , "fast_dgetfield"      , "bJJ"  , null    , BasicType.getTDouble() ,  0, true , _getfield       );
+    def(_fast_fgetfield      , "fast_fgetfield"      , "bJJ"  , null    , BasicType.getTFloat()  ,  0, true , _getfield       );
+    def(_fast_igetfield      , "fast_igetfield"      , "bJJ"  , null    , BasicType.getTInt()    ,  0, true , _getfield       );
+    def(_fast_lgetfield      , "fast_lgetfield"      , "bJJ"  , null    , BasicType.getTLong()   ,  0, true , _getfield       );
+    def(_fast_sgetfield      , "fast_sgetfield"      , "bJJ"  , null    , BasicType.getTShort()  ,  0, true , _getfield       );
 
-    def(_fast_aputfield      , "fast_aputfield"      , "bjj"  , null    , BasicType.getTObject() ,  0, true , _putfield       );
-    def(_fast_bputfield      , "fast_bputfield"      , "bjj"  , null    , BasicType.getTInt()    ,  0, true , _putfield       );
-    def(_fast_cputfield      , "fast_cputfield"      , "bjj"  , null    , BasicType.getTChar()   ,  0, true , _putfield       );
-    def(_fast_dputfield      , "fast_dputfield"      , "bjj"  , null    , BasicType.getTDouble() ,  0, true , _putfield       );
-    def(_fast_fputfield      , "fast_fputfield"      , "bjj"  , null    , BasicType.getTFloat()  ,  0, true , _putfield       );
-    def(_fast_iputfield      , "fast_iputfield"      , "bjj"  , null    , BasicType.getTInt()    ,  0, true , _putfield       );
-    def(_fast_lputfield      , "fast_lputfield"      , "bjj"  , null    , BasicType.getTLong()   ,  0, true , _putfield       );
-    def(_fast_sputfield      , "fast_sputfield"      , "bjj"  , null    , BasicType.getTShort()  ,  0, true , _putfield       );
+    def(_fast_aputfield      , "fast_aputfield"      , "bJJ"  , null    , BasicType.getTObject() ,  0, true , _putfield       );
+    def(_fast_bputfield      , "fast_bputfield"      , "bJJ"  , null    , BasicType.getTInt()    ,  0, true , _putfield       );
+    def(_fast_cputfield      , "fast_cputfield"      , "bJJ"  , null    , BasicType.getTChar()   ,  0, true , _putfield       );
+    def(_fast_dputfield      , "fast_dputfield"      , "bJJ"  , null    , BasicType.getTDouble() ,  0, true , _putfield       );
+    def(_fast_fputfield      , "fast_fputfield"      , "bJJ"  , null    , BasicType.getTFloat()  ,  0, true , _putfield       );
+    def(_fast_iputfield      , "fast_iputfield"      , "bJJ"  , null    , BasicType.getTInt()    ,  0, true , _putfield       );
+    def(_fast_lputfield      , "fast_lputfield"      , "bJJ"  , null    , BasicType.getTLong()   ,  0, true , _putfield       );
+    def(_fast_sputfield      , "fast_sputfield"      , "bJJ"  , null    , BasicType.getTShort()  ,  0, true , _putfield       );
 
     def(_fast_aload_0        , "fast_aload_0"        , "b"    , null    , BasicType.getTObject() ,  1, true , _aload_0        );
-    def(_fast_iaccess_0      , "fast_iaccess_0"      , "b_jj" , null    , BasicType.getTInt()    ,  1, true , _aload_0        );
-    def(_fast_aaccess_0      , "fast_aaccess_0"      , "b_jj" , null    , BasicType.getTObject() ,  1, true , _aload_0        );
-    def(_fast_faccess_0      , "fast_faccess_0"      , "b_jj" , null    , BasicType.getTObject() ,  1, true , _aload_0        );
+    def(_fast_iaccess_0      , "fast_iaccess_0"      , "b_JJ" , null    , BasicType.getTInt()    ,  1, true , _aload_0        );
+    def(_fast_aaccess_0      , "fast_aaccess_0"      , "b_JJ" , null    , BasicType.getTObject() ,  1, true , _aload_0        );
+    def(_fast_faccess_0      , "fast_faccess_0"      , "b_JJ" , null    , BasicType.getTObject() ,  1, true , _aload_0        );
 
     def(_fast_iload          , "fast_iload"          , "bi"   , null    , BasicType.getTInt()    ,  1, false, _iload);
     def(_fast_iload2         , "fast_iload2"         , "bi_i" , null    , BasicType.getTInt()    ,  2, false, _iload);
     def(_fast_icaload        , "fast_icaload"        , "bi_"  , null    , BasicType.getTInt()    ,  0, false, _iload);
 
     // Faster method invocation.
-    def(_fast_invokevfinal   , "fast_invokevfinal"   , "bjj"  , null    , BasicType.getTIllegal(), -1, true, _invokevirtual);
+    def(_fast_invokevfinal   , "fast_invokevfinal"   , "bJJ"  , null    , BasicType.getTIllegal(), -1, true, _invokevirtual);
 
     def(_fast_linearswitch   , "fast_linearswitch"   , ""     , null    , BasicType.getTVoid()   , -1, false, _lookupswitch   );
     def(_fast_binaryswitch   , "fast_binaryswitch"   , ""     , null    , BasicType.getTVoid()   , -1, false, _lookupswitch   );
+
+    def(_return_register_finalizer, "return_register_finalizer", "b"    , null    , BasicType.getTVoid()   , 0, true, _return );
+
+    def(_fast_aldc           , "fast_aldc"           , "bj"   , null    , BasicType.getTObject(),   1, true,  _ldc   );
+    def(_fast_aldc_w         , "fast_aldc_w"         , "bJJ"  , null    , BasicType.getTObject(),   1, true,  _ldc_w );
+
     def(_shouldnotreachhere  , "_shouldnotreachhere" , "b"    , null    , BasicType.getTVoid()   ,  0, false);
 
     if (Assert.ASSERTS_ENABLED) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Wed Jul 05 17:17:57 2017 +0200
@@ -152,7 +152,7 @@
     return res;
   }
 
-  public int getNameAndTypeAt(int which) {
+  public int[] getNameAndTypeAt(int which) {
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool");
     }
@@ -160,18 +160,16 @@
     if (DEBUG) {
       System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i);
     }
-    return i;
+    return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) };
   }
 
   public Symbol getNameRefAt(int which) {
-    int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which));
-    int nameIndex = extractLowShortFromInt(refIndex);
+    int nameIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[0];
     return getSymbolAt(nameIndex);
   }
 
   public Symbol getSignatureRefAt(int which) {
-    int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which));
-    int sigIndex = extractHighShortFromInt(refIndex);
+    int sigIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[1];
     return getSymbolAt(sigIndex);
   }
 
@@ -220,11 +218,11 @@
 
   /** Lookup for entries consisting of (name_index, signature_index) */
   public int getNameRefIndexAt(int index) {
-    int refIndex = getNameAndTypeAt(index);
+    int[] refIndex = getNameAndTypeAt(index);
     if (DEBUG) {
-      System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex);
+      System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);
     }
-    int i = extractLowShortFromInt(refIndex);
+    int i = refIndex[0];
     if (DEBUG) {
       System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i);
     }
@@ -233,17 +231,53 @@
 
   /** Lookup for entries consisting of (name_index, signature_index) */
   public int getSignatureRefIndexAt(int index) {
-    int refIndex = getNameAndTypeAt(index);
+    int[] refIndex = getNameAndTypeAt(index);
     if (DEBUG) {
-      System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex);
+      System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);
     }
-    int i = extractHighShortFromInt(refIndex);
+    int i = refIndex[1];
     if (DEBUG) {
       System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i);
     }
     return i;
   }
 
+  /** Lookup for MethodHandle entries. */
+  public int getMethodHandleIndexAt(int i) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");
+    }
+    int res = extractHighShortFromInt(getIntAt(i));
+    if (DEBUG) {
+      System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res);
+    }
+    return res;
+  }
+
+  /** Lookup for MethodHandle entries. */
+  public int getMethodHandleRefKindAt(int i) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");
+    }
+    int res = extractLowShortFromInt(getIntAt(i));
+    if (DEBUG) {
+      System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res);
+    }
+    return res;
+  }
+
+  /** Lookup for MethodType entries. */
+  public int getMethodTypeIndexAt(int i) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool");
+    }
+    int res = getIntAt(i);
+    if (DEBUG) {
+      System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res);
+    }
+    return res;
+  }
+
   final private static String[] nameForTag = new String[] {
   };
 
@@ -261,6 +295,8 @@
     case JVM_CONSTANT_Methodref:          return "JVM_CONSTANT_Methodref";
     case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref";
     case JVM_CONSTANT_NameAndType:        return "JVM_CONSTANT_NameAndType";
+    case JVM_CONSTANT_MethodHandle:       return "JVM_CONSTANT_MethodHandle";
+    case JVM_CONSTANT_MethodType:         return "JVM_CONSTANT_MethodType";
     case JVM_CONSTANT_Invalid:            return "JVM_CONSTANT_Invalid";
     case JVM_CONSTANT_UnresolvedClass:    return "JVM_CONSTANT_UnresolvedClass";
     case JVM_CONSTANT_UnresolvedClassInError:    return "JVM_CONSTANT_UnresolvedClassInError";
@@ -317,6 +353,8 @@
         case JVM_CONSTANT_Methodref:
         case JVM_CONSTANT_InterfaceMethodref:
         case JVM_CONSTANT_NameAndType:
+        case JVM_CONSTANT_MethodHandle:
+        case JVM_CONSTANT_MethodType:
           visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
           break;
         }
@@ -467,6 +505,18 @@
                                           + ", type = " + signatureIndex);
                   break;
               }
+
+              case JVM_CONSTANT_MethodHandle: {
+                  dos.writeByte(cpConstType);
+                  int value = getIntAt(ci);
+                  short nameIndex = (short) extractLowShortFromInt(value);
+                  short signatureIndex = (short) extractHighShortFromInt(value);
+                  dos.writeShort(nameIndex);
+                  dos.writeShort(signatureIndex);
+                  if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex
+                                          + ", type = " + signatureIndex);
+                  break;
+              }
               default:
                   throw new InternalError("unknown tag: " + cpConstType);
           } // switch
@@ -488,10 +538,12 @@
   //
 
   private static int extractHighShortFromInt(int val) {
+    // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
     return (val >> 16) & 0xFFFF;
   }
 
   private static int extractLowShortFromInt(int val) {
+    // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
     return val & 0xFFFF;
   }
 }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java	Wed Jul 05 17:17:57 2017 +0200
@@ -78,6 +78,31 @@
     return new ConstantPoolCacheEntry(this, i);
   }
 
+  public static boolean isSecondaryIndex(int i)     { return (i < 0); }
+  public static int     decodeSecondaryIndex(int i) { return  isSecondaryIndex(i) ? ~i : i; }
+  public static int     encodeSecondaryIndex(int i) { return !isSecondaryIndex(i) ? ~i : i; }
+
+  // secondary entries hold invokedynamic call site bindings
+  public ConstantPoolCacheEntry getSecondaryEntryAt(int i) {
+    ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, decodeSecondaryIndex(i));
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(e.isSecondaryEntry(), "must be a secondary entry");
+    }
+    return e;
+  }
+
+  public ConstantPoolCacheEntry getMainEntryAt(int i) {
+    if (isSecondaryIndex(i)) {
+      // run through an extra level of indirection:
+      i = getSecondaryEntryAt(i).getMainEntryIndex();
+    }
+    ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, i);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(!e.isSecondaryEntry(), "must not be a secondary entry");
+    }
+    return e;
+  }
+
   public int getIntAt(int entry, int fld) {
     //alignObjectSize ?
     long offset = baseOffset + /*alignObjectSize*/entry * elementSize + fld* getHeap().getIntSize();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheEntry.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheEntry.java	Wed Jul 05 17:17:57 2017 +0200
@@ -28,6 +28,7 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
 
 public class ConstantPoolCacheEntry {
   private static long          size;
@@ -67,9 +68,23 @@
   }
 
   public int getConstantPoolIndex() {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(!isSecondaryEntry(), "must not be a secondary CP entry");
+    }
     return (int) (getIndices() & 0xFFFF);
   }
 
+  public boolean isSecondaryEntry() {
+    return (getIndices() & 0xFFFF) == 0;
+  }
+
+  public int getMainEntryIndex() {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(isSecondaryEntry(), "must be a secondary CP entry");
+    }
+    return (int) (getIndices() >>> 16);
+  }
+
   private long getIndices() {
       return cp.getHandle().getCIntegerAt(indices.getOffset() + offset, indices.getSize(), indices.isUnsigned());
   }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java	Wed Jul 05 17:17:57 2017 +0200
@@ -566,6 +566,7 @@
       case Bytecodes._invokespecial:
       case Bytecodes._invokestatic:
       case Bytecodes._invokeinterface:
+      case Bytecodes._invokedynamic:
         // FIXME: print signature of referenced method (need more
         // accessors in ConstantPool and ConstantPoolCache)
         int idx = currentBC.getIndexBig();
@@ -605,6 +606,7 @@
       case Bytecodes._invokespecial:
       case Bytecodes._invokestatic:
       case Bytecodes._invokeinterface:
+      case Bytecodes._invokedynamic:
         // FIXME: print signature of referenced method (need more
         // accessors in ConstantPool and ConstantPoolCache)
         int idx = currentBC.getIndexBig();
@@ -1134,6 +1136,7 @@
       case Bytecodes._invokespecial:
       case Bytecodes._invokestatic:
       case Bytecodes._invokeinterface:
+      case Bytecodes._invokedynamic:
         _itr_send = itr;
         _report_result_for_send = true;
         break;
@@ -1379,6 +1382,7 @@
     case Bytecodes._invokevirtual:
     case Bytecodes._invokespecial:     doMethod(false, false, itr.getIndexBig(), itr.bci()); break;
     case Bytecodes._invokestatic:      doMethod(true,  false, itr.getIndexBig(), itr.bci()); break;
+    case Bytecodes._invokedynamic:     doMethod(false, true,  itr.getIndexBig(), itr.bci()); break;
     case Bytecodes._invokeinterface:   doMethod(false, true,  itr.getIndexBig(), itr.bci()); break;
     case Bytecodes._newarray:
     case Bytecodes._anewarray:         ppNewRef(vCTS, itr.bci()); break;
@@ -1725,7 +1729,7 @@
   void  doMethod                            (boolean is_static, boolean is_interface, int idx, int bci) {
     // Dig up signature for field in constant pool
     ConstantPool cp       = _method.getConstants();
-    int nameAndTypeIdx    = cp.getNameAndTypeRefIndexAt(idx);
+    int nameAndTypeIdx    = cp.getTagAt(idx).isNameAndType() ? idx : cp.getNameAndTypeRefIndexAt(idx);
     int signatureIdx      = cp.getSignatureRefIndexAt(nameAndTypeIdx);
     Symbol signature      = cp.getSymbolAt(signatureIdx);
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Wed Jul 05 17:17:57 2017 +0200
@@ -40,6 +40,19 @@
     public static final int JVM_CONSTANT_Methodref          = 10;
     public static final int JVM_CONSTANT_InterfaceMethodref = 11;
     public static final int JVM_CONSTANT_NameAndType        = 12;
+    public static final int JVM_CONSTANT_MethodHandle       = 15;
+    public static final int JVM_CONSTANT_MethodType         = 16;
+
+    // JVM_CONSTANT_MethodHandle subtypes
+    public static final int JVM_REF_getField                = 1;
+    public static final int JVM_REF_getStatic               = 2;
+    public static final int JVM_REF_putField                = 3;
+    public static final int JVM_REF_putStatic               = 4;
+    public static final int JVM_REF_invokeVirtual           = 5;
+    public static final int JVM_REF_invokeStatic            = 6;
+    public static final int JVM_REF_invokeSpecial           = 7;
+    public static final int JVM_REF_newInvokeSpecial        = 8;
+    public static final int JVM_REF_invokeInterface         = 9;
 
     // HotSpot specific constant pool constant types.
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java	Wed Jul 05 17:17:57 2017 +0200
@@ -54,14 +54,34 @@
 
     }
 
-    protected short getConstantPoolIndex(int bci) {
+    protected short getConstantPoolIndex(int rawcode, int bci) {
        // get ConstantPool index from ConstantPoolCacheIndex at given bci
-       short cpCacheIndex = method.getBytecodeShortArg(bci);
+       String fmt = Bytecodes.format(rawcode);
+       int cpCacheIndex;
+       switch (fmt.length()) {
+       case 2: cpCacheIndex = method.getBytecodeByteArg(bci); break;
+       case 3: cpCacheIndex = method.getBytecodeShortArg(bci); break;
+       case 5:
+           if (fmt.indexOf("__") >= 0)
+               cpCacheIndex = method.getBytecodeShortArg(bci);
+           else
+               cpCacheIndex = method.getBytecodeIntArg(bci);
+           break;
+       default: throw new IllegalArgumentException();
+       }
        if (cpCache == null) {
-          return cpCacheIndex;
+          return (short) cpCacheIndex;
+       } else if (fmt.indexOf("JJJJ") >= 0) {
+          // change byte-ordering and go via secondary cache entry
+          return (short) cpCache.getMainEntryAt(bytes.swapInt(cpCacheIndex)).getConstantPoolIndex();
+       } else if (fmt.indexOf("JJ") >= 0) {
+          // change byte-ordering and go via cache
+          return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort((short)cpCacheIndex))).getConstantPoolIndex();
+       } else if (fmt.indexOf("j") >= 0) {
+          // go via cache
+          return (short) cpCache.getEntryAt((int) (0xFF & cpCacheIndex)).getConstantPoolIndex();
        } else {
-          // change byte-ordering and go via cache
-          return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort(cpCacheIndex))).getConstantPoolIndex();
+          return (short) cpCacheIndex;
        }
     }
 
@@ -100,10 +120,31 @@
                 case Bytecodes._invokespecial:
                 case Bytecodes._invokestatic:
                 case Bytecodes._invokeinterface: {
-                    cpoolIndex = getConstantPoolIndex(bci + 1);
+                    cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
                     writeShort(code, bci + 1, cpoolIndex);
                     break;
                 }
+
+                case Bytecodes._invokedynamic:
+                    cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
+                    writeShort(code, bci + 1, cpoolIndex);
+                    writeShort(code, bci + 3, (short)0);  // clear out trailing bytes
+                    break;
+
+                case Bytecodes._ldc_w:
+                    if (hotspotcode != bytecode) {
+                        // fast_aldc_w puts constant in CP cache
+                        cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
+                        writeShort(code, bci + 1, cpoolIndex);
+                    }
+                    break;
+                case Bytecodes._ldc:
+                    if (hotspotcode != bytecode) {
+                        // fast_aldc puts constant in CP cache
+                        cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
+                        code[bci + 1] = (byte)(cpoolIndex);
+                    }
+                    break;
             }
 
             len = Bytecodes.lengthFor(bytecode);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Wed Jul 05 17:17:57 2017 +0200
@@ -61,10 +61,12 @@
     protected short  _signatureIndex;
 
     protected static int extractHighShortFromInt(int val) {
+        // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
         return (val >> 16) & 0xFFFF;
     }
 
     protected static int extractLowShortFromInt(int val) {
+        // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
         return val & 0xFFFF;
     }
 
@@ -297,6 +299,28 @@
                                         + ", type = " + signatureIndex);
                      break;
                 }
+
+                case JVM_CONSTANT_MethodHandle: {
+                     dos.writeByte(cpConstType);
+                     int value = cpool.getIntAt(ci);
+                     short refIndex = (short) extractHighShortFromInt(value);
+                     byte  refKind  = (byte)  extractLowShortFromInt(value);
+                     dos.writeByte(refKind);
+                     dos.writeShort(refIndex);
+                     if (DEBUG) debugMessage("CP[" + ci + "] = MH index = " + refIndex
+                                        + ", kind = " + refKind);
+                     break;
+                }
+
+                case JVM_CONSTANT_MethodType: {
+                     dos.writeByte(cpConstType);
+                     int value = cpool.getIntAt(ci);
+                     short refIndex = (short) value;
+                     dos.writeShort(refIndex);
+                     if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex);
+                     break;
+                }
+
                 default:
                   throw new InternalError("Unknown tag: " + cpConstType);
             } // switch
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Wed Jul 05 17:17:57 2017 +0200
@@ -572,6 +572,16 @@
                buf.cell(Integer.toString(cpool.getIntAt(index)));
                break;
 
+            case JVM_CONSTANT_MethodHandle:
+               buf.cell("JVM_CONSTANT_MethodHandle");
+               buf.cell(genLowHighShort(cpool.getIntAt(index)));
+               break;
+
+            case JVM_CONSTANT_MethodType:
+               buf.cell("JVM_CONSTANT_MethodType");
+               buf.cell(Integer.toString(cpool.getIntAt(index)));
+               break;
+
             default:
                throw new InternalError("unknown tag: " + ctag);
          }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Wed Jul 05 17:17:57 2017 +0200
@@ -38,12 +38,26 @@
   private static int JVM_CONSTANT_Methodref               = 10;
   private static int JVM_CONSTANT_InterfaceMethodref      = 11;
   private static int JVM_CONSTANT_NameAndType             = 12;
+  private static int JVM_CONSTANT_MethodHandle            = 15;  // JSR 292
+  private static int JVM_CONSTANT_MethodType              = 16;  // JSR 292
   private static int JVM_CONSTANT_Invalid                 = 0;   // For bad value initialization
   private static int JVM_CONSTANT_UnresolvedClass         = 100; // Temporary tag until actual use
   private static int JVM_CONSTANT_ClassIndex              = 101; // Temporary tag while constructing constant pool
   private static int JVM_CONSTANT_UnresolvedString        = 102; // Temporary tag until actual use
   private static int JVM_CONSTANT_StringIndex             = 103; // Temporary tag while constructing constant pool
   private static int JVM_CONSTANT_UnresolvedClassInError  = 104; // Resolution failed
+  private static int JVM_CONSTANT_Object                  = 105; // Required for BoundMethodHandle arguments.
+
+  // JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure
+  private static int JVM_REF_getField                = 1;
+  private static int JVM_REF_getStatic               = 2;
+  private static int JVM_REF_putField                = 3;
+  private static int JVM_REF_putStatic               = 4;
+  private static int JVM_REF_invokeVirtual           = 5;
+  private static int JVM_REF_invokeStatic            = 6;
+  private static int JVM_REF_invokeSpecial           = 7;
+  private static int JVM_REF_newInvokeSpecial        = 8;
+  private static int JVM_REF_invokeInterface         = 9;
 
   private byte tag;
 
@@ -62,6 +76,8 @@
   public boolean isDouble()           { return tag == JVM_CONSTANT_Double; }
   public boolean isNameAndType()      { return tag == JVM_CONSTANT_NameAndType; }
   public boolean isUtf8()             { return tag == JVM_CONSTANT_Utf8; }
+  public boolean isMethodHandle()     { return tag == JVM_CONSTANT_MethodHandle; }
+  public boolean isMethodType()       { return tag == JVM_CONSTANT_MethodType; }
 
   public boolean isInvalid()          { return tag == JVM_CONSTANT_Invalid; }
 
@@ -73,6 +89,8 @@
   public boolean isUnresolvedString()       { return tag == JVM_CONSTANT_UnresolvedString; }
   public boolean isStringIndex()            { return tag == JVM_CONSTANT_StringIndex; }
 
+  public boolean isObject()                 { return tag == JVM_CONSTANT_Object; }
+
   public boolean isKlassReference()   { return isKlassIndex() || isUnresolvedKlass(); }
   public boolean isFieldOrMethod()    { return isField() || isMethod() || isInterfaceMethod(); }
   public boolean isSymbol()           { return isUtf8(); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Wed Jul 05 17:17:57 2017 +0200
@@ -825,6 +825,8 @@
    }
    writeln("");
    disAsm.decode(new sapkg.interpreter.BytecodeVisitor() {
+                    prologue: function(method) { },
+                    epilogue: function() { },
                     visit: function(bytecode) {
                        if (hasLines) {
                           var line = method.getLineNumberFromBCI(bci);
--- a/hotspot/make/hotspot_version	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/make/hotspot_version	Wed Jul 05 17:17:57 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=19
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=03
+HS_BUILD_NUMBER=04
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/hotspot/make/linux/makefiles/adlc.make	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/make/linux/makefiles/adlc.make	Wed Jul 05 17:17:57 2017 +0200
@@ -138,7 +138,11 @@
 
 # Normally, debugging is done directly on the ad_<arch>*.cpp files.
 # But -g will put #line directives in those files pointing back to <arch>.ad.
+# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives
+# so skip it for 3.2 and ealier.
+ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
 ADLCFLAGS += -g
+endif
 
 ifdef LP64
 ADLCFLAGS += -D_LP64
--- a/hotspot/make/linux/makefiles/sa.make	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/make/linux/makefiles/sa.make	Wed Jul 05 17:17:57 2017 +0200
@@ -40,6 +40,9 @@
 # tools.jar is needed by the JDI - SA binding
 SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
 
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
 # gnumake 3.78.1 does not accept the *s that
 # are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
 AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
@@ -65,7 +68,7 @@
 	  echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
 	  exit 1; \
 	fi
-	$(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \
+	$(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
 	  echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
 	  echo ""; \
 	  exit 1; \
--- a/hotspot/make/solaris/makefiles/sa.make	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/make/solaris/makefiles/sa.make	Wed Jul 05 17:17:57 2017 +0200
@@ -36,6 +36,9 @@
 # tools.jar is needed by the JDI - SA binding
 SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar
 
+# TODO: if it's a modules image, check if SA module is installed.
+MODULELIB_PATH= $(BOOT_JAVA_HOME)/lib/modules
+
 # gnumake 3.78.1 does not accept the *s that
 # are in AGENT_FILES1 and AGENT_FILES2, so use the shell to expand them
 AGENT_FILES1 := $(shell /usr/bin/test -d $(AGENT_DIR) && /bin/ls $(AGENT_FILES1))
@@ -59,7 +62,7 @@
 	   echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \
 	   exit 1; \
 	fi
-	$(QUIETLY) if [ ! -f $(SA_CLASSPATH) ] ; then \
+	$(QUIETLY) if [ ! -f $(SA_CLASSPATH) -a ! -d $(MODULELIB_PATH) ] ; then \
 	  echo "Missing $(SA_CLASSPATH) file. Use 1.6.0 or later version of JDK";\
 	  echo ""; \
 	  exit 1; \
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -318,6 +318,31 @@
   __ bind(exit);
 }
 
+// Fast path for caching oop constants.
+// %%% We should use this to handle Class and String constants also.
+// %%% It will simplify the ldc/primitive path considerably.
+void TemplateTable::fast_aldc(bool wide) {
+  transition(vtos, atos);
+
+  if (!EnableMethodHandles) {
+    // We should not encounter this bytecode if !EnableMethodHandles.
+    // The verifier will stop it.  However, if we get past the verifier,
+    // this will stop the thread in a reasonable way, without crashing the JVM.
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+                     InterpreterRuntime::throw_IncompatibleClassChangeError));
+    // the call_VM checks for exception, so we should never return here.
+    __ should_not_reach_here();
+    return;
+  }
+
+  Register Rcache = G3_scratch;
+  Register Rscratch = G4_scratch;
+
+  resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1));
+
+  __ verify_oop(Otos_i);
+}
+
 void TemplateTable::ldc2_w() {
   transition(vtos, vtos);
   Label retry, resolved, Long, exit;
@@ -1994,6 +2019,8 @@
     case Bytecodes::_invokestatic   : // fall through
     case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);  break;
     case Bytecodes::_invokedynamic  : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);  break;
+    case Bytecodes::_fast_aldc      : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);     break;
+    case Bytecodes::_fast_aldc_w    : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);     break;
     default                         : ShouldNotReachHere();                                 break;
   }
   // first time invocation - must resolve first
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -375,6 +375,32 @@
   __ bind(Done);
 }
 
+// Fast path for caching oop constants.
+// %%% We should use this to handle Class and String constants also.
+// %%% It will simplify the ldc/primitive path considerably.
+void TemplateTable::fast_aldc(bool wide) {
+  transition(vtos, atos);
+
+  if (!EnableMethodHandles) {
+    // We should not encounter this bytecode if !EnableMethodHandles.
+    // The verifier will stop it.  However, if we get past the verifier,
+    // this will stop the thread in a reasonable way, without crashing the JVM.
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+                     InterpreterRuntime::throw_IncompatibleClassChangeError));
+    // the call_VM checks for exception, so we should never return here.
+    __ should_not_reach_here();
+    return;
+  }
+
+  const Register cache = rcx;
+  const Register index = rdx;
+
+  resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1));
+  if (VerifyOops) {
+    __ verify_oop(rax);
+  }
+}
+
 void TemplateTable::ldc2_w() {
   transition(vtos, vtos);
   Label Long, Done;
@@ -2055,6 +2081,8 @@
     case Bytecodes::_invokestatic   : // fall through
     case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);  break;
     case Bytecodes::_invokedynamic  : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
+    case Bytecodes::_fast_aldc      : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);     break;
+    case Bytecodes::_fast_aldc_w    : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);     break;
     default                         : ShouldNotReachHere();                                 break;
   }
   __ movl(temp, (int)bytecode());
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -389,6 +389,32 @@
   __ bind(Done);
 }
 
+// Fast path for caching oop constants.
+// %%% We should use this to handle Class and String constants also.
+// %%% It will simplify the ldc/primitive path considerably.
+void TemplateTable::fast_aldc(bool wide) {
+  transition(vtos, atos);
+
+  if (!EnableMethodHandles) {
+    // We should not encounter this bytecode if !EnableMethodHandles.
+    // The verifier will stop it.  However, if we get past the verifier,
+    // this will stop the thread in a reasonable way, without crashing the JVM.
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+                     InterpreterRuntime::throw_IncompatibleClassChangeError));
+    // the call_VM checks for exception, so we should never return here.
+    __ should_not_reach_here();
+    return;
+  }
+
+  const Register cache = rcx;
+  const Register index = rdx;
+
+  resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1));
+  if (VerifyOops) {
+    __ verify_oop(rax);
+  }
+}
+
 void TemplateTable::ldc2_w() {
   transition(vtos, vtos);
   Label Long, Done;
@@ -2063,6 +2089,12 @@
   case Bytecodes::_invokedynamic:
     entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
     break;
+  case Bytecodes::_fast_aldc:
+    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
+    break;
+  case Bytecodes::_fast_aldc_w:
+    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
+    break;
   default:
     ShouldNotReachHere();
     break;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -34,7 +34,7 @@
 VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
 
 static BufferBlob* stub_blob;
-static const int stub_size = 300;
+static const int stub_size = 400;
 
 extern "C" {
   typedef void (*getPsrInfo_stub_t)(void*);
@@ -56,7 +56,7 @@
     const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
     const uint32_t CPU_FAMILY_486   = (4 << CPU_FAMILY_SHIFT);
 
-    Label detect_486, cpu486, detect_586, std_cpuid1;
+    Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
     Label ext_cpuid1, ext_cpuid5, done;
 
     StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
@@ -131,13 +131,62 @@
     __ movl(Address(rsi, 8), rcx);
     __ movl(Address(rsi,12), rdx);
 
-    __ cmpl(rax, 3);     // Is cpuid(0x4) supported?
-    __ jccb(Assembler::belowEqual, std_cpuid1);
+    __ cmpl(rax, 0xa);                  // Is cpuid(0xB) supported?
+    __ jccb(Assembler::belowEqual, std_cpuid4);
+
+    //
+    // cpuid(0xB) Processor Topology
+    //
+    __ movl(rax, 0xb);
+    __ xorl(rcx, rcx);   // Threads level
+    __ cpuid();
+
+    __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB0_offset())));
+    __ movl(Address(rsi, 0), rax);
+    __ movl(Address(rsi, 4), rbx);
+    __ movl(Address(rsi, 8), rcx);
+    __ movl(Address(rsi,12), rdx);
+
+    __ movl(rax, 0xb);
+    __ movl(rcx, 1);     // Cores level
+    __ cpuid();
+    __ push(rax);
+    __ andl(rax, 0x1f);  // Determine if valid topology level
+    __ orl(rax, rbx);    // eax[4:0] | ebx[0:15] == 0 indicates invalid level
+    __ andl(rax, 0xffff);
+    __ pop(rax);
+    __ jccb(Assembler::equal, std_cpuid4);
+
+    __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB1_offset())));
+    __ movl(Address(rsi, 0), rax);
+    __ movl(Address(rsi, 4), rbx);
+    __ movl(Address(rsi, 8), rcx);
+    __ movl(Address(rsi,12), rdx);
+
+    __ movl(rax, 0xb);
+    __ movl(rcx, 2);     // Packages level
+    __ cpuid();
+    __ push(rax);
+    __ andl(rax, 0x1f);  // Determine if valid topology level
+    __ orl(rax, rbx);    // eax[4:0] | ebx[0:15] == 0 indicates invalid level
+    __ andl(rax, 0xffff);
+    __ pop(rax);
+    __ jccb(Assembler::equal, std_cpuid4);
+
+    __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB2_offset())));
+    __ movl(Address(rsi, 0), rax);
+    __ movl(Address(rsi, 4), rbx);
+    __ movl(Address(rsi, 8), rcx);
+    __ movl(Address(rsi,12), rdx);
 
     //
     // cpuid(0x4) Deterministic cache params
     //
+    __ bind(std_cpuid4);
     __ movl(rax, 4);
+    __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x4) supported?
+    __ jccb(Assembler::greater, std_cpuid1);
+
     __ xorl(rcx, rcx);   // L1 cache
     __ cpuid();
     __ push(rax);
@@ -460,13 +509,18 @@
   AllocatePrefetchDistance = allocate_prefetch_distance();
   AllocatePrefetchStyle    = allocate_prefetch_style();
 
-  if( AllocatePrefetchStyle == 2 && is_intel() &&
-      cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core
+  if( is_intel() && cpu_family() == 6 && supports_sse3() ) {
+    if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core
 #ifdef _LP64
-    AllocatePrefetchDistance = 384;
+      AllocatePrefetchDistance = 384;
 #else
-    AllocatePrefetchDistance = 320;
+      AllocatePrefetchDistance = 320;
 #endif
+    }
+    if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus
+      AllocatePrefetchDistance = 192;
+      AllocatePrefetchLines = 4;
+    }
   }
   assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
 
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -114,6 +114,14 @@
     } bits;
   };
 
+  union TplCpuidBEbx {
+    uint32_t value;
+    struct {
+      uint32_t logical_cpus : 16,
+                            : 16;
+    } bits;
+  };
+
   union ExtCpuid1Ecx {
     uint32_t value;
     struct {
@@ -211,6 +219,25 @@
     uint32_t     dcp_cpuid4_ecx; // unused currently
     uint32_t     dcp_cpuid4_edx; // unused currently
 
+    // cpuid function 0xB (processor topology)
+    // ecx = 0
+    uint32_t     tpl_cpuidB0_eax;
+    TplCpuidBEbx tpl_cpuidB0_ebx;
+    uint32_t     tpl_cpuidB0_ecx; // unused currently
+    uint32_t     tpl_cpuidB0_edx; // unused currently
+
+    // ecx = 1
+    uint32_t     tpl_cpuidB1_eax;
+    TplCpuidBEbx tpl_cpuidB1_ebx;
+    uint32_t     tpl_cpuidB1_ecx; // unused currently
+    uint32_t     tpl_cpuidB1_edx; // unused currently
+
+    // ecx = 2
+    uint32_t     tpl_cpuidB2_eax;
+    TplCpuidBEbx tpl_cpuidB2_ebx;
+    uint32_t     tpl_cpuidB2_ecx; // unused currently
+    uint32_t     tpl_cpuidB2_edx; // unused currently
+
     // cpuid function 0x80000000 // example, unused
     uint32_t ext_max_function;
     uint32_t ext_vendor_name_0;
@@ -316,6 +343,9 @@
   static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
   static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
   static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
+  static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); }
+  static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
+  static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
 
   // Initialization
   static void initialize();
@@ -346,10 +376,22 @@
   static bool is_amd()            { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
   static bool is_intel()          { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
 
+  static bool supports_processor_topology() {
+    return (_cpuid_info.std_max_function >= 0xB) &&
+           // eax[4:0] | ebx[0:15] == 0 indicates invalid topology level.
+           // Some cpus have max cpuid >= 0xB but do not support processor topology.
+           ((_cpuid_info.tpl_cpuidB0_eax & 0x1f | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0);
+  }
+
   static uint cores_per_cpu()  {
     uint result = 1;
     if (is_intel()) {
-      result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
+      if (supports_processor_topology()) {
+        result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
+                 _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
+      } else {
+        result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
+      }
     } else if (is_amd()) {
       result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1);
     }
@@ -358,7 +400,9 @@
 
   static uint threads_per_core()  {
     uint result = 1;
-    if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
+    if (is_intel() && supports_processor_topology()) {
+      result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
+    } else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
       result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
                cores_per_cpu();
     }
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -820,7 +820,7 @@
                                            bool      is_top_frame) {
   assert(popframe_extra_args == 0, "what to do?");
   assert(!is_top_frame || (!callee_locals && !callee_param_count),
-         "top frame should have no caller")
+         "top frame should have no caller");
 
   // This code must exactly match what InterpreterFrame::build
   // does (the full InterpreterFrame::build, that is, not the
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -2079,9 +2079,9 @@
 static char saved_jvm_path[MAXPATHLEN] = {0};
 
 // Find the full path to the current module, libjvm.so or libjvm_g.so
-void os::jvm_path(char *buf, jint len) {
+void os::jvm_path(char *buf, jint buflen) {
   // Error checking.
-  if (len < MAXPATHLEN) {
+  if (buflen < MAXPATHLEN) {
     assert(false, "must use a large-enough buffer");
     buf[0] = '\0';
     return;
@@ -2117,6 +2117,9 @@
       // Look for JAVA_HOME in the environment.
       char* java_home_var = ::getenv("JAVA_HOME");
       if (java_home_var != NULL && java_home_var[0] != 0) {
+        char* jrelib_p;
+        int len;
+
         // Check the current module name "libjvm.so" or "libjvm_g.so".
         p = strrchr(buf, '/');
         assert(strstr(p, "/libjvm") == p, "invalid library name");
@@ -2124,14 +2127,24 @@
 
         if (realpath(java_home_var, buf) == NULL)
           return;
-        sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch);
+
+        // determine if this is a legacy image or modules image
+        // modules image doesn't have "jre" subdirectory
+        len = strlen(buf);
+        jrelib_p = buf + len;
+        snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+        if (0 != access(buf, F_OK)) {
+          snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+        }
+
         if (0 == access(buf, F_OK)) {
           // Use current module name "libjvm[_g].so" instead of
           // "libjvm"debug_only("_g")".so" since for fastdebug version
           // we should have "libjvm.so" but debug_only("_g") adds "_g"!
           // It is used when we are choosing the HPI library's name
           // "libhpi[_g].so" in hpi::initialize_get_interface().
-          sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p);
+          len = strlen(buf);
+          snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
         } else {
           // Go back to path of .so
           if (realpath(dli_fname, buf) == NULL)
--- a/hotspot/src/os/linux/vm/vtune_linux.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 1999, 2007, 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.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_linux.cpp.incl"
-
-// empty implementation
-
-void VTune::start_GC() {}
-void VTune::end_GC() {}
-void VTune::start_class_load() {}
-void VTune::end_class_load() {}
-void VTune::exit() {}
-void VTune::register_stub(const char* name, address start, address end) {}
-
-void VTune::create_nmethod(nmethod* nm) {}
-void VTune::delete_nmethod(nmethod* nm) {}
-
-void vtune_init() {}
-
-
-// Reconciliation History
-// vtune_solaris.cpp    1.8 99/07/12 23:54:21
-// End
--- a/hotspot/src/os/solaris/vm/osThread_solaris.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os/solaris/vm/osThread_solaris.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -123,7 +123,7 @@
 
   int set_interrupt_callback    (Sync_Interrupt_Callback * cb);
   void remove_interrupt_callback(Sync_Interrupt_Callback * cb);
-  void OSThread::do_interrupt_callbacks_at_interrupt(InterruptArguments *args);
+  void do_interrupt_callbacks_at_interrupt(InterruptArguments *args);
 
  // ***************************************************************
  // java.lang.Thread.interrupt state.
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -2435,6 +2435,8 @@
       char* java_home_var = ::getenv("JAVA_HOME");
       if (java_home_var != NULL && java_home_var[0] != 0) {
         char cpu_arch[12];
+        char* jrelib_p;
+        int   len;
         sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof(cpu_arch));
 #ifdef _LP64
         // If we are on sparc running a 64-bit vm, look in jre/lib/sparcv9.
@@ -2450,14 +2452,23 @@
         p = strstr(p, "_g") ? "_g" : "";
 
         realpath(java_home_var, buf);
-        sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch);
+        // determine if this is a legacy image or modules image
+        // modules image doesn't have "jre" subdirectory
+        len = strlen(buf);
+        jrelib_p = buf + len;
+        snprintf(jrelib_p, buflen-len, "/jre/lib/%s", cpu_arch);
+        if (0 != access(buf, F_OK)) {
+          snprintf(jrelib_p, buflen-len, "/lib/%s", cpu_arch);
+        }
+
         if (0 == access(buf, F_OK)) {
           // Use current module name "libjvm[_g].so" instead of
           // "libjvm"debug_only("_g")".so" since for fastdebug version
           // we should have "libjvm.so" but debug_only("_g") adds "_g"!
           // It is used when we are choosing the HPI library's name
           // "libhpi[_g].so" in hpi::initialize_get_interface().
-          sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p);
+          len = strlen(buf);
+          snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
         } else {
           // Go back to path of .so
           realpath((char *)dlinfo.dli_fname, buf);
--- a/hotspot/src/os/solaris/vm/vtune_solaris.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_solaris.cpp.incl"
-
-// empty implementation
-
-void VTune::start_GC() {}
-void VTune::end_GC() {}
-void VTune::start_class_load() {}
-void VTune::end_class_load() {}
-void VTune::exit() {}
-void VTune::register_stub(const char* name, address start, address end) {}
-
-void VTune::create_nmethod(nmethod* nm) {}
-void VTune::delete_nmethod(nmethod* nm) {}
-
-void vtune_init() {}
--- a/hotspot/src/os/windows/vm/vtune_windows.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.
- *
- */
-
-#include "incls/_precompiled.incl"
-#include "incls/_vtune_windows.cpp.incl"
-
-static int current_method_ID = 0;
-
-// ------------- iJITProf.h -------------------
-// defined by Intel -- do not change
-
-#include "windows.h"
-
-extern "C" {
-  enum iJITP_Event {
-    ExceptionOccurred_S,                  // Java exception
-    ExceptionOccurred_IDS,
-
-    Shutdown,                             // VM exit
-
-    ThreadCreate,                         // threads
-    ThreadDestroy,
-    ThreadSwitch,
-
-    ClassLoadStart,                       // class loading
-    ClassLoadEnd,
-
-    GCStart,                              // GC
-    GCEnd,
-
-    NMethodCreate = 13,                   // nmethod creation
-    NMethodDelete
-
-    // rest of event types omitted (call profiling not supported yet)
-  };
-
-  // version number -- 0 if VTune not installed
-  int WINAPI iJitP_VersionNumber();
-
-  enum iJITP_ModeFlags {
-    NoNotification = 0x0,                // don't call vtune
-    NotifyNMethodCreate   = 0x1,         // notify NMethod_Create
-    NotifyNMethodDelete   = 0x2,         // notify NMethod_Create
-    NotifyMethodEnter     = 0x4,         // method entry
-    NotifyMethodExit      = 0x8,         // method exit
-    NotifyShutdown        = 0x10,        // VM exit
-    NotifyGC              = 0x20,        // GC
-  };
-
-  // call back function type
-  typedef void (WINAPI *ModeChangedFn)(iJITP_ModeFlags flags);
-
-  // -------------  VTune method interfaces ----------------------
-  typedef void  (WINAPI *RegisterCallbackFn)(ModeChangedFn fn);   // register callback
-  typedef int   (WINAPI *NotifyEventFn)(iJITP_Event, void* event_data);
-
-  // specific event data structures
-
-  // data for NMethodCreate
-
-  struct VTuneObj {                       // base class for allocation
-                                          // (can't use CHeapObj -- has vtable ptr)
-    void* operator new(size_t size) { return os::malloc(size); }
-    void  operator delete(void* p)  { fatal("never delete VTune data"); }
-  };
-
-  struct LineNumberInfo : VTuneObj {      // PC-to-line number mapping
-    unsigned long offset;                 // byte offset from start of method
-    unsigned long line_num;               // corresponding line number
-  };
-
-  struct MethodLoadInfo : VTuneObj {
-    unsigned long methodID;               // unique method ID
-    const char* name;                     // method name
-    unsigned long instr_start;            // start address
-    unsigned long instr_size;             // length in bytes
-    unsigned long line_number_size;       // size of line number table
-    LineNumberInfo* line_number_table;    // line number mapping
-    unsigned long classID;                // unique class ID
-    char* class_file_name;                // fully qualified class file name
-    char* source_file_name;               // fully qualified source file name
-
-    MethodLoadInfo(nmethod* nm);          // for real nmethods
-    MethodLoadInfo(const char* vm_name, address start, address end);
-                                          // for "nmethods" like stubs, interpreter, etc
-
-  };
-
-  // data for NMethodDelete
-  struct MethodInfo : VTuneObj {
-    unsigned long methodID;               // unique method ID
-    unsigned long classID;                // (added for convenience -- not part of Intel interface)
-
-    MethodInfo(methodOop m);
-  };
-};
-
-MethodInfo::MethodInfo(methodOop m) {
-  // just give it a new ID -- we're not compiling methods twice (usually)
-  // (and even if we did, one might want to see the two versions separately)
-  methodID = ++current_method_ID;
-}
-
-MethodLoadInfo::MethodLoadInfo(const char* vm_name, address start, address end) {
-  classID  = 0;
-  methodID = ++current_method_ID;
-  name = vm_name;
-  instr_start = (unsigned long)start;
-  instr_size = end - start;
-  line_number_size = 0;
-  line_number_table = NULL;
-  class_file_name = source_file_name = "HotSpot JVM";
-}
-
-MethodLoadInfo::MethodLoadInfo(nmethod* nm) {
-  methodOop m = nm->method();
-  MethodInfo info(m);
-  classID  = info.classID;
-  methodID = info.methodID;
-  name = strdup(m->name()->as_C_string());
-  instr_start = (unsigned long)nm->instructions_begin();
-  instr_size = nm->code_size();
-  line_number_size = 0;
-  line_number_table = NULL;
-  klassOop kl = m->method_holder();
-  char* class_name = Klass::cast(kl)->name()->as_C_string();
-  char* file_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + 1);
-  strcpy(file_name, class_name);
-  class_file_name = file_name;
-  char* src_name = NEW_C_HEAP_ARRAY(char, strlen(class_name) + strlen(".java") + 1);
-  strcpy(src_name, class_name);
-  strcat(src_name, ".java");
-  source_file_name = src_name;
-}
-
-// --------------------- DLL loading functions ------------------------
-
-#define DLLNAME "iJitProf.dll"
-
-static HINSTANCE load_lib(char* name) {
-  HINSTANCE lib = NULL;
-  HKEY hk;
-
-  // try to get VTune directory from the registry
-  if (RegOpenKey(HKEY_CURRENT_USER, "Software\\VB and VBA Program Settings\\VTune\\StartUp", &hk) == ERROR_SUCCESS) {
-    for (int i = 0; true; i++) {
-      char szName[MAX_PATH + 1];
-      char szVal [MAX_PATH + 1];
-      DWORD cbName, cbVal;
-
-      cbName = cbVal = MAX_PATH + 1;
-      if (RegEnumValue(hk, i, szName, &cbName, NULL, NULL, (LPBYTE)szVal, &cbVal) == ERROR_SUCCESS) {
-        // get VTune directory
-        if (!strcmp(szName, name)) {
-          char*p = szVal;
-          while (*p == ' ') p++;    // trim
-          char* q = p + strlen(p) - 1;
-          while (*q == ' ') *(q--) = '\0';
-
-          // chdir to the VTune dir
-          GetCurrentDirectory(MAX_PATH + 1, szName);
-          SetCurrentDirectory(p);
-          // load lib
-          lib = LoadLibrary(strcat(strcat(p, "\\"), DLLNAME));
-          if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s", p);
-          // restore current dir
-          SetCurrentDirectory(szName);
-          break;
-        }
-      } else {
-        break;
-      }
-    }
-  }
-  return lib;
-}
-
-static RegisterCallbackFn iJIT_RegisterCallback = NULL;
-static NotifyEventFn      iJIT_NotifyEvent      = NULL;
-
-static bool load_iJIT_funcs() {
-  // first try to load from PATH
-  HINSTANCE lib = LoadLibrary(DLLNAME);
-  if (lib != NULL && WizardMode) tty->print_cr("*loaded VTune DLL %s via PATH", DLLNAME);
-
-  // if not successful, try to look in the VTUNE directory
-  if (lib == NULL) lib = load_lib("VTUNEDIR30");
-  if (lib == NULL) lib = load_lib("VTUNEDIR25");
-  if (lib == NULL) lib = load_lib("VTUNEDIR");
-
-  if (lib == NULL) return false;    // unsuccessful
-
-  // try to load the functions
-  iJIT_RegisterCallback = (RegisterCallbackFn)GetProcAddress(lib, "iJIT_RegisterCallback");
-  iJIT_NotifyEvent      = (NotifyEventFn)     GetProcAddress(lib, "iJIT_NotifyEvent");
-
-  if (!iJIT_RegisterCallback) tty->print_cr("*couldn't find VTune entry point iJIT_RegisterCallback");
-  if (!iJIT_NotifyEvent)      tty->print_cr("*couldn't find VTune entry point iJIT_NotifyEvent");
-  return iJIT_RegisterCallback != NULL && iJIT_NotifyEvent != NULL;
-}
-
-// --------------------- VTune class ------------------------
-
-static bool active = false;
-static int  flags  = 0;
-
-void VTune::start_GC() {
-  if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCStart, NULL);
-}
-
-void VTune::end_GC() {
-  if (active && (flags & NotifyGC)) iJIT_NotifyEvent(GCEnd, NULL);
-}
-
-void VTune::start_class_load() {
-  // not yet implemented in VTune
-}
-
-void VTune::end_class_load() {
-  // not yet implemented in VTune
-}
-
-void VTune::exit() {
-  if (active && (flags & NotifyShutdown)) iJIT_NotifyEvent(Shutdown, NULL);
-}
-
-void VTune::register_stub(const char* name, address start, address end) {
-  if (flags & NotifyNMethodCreate) {
-    MethodLoadInfo* info = new MethodLoadInfo(name, start, end);
-    if (PrintMiscellaneous && WizardMode && Verbose) {
-      tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
-                    info->instr_start, info->instr_start + info->instr_size);
-    }
-    iJIT_NotifyEvent(NMethodCreate, info);
-  }
-}
-
-void VTune::create_nmethod(nmethod* nm) {
-  if (flags & NotifyNMethodCreate) {
-    MethodLoadInfo* info = new MethodLoadInfo(nm);
-    if (PrintMiscellaneous && WizardMode && Verbose) {
-      tty->print_cr("NMethodCreate %s (%d): %#x..%#x", info->name, info->methodID,
-                    info->instr_start, info->instr_start + info->instr_size);
-    }
-    iJIT_NotifyEvent(NMethodCreate, info);
-  }
-}
-
-void VTune::delete_nmethod(nmethod* nm) {
-  if (flags & NotifyNMethodDelete) {
-    MethodInfo* info = new MethodInfo(nm->method());
-    iJIT_NotifyEvent(NMethodDelete, info);
-  }
-}
-
-static void set_flags(int new_flags) {
-  flags = new_flags;
-  // if (WizardMode) tty->print_cr("*new VTune flags: %#x", flags);
-}
-
-void vtune_init() {
-  if (!UseVTune) return;
-  active = load_iJIT_funcs();
-  if (active) {
-    iJIT_RegisterCallback((ModeChangedFn)set_flags);
-  } else {
-    assert(flags == 0, "flags shouldn't be set");
-  }
-}
--- a/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -26,7 +26,7 @@
 #ifdef AMD64
   (void)memmove(to, from, count * HeapWordSize);
 #else
-  // Same as pd_aligned_conjoint_words, except includes a zero-count check.
+  // Includes a zero-count check.
   intx temp;
   __asm__ volatile("        testl   %6,%6         ;"
                    "        jz      7f            ;"
@@ -84,7 +84,7 @@
     break;
   }
 #else
-  // Same as pd_aligned_disjoint_words, except includes a zero-count check.
+  // Includes a zero-count check.
   intx temp;
   __asm__ volatile("        testl   %6,%6       ;"
                    "        jz      3f          ;"
@@ -130,75 +130,18 @@
 }
 
 static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
-#ifdef AMD64
-  (void)memmove(to, from, count * HeapWordSize);
-#else
-  // Same as pd_conjoint_words, except no zero-count check.
-  intx temp;
-  __asm__ volatile("        cmpl    %4,%5         ;"
-                   "        leal    -4(%4,%6,4),%3;"
-                   "        jbe     1f            ;"
-                   "        cmpl    %7,%5         ;"
-                   "        jbe     4f            ;"
-                   "1:      cmpl    $32,%6        ;"
-                   "        ja      3f            ;"
-                   "        subl    %4,%1         ;"
-                   "2:      movl    (%4),%3       ;"
-                   "        movl    %7,(%5,%4,1)  ;"
-                   "        addl    $4,%0         ;"
-                   "        subl    $1,%2          ;"
-                   "        jnz     2b            ;"
-                   "        jmp     7f            ;"
-                   "3:      rep;    smovl         ;"
-                   "        jmp     7f            ;"
-                   "4:      cmpl    $32,%2        ;"
-                   "        movl    %7,%0         ;"
-                   "        leal    -4(%5,%6,4),%1;"
-                   "        ja      6f            ;"
-                   "        subl    %4,%1         ;"
-                   "5:      movl    (%4),%3       ;"
-                   "        movl    %7,(%5,%4,1)  ;"
-                   "        subl    $4,%0         ;"
-                   "        subl    $1,%2          ;"
-                   "        jnz     5b            ;"
-                   "        jmp     7f            ;"
-                   "6:      std                   ;"
-                   "        rep;    smovl         ;"
-                   "        cld                   ;"
-                   "7:      nop                    "
-                   : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
-                   : "0"  (from), "1"  (to), "2"  (count), "3"  (temp)
-                   : "memory", "flags");
-#endif // AMD64
+  pd_conjoint_words(from, to, count);
 }
 
 static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
-#ifdef AMD64
   pd_disjoint_words(from, to, count);
-#else
-  // Same as pd_disjoint_words, except no zero-count check.
-  intx temp;
-  __asm__ volatile("        cmpl    $32,%6      ;"
-                   "        ja      2f          ;"
-                   "        subl    %4,%1       ;"
-                   "1:      movl    (%4),%3     ;"
-                   "        movl    %7,(%5,%4,1);"
-                   "        addl    $4,%0       ;"
-                   "        subl    $1,%2        ;"
-                   "        jnz     1b          ;"
-                   "        jmp     3f          ;"
-                   "2:      rep;    smovl       ;"
-                   "3:      nop                  "
-                   : "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
-                   : "0"  (from), "1"  (to), "2"  (count), "3"  (temp)
-                   : "memory", "cc");
-#endif // AMD64
 }
 
 static void pd_conjoint_bytes(void* from, void* to, size_t count) {
 #ifdef AMD64
   (void)memmove(to, from, count);
 #else
+  // Includes a zero-count check.
   intx temp;
   __asm__ volatile("        testl   %6,%6          ;"
                    "        jz      13f            ;"
--- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s	Wed Jul 05 17:17:57 2017 +0200
@@ -121,10 +121,10 @@
         jnz      3b
         addl     %esi,%edi
 4:      movl     %eax,%ecx            # byte count less prefix
-        andl     $3,%ecx              # suffix byte count
+5:      andl     $3,%ecx              # suffix byte count
         jz       7f                   # no suffix
         # copy suffix
-5:      xorl     %eax,%eax
+        xorl     %eax,%eax
 6:      movb     (%esi,%eax,1),%dl
         movb     %dl,(%edi,%eax,1)
         addl     $1,%eax
@@ -159,10 +159,10 @@
         # copy dwords, aligned or not
 3:      rep;     smovl
 4:      movl     %eax,%ecx            # byte count
-        andl     $3,%ecx              # suffix byte count
+5:      andl     $3,%ecx              # suffix byte count
         jz       7f                   # no suffix
         # copy suffix
-5:      subl     %esi,%edi
+        subl     %esi,%edi
         addl     $3,%esi
 6:      movb     (%esi),%dl
         movb     %dl,(%edi,%esi,1)
@@ -214,10 +214,10 @@
         # copy aligned dwords
 3:      rep;     smovl
 4:      movl     %eax,%ecx
-        andl     $3,%ecx
+5:      andl     $3,%ecx
         jz       7f
         # copy suffix
-5:      xorl     %eax,%eax
+        xorl     %eax,%eax
 6:      movb     (%esi,%eax,1),%dl
         movb     %dl,(%edi,%eax,1)
         addl     $1,%eax
@@ -250,9 +250,9 @@
         jnz      3b
         addl     %esi,%edi
 4:      movl     %eax,%ecx
-        andl     $3,%ecx
+5:      andl     $3,%ecx
         jz       7f
-5:      subl     %esi,%edi
+        subl     %esi,%edi
         addl     $3,%esi
 6:      movb     (%esi),%dl
         movb     %dl,(%edi,%esi,1)
@@ -287,11 +287,12 @@
         andl     $3,%eax              # either 0 or 2
         jz       1f                   # no prefix
         # copy prefix
+        subl     $1,%ecx
+        jl       5f                   # zero count
         movw     (%esi),%dx
         movw     %dx,(%edi)
         addl     %eax,%esi            # %eax == 2
         addl     %eax,%edi
-        subl     $1,%ecx
 1:      movl     %ecx,%eax            # word count less prefix
         sarl     %ecx                 # dword count
         jz       4f                   # no dwords to move
@@ -454,12 +455,13 @@
         ret
         .=.+10
 2:      subl     %esi,%edi
+        jmp      4f
         .p2align 4,,15
 3:      movl     (%esi),%edx
         movl     %edx,(%edi,%esi,1)
         addl     $4,%esi
-        subl     $1,%ecx
-        jnz      3b
+4:      subl     $1,%ecx
+        jge      3b
         popl     %edi
         popl     %esi
         ret
@@ -467,19 +469,20 @@
         std
         leal     -4(%edi,%ecx,4),%edi # to + count*4 - 4
         cmpl     $32,%ecx
-        ja       3f                   # > 32 dwords
+        ja       4f                   # > 32 dwords
         subl     %eax,%edi            # eax == from + count*4 - 4
+        jmp      3f
         .p2align 4,,15
 2:      movl     (%eax),%edx
         movl     %edx,(%edi,%eax,1)
         subl     $4,%eax
-        subl     $1,%ecx
-        jnz      2b
+3:      subl     $1,%ecx
+        jge      2b
         cld
         popl     %edi
         popl     %esi
         ret
-3:      movl     %eax,%esi            # from + count*4 - 4
+4:      movl     %eax,%esi            # from + count*4 - 4
         rep;     smovl
         cld
         popl     %edi
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -861,7 +861,7 @@
 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
 add_func_t*          os::atomic_add_func          = os::atomic_add_bootstrap;
 
-extern "C" _solaris_raw_setup_fpu(address ptr);
+extern "C" void _solaris_raw_setup_fpu(address ptr);
 void os::setup_fpu() {
   address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
   _solaris_raw_setup_fpu(fpu_cntrl);
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.s	Wed Jul 05 17:17:57 2017 +0200
@@ -154,10 +154,10 @@
         jnz      3b
         addl     %esi,%edi
 4:      movl     %eax,%ecx            / byte count less prefix
-        andl     $3,%ecx              / suffix byte count
+5:      andl     $3,%ecx              / suffix byte count
         jz       7f                   / no suffix
         / copy suffix
-5:      xorl     %eax,%eax
+        xorl     %eax,%eax
 6:      movb     (%esi,%eax,1),%dl
         movb     %dl,(%edi,%eax,1)
         addl     $1,%eax
@@ -192,10 +192,10 @@
         / copy dwords, aligned or not
 3:      rep;     smovl
 4:      movl     %eax,%ecx            / byte count
-        andl     $3,%ecx              / suffix byte count
+5:      andl     $3,%ecx              / suffix byte count
         jz       7f                   / no suffix
         / copy suffix
-5:      subl     %esi,%edi
+        subl     %esi,%edi
         addl     $3,%esi
 6:      movb     (%esi),%dl
         movb     %dl,(%edi,%esi,1)
@@ -246,10 +246,10 @@
         / copy aligned dwords
 3:      rep;     smovl
 4:      movl     %eax,%ecx
-        andl     $3,%ecx
+5:      andl     $3,%ecx
         jz       7f
         / copy suffix
-5:      xorl     %eax,%eax
+        xorl     %eax,%eax
 6:      movb     (%esi,%eax,1),%dl
         movb     %dl,(%edi,%eax,1)
         addl     $1,%eax
@@ -282,9 +282,9 @@
         jnz      3b
         addl     %esi,%edi
 4:      movl     %eax,%ecx
-        andl     $3,%ecx
+5:      andl     $3,%ecx
         jz       7f
-5:      subl     %esi,%edi
+        subl     %esi,%edi
         addl     $3,%esi
 6:      movb     (%esi),%dl
         movb     %dl,(%edi,%esi,1)
@@ -318,11 +318,12 @@
         andl     $3,%eax              / either 0 or 2
         jz       1f                   / no prefix
         / copy prefix
+        subl     $1,%ecx
+        jl       5f                   / zero count
         movw     (%esi),%dx
         movw     %dx,(%edi)
         addl     %eax,%esi            / %eax == 2
         addl     %eax,%edi
-        subl     $1,%ecx
 1:      movl     %ecx,%eax            / word count less prefix
         sarl     %ecx                 / dword count
         jz       4f                   / no dwords to move
@@ -482,12 +483,13 @@
         ret
         .=.+10
 2:      subl     %esi,%edi
+        jmp      4f
         .align   16
 3:      movl     (%esi),%edx
         movl     %edx,(%edi,%esi,1)
         addl     $4,%esi
-        subl     $1,%ecx
-        jnz      3b
+4:      subl     $1,%ecx
+        jge      3b
         popl     %edi
         popl     %esi
         ret
@@ -495,19 +497,20 @@
         std
         leal     -4(%edi,%ecx,4),%edi / to + count*4 - 4
         cmpl     $32,%ecx
-        ja       3f                   / > 32 dwords
+        ja       4f                   / > 32 dwords
         subl     %eax,%edi            / eax == from + count*4 - 4
+        jmp      3f
         .align   16
 2:      movl     (%eax),%edx
         movl     %edx,(%edi,%eax,1)
         subl     $4,%eax
-        subl     $1,%ecx
-        jnz      2b
+3:      subl     $1,%ecx
+        jge      2b
         cld
         popl     %edi
         popl     %esi
         ret
-3:      movl     %eax,%esi            / from + count*4 - 4
+4:      movl     %eax,%esi            / from + count*4 - 4
         rep;     smovl
         cld
         popl     %edi
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -404,7 +404,7 @@
       locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity);
     } else {
       locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
-      Copy::conjoint_bytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
+      Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
       _locs_own = true;
     }
     _locs_start    = locs_start;
@@ -581,7 +581,7 @@
                              (HeapWord*)(buf+buf_offset),
                              (lsize + HeapWordSize-1) / HeapWordSize);
       } else {
-        Copy::conjoint_bytes(lstart, buf+buf_offset, lsize);
+        Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize);
       }
     }
     buf_offset += lsize;
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -242,10 +242,10 @@
   code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
                                         locs_buffer_size / sizeof(relocInfo));
   code->initialize_consts_size(Compilation::desired_max_constant_size());
-  // Call stubs + deopt/exception handler
+  // Call stubs + two deopt handlers (regular and MH) + exception handler
   code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
                               LIR_Assembler::exception_handler_size +
-                              LIR_Assembler::deopt_handler_size);
+                              2 * LIR_Assembler::deopt_handler_size);
 }
 
 
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -878,15 +878,12 @@
       case T_OBJECT :
        {
         ciObject* obj = con.as_object();
-        if (obj->is_klass()) {
-          ciKlass* klass = obj->as_klass();
-          if (!klass->is_loaded() || PatchALot) {
-            patch_state = state()->copy();
-            t = new ObjectConstant(obj);
-          } else {
-            t = new InstanceConstant(klass->java_mirror());
-          }
+        if (!obj->is_loaded()
+            || (PatchALot && obj->klass() != ciEnv::current()->String_klass())) {
+          patch_state = state()->copy();
+          t = new ObjectConstant(obj);
         } else {
+          assert(!obj->is_klass(), "must be java_mirror of klass");
           t = new InstanceConstant(obj->as_instance());
         }
         break;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -601,7 +601,7 @@
 
 
 static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
-  Bytecode_field* field_access = Bytecode_field_at(caller(), caller->bcp_from(bci));
+  Bytecode_field* field_access = Bytecode_field_at(caller, bci);
   // This can be static or non-static field access
   Bytecodes::Code code       = field_access->code();
 
@@ -721,7 +721,7 @@
   Handle load_klass(THREAD, NULL);                // oop needed by load_klass_patching code
   if (stub_id == Runtime1::access_field_patching_id) {
 
-    Bytecode_field* field_access = Bytecode_field_at(caller_method(), caller_method->bcp_from(bci));
+    Bytecode_field* field_access = Bytecode_field_at(caller_method, bci);
     FieldAccessInfo result; // initialize class if needed
     Bytecodes::Code code = field_access->code();
     constantPoolHandle constants(THREAD, caller_method->constants());
@@ -781,11 +781,9 @@
       case Bytecodes::_ldc:
       case Bytecodes::_ldc_w:
         {
-          Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method(),
-                                                               caller_method->bcp_from(bci));
-          klassOop resolved = caller_method->constants()->klass_at(cc->index(), CHECK);
-          // ldc wants the java mirror.
-          k = resolved->klass_part()->java_mirror();
+          Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method, bci);
+          k = cc->resolve_constant(CHECK);
+          assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant");
         }
         break;
       default: Unimplemented();
@@ -816,6 +814,15 @@
     // Return to the now deoptimized frame.
   }
 
+  // If we are patching in a non-perm oop, make sure the nmethod
+  // is on the right list.
+  if (ScavengeRootsInCode && load_klass.not_null() && load_klass->is_scavengable()) {
+    MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
+    guarantee(nm != NULL, "only nmethods can contain non-perm oops");
+    if (!nm->on_scavenge_root_list())
+      CodeCache::add_scavenge_root_nmethod(nm);
+  }
 
   // Now copy code back
 
@@ -1115,7 +1122,7 @@
   if (length == 0) return;
   // Not guaranteed to be word atomic, but that doesn't matter
   // for anything but an oop array, which is covered by oop_arraycopy.
-  Copy::conjoint_bytes(src, dst, length);
+  Copy::conjoint_jbytes(src, dst, length);
 JRT_END
 
 JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num))
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -106,7 +106,7 @@
 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
   for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i))
-      _arg_returned.set_bit(i);
+      _arg_returned.set(i);
   }
   _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated());
   _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
@@ -126,16 +126,16 @@
   if (_conservative)
     return true;
   for (int i = 0; i < _arg_size; i++) {
-    if (vars.contains(i) && _arg_stack.at(i))
+    if (vars.contains(i) && _arg_stack.test(i))
       return true;
   }
   return false;
 }
 
-void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) {
+void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
   for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i)) {
-      bm.clear_bit(i);
+      bm >>= i;
     }
   }
 }
@@ -1157,15 +1157,15 @@
   ciSignature* sig = method()->signature();
   int j = 0;
   if (!method()->is_static()) {
-    _arg_local.set_bit(0);
-    _arg_stack.set_bit(0);
+    _arg_local.set(0);
+    _arg_stack.set(0);
     j++;
   }
   for (i = 0; i < sig->count(); i++) {
     ciType* t = sig->type_at(i);
     if (!t->is_primitive_type()) {
-      _arg_local.set_bit(j);
-      _arg_stack.set_bit(j);
+      _arg_local.set(j);
+      _arg_stack.set(j);
     }
     j += t->size();
   }
@@ -1198,9 +1198,9 @@
     set_modified(var, OFFSET_ANY, 4);
     set_global_escape(var);
   }
-  _arg_local.clear();
-  _arg_stack.clear();
-  _arg_returned.clear();
+  _arg_local.Clear();
+  _arg_stack.Clear();
+  _arg_returned.Clear();
   _return_local = false;
   _return_allocated = false;
   _allocated_escapes = true;
@@ -1254,7 +1254,7 @@
 
   // Do not scan method if it has no object parameters and
   // does not returns an object (_return_allocated is set in initialize()).
-  if (_arg_local.is_empty() && !_return_allocated) {
+  if (_arg_local.Size() == 0 && !_return_allocated) {
     // Clear all info since method's bytecode was not analysed and
     // set pessimistic escape information.
     clear_escape_info();
@@ -1275,14 +1275,14 @@
   //
   if (!has_dependencies() && !methodData()->is_empty()) {
     for (i = 0; i < _arg_size; i++) {
-      if (_arg_local.at(i)) {
-        assert(_arg_stack.at(i), "inconsistent escape info");
+      if (_arg_local.test(i)) {
+        assert(_arg_stack.test(i), "inconsistent escape info");
         methodData()->set_arg_local(i);
         methodData()->set_arg_stack(i);
-      } else if (_arg_stack.at(i)) {
+      } else if (_arg_stack.test(i)) {
         methodData()->set_arg_stack(i);
       }
-      if (_arg_returned.at(i)) {
+      if (_arg_returned.test(i)) {
         methodData()->set_arg_returned(i);
       }
       methodData()->set_arg_modified(i, _arg_modified[i]);
@@ -1308,9 +1308,12 @@
 
   // read escape information from method descriptor
   for (int i = 0; i < _arg_size; i++) {
-    _arg_local.at_put(i, methodData()->is_arg_local(i));
-    _arg_stack.at_put(i, methodData()->is_arg_stack(i));
-    _arg_returned.at_put(i, methodData()->is_arg_returned(i));
+    if (methodData()->is_arg_local(i))
+      _arg_local.set(i);
+    if (methodData()->is_arg_stack(i))
+      _arg_stack.set(i);
+    if (methodData()->is_arg_returned(i))
+      _arg_returned.set(i);
     _arg_modified[i] = methodData()->arg_modified(i);
   }
   _return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
@@ -1358,26 +1361,26 @@
 
 BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
     : _conservative(method == NULL || !EstimateArgEscape)
+    , _arena(CURRENT_ENV->arena())
     , _method(method)
     , _methodData(method ? method->method_data() : NULL)
     , _arg_size(method ? method->arg_size() : 0)
-    , _stack()
-    , _arg_local(_arg_size)
-    , _arg_stack(_arg_size)
-    , _arg_returned(_arg_size)
-    , _dirty(_arg_size)
+    , _arg_local(_arena)
+    , _arg_stack(_arena)
+    , _arg_returned(_arena)
+    , _dirty(_arena)
     , _return_local(false)
     , _return_allocated(false)
     , _allocated_escapes(false)
     , _unknown_modified(false)
-    , _dependencies()
+    , _dependencies(_arena, 4, 0, NULL)
     , _parent(parent)
     , _level(parent == NULL ? 0 : parent->level() + 1) {
   if (!_conservative) {
-    _arg_local.clear();
-    _arg_stack.clear();
-    _arg_returned.clear();
-    _dirty.clear();
+    _arg_local.Clear();
+    _arg_stack.Clear();
+    _arg_returned.Clear();
+    _dirty.Clear();
     Arena* arena = CURRENT_ENV->arena();
     _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
     Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
@@ -1414,8 +1417,8 @@
     deps->assert_evol_method(method());
   }
   for (int i = 0; i < _dependencies.length(); i+=2) {
-    ciKlass *k = _dependencies[i]->as_klass();
-    ciMethod *m = _dependencies[i+1]->as_method();
+    ciKlass *k = _dependencies.at(i)->as_klass();
+    ciMethod *m = _dependencies.at(i+1)->as_method();
     deps->assert_unique_concrete_method(k, m);
   }
 }
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -22,9 +22,6 @@
  *
  */
 
-define_array(ciObjectArray, ciObject*);
-define_stack(ciObjectList, ciObjectArray);
-
 // This class implements a fast, conservative analysis of effect of methods
 // on the escape state of their arguments.  The analysis is at the bytecode
 // level.
@@ -34,18 +31,17 @@
 
 class BCEscapeAnalyzer : public ResourceObj {
  private:
+  Arena*            _arena;        // ciEnv arena
+
   bool              _conservative; // If true, return maximally
                                    // conservative results.
   ciMethod*         _method;
   ciMethodData*     _methodData;
   int               _arg_size;
-
-  intStack          _stack;
-
-  BitMap            _arg_local;
-  BitMap            _arg_stack;
-  BitMap            _arg_returned;
-  BitMap            _dirty;
+  VectorSet         _arg_local;
+  VectorSet         _arg_stack;
+  VectorSet         _arg_returned;
+  VectorSet         _dirty;
   enum{ ARG_OFFSET_MAX = 31};
   uint              *_arg_modified;
 
@@ -54,7 +50,7 @@
   bool              _allocated_escapes;
   bool              _unknown_modified;
 
-  ciObjectList     _dependencies;
+  GrowableArray<ciObject *> _dependencies;
 
   ciMethodBlocks   *_methodBlocks;
 
@@ -68,20 +64,10 @@
  private:
   // helper functions
   bool is_argument(int i)    { return i >= 0 && i < _arg_size; }
-
-  void raw_push(int i)       { _stack.push(i); }
-  int  raw_pop()             { return _stack.is_empty() ? -1 : _stack.pop(); }
-  void apush(int i)          { raw_push(i); }
-  void spush()               { raw_push(-1); }
-  void lpush()               { spush(); spush(); }
-  int  apop()                { return raw_pop(); }
-  void spop()                { assert(_stack.is_empty() || _stack.top() == -1, ""); raw_pop(); }
-  void lpop()                { spop(); spop(); }
-
   void set_returned(ArgumentMap vars);
   bool is_argument(ArgumentMap vars);
   bool is_arg_stack(ArgumentMap vars);
-  void clear_bits(ArgumentMap vars, BitMap &bs);
+  void clear_bits(ArgumentMap vars, VectorSet &bs);
   void set_method_escape(ArgumentMap vars);
   void set_global_escape(ArgumentMap vars);
   void set_dirty(ArgumentMap vars);
@@ -116,25 +102,25 @@
   ciMethodData*     methodData() const           { return _methodData; }
   BCEscapeAnalyzer* parent() const               { return _parent; }
   int               level() const                { return _level; }
-  ciObjectList*     dependencies()               { return &_dependencies; }
+  GrowableArray<ciObject *>* dependencies()               { return &_dependencies; }
   bool              has_dependencies() const     { return !_dependencies.is_empty(); }
 
   // retrieval of interprocedural escape information
 
   // The given argument does not escape the callee.
   bool is_arg_local(int i) const {
-    return !_conservative && _arg_local.at(i);
+    return !_conservative && _arg_local.test(i);
   }
 
   // The given argument escapes the callee, but does not become globally
   // reachable.
   bool is_arg_stack(int i) const {
-    return !_conservative && _arg_stack.at(i);
+    return !_conservative && _arg_stack.test(i);
   }
 
   // The given argument does not escape globally, and may be returned.
   bool is_arg_returned(int i) const {
-    return !_conservative && _arg_returned.at(i); }
+    return !_conservative && _arg_returned.test(i); }
 
   // True iff only input arguments are returned.
   bool is_return_local() const {
--- a/hotspot/src/share/vm/ci/ciCPCache.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciCPCache.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -44,13 +44,23 @@
 // ciCPCache::is_f1_null_at
 bool ciCPCache::is_f1_null_at(int index) {
   VM_ENTRY_MARK;
-  constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop();
-  oop f1 = cpcache->secondary_entry_at(index)->f1();
+  oop f1 = entry_at(index)->f1();
   return (f1 == NULL);
 }
 
 
 // ------------------------------------------------------------------
+// ciCPCache::get_pool_index
+int ciCPCache::get_pool_index(int index) {
+  VM_ENTRY_MARK;
+  ConstantPoolCacheEntry* e = entry_at(index);
+  if (e->is_secondary_entry())
+    e = entry_at(e->main_entry_index());
+  return e->constant_pool_index();
+}
+
+
+// ------------------------------------------------------------------
 // ciCPCache::print
 //
 // Print debugging information about the cache.
--- a/hotspot/src/share/vm/ci/ciCPCache.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciCPCache.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -29,6 +29,18 @@
 // Note: This class is called ciCPCache as ciConstantPoolCache is used
 // for something different.
 class ciCPCache : public ciObject {
+private:
+  constantPoolCacheOop get_cpCacheOop() {   // must be called inside a VM_ENTRY_MARK
+    return (constantPoolCacheOop) get_oop();
+  }
+
+  ConstantPoolCacheEntry* entry_at(int i) {
+    int raw_index = i;
+    if (constantPoolCacheOopDesc::is_secondary_index(i))
+      raw_index = constantPoolCacheOopDesc::decode_secondary_index(i);
+    return get_cpCacheOop()->entry_at(raw_index);
+  }
+
 public:
   ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
 
@@ -41,5 +53,7 @@
 
   bool is_f1_null_at(int index);
 
+  int get_pool_index(int index);
+
   void print();
 };
--- a/hotspot/src/share/vm/ci/ciClassList.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciClassList.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -85,6 +85,7 @@
 friend class ciConstantPoolCache;      \
 friend class ciField;                  \
 friend class ciConstant;               \
+friend class ciCPCache;                \
 friend class ciFlags;                  \
 friend class ciExceptionHandler;       \
 friend class ciCallProfile;            \
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -511,9 +511,22 @@
 //
 // Implementation of get_constant_by_index().
 ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
-                                             int index,
+                                             int pool_index, int cache_index,
                                              ciInstanceKlass* accessor) {
+  bool ignore_will_link;
   EXCEPTION_CONTEXT;
+  int index = pool_index;
+  if (cache_index >= 0) {
+    assert(index < 0, "only one kind of index at a time");
+    ConstantPoolCacheEntry* cpc_entry = cpool->cache()->entry_at(cache_index);
+    index = cpc_entry->constant_pool_index();
+    oop obj = cpc_entry->f1();
+    if (obj != NULL) {
+      assert(obj->is_instance(), "must be an instance");
+      ciObject* ciobj = get_object(obj);
+      return ciConstant(T_OBJECT, ciobj);
+    }
+  }
   constantTag tag = cpool->tag_at(index);
   if (tag.is_int()) {
     return ciConstant(T_INT, (jint)cpool->int_at(index));
@@ -540,8 +553,7 @@
     return ciConstant(T_OBJECT, constant);
   } else if (tag.is_klass() || tag.is_unresolved_klass()) {
     // 4881222: allow ldc to take a class type
-    bool ignore;
-    ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor);
+    ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
     if (HAS_PENDING_EXCEPTION) {
       CLEAR_PENDING_EXCEPTION;
       record_out_of_memory_failure();
@@ -549,12 +561,26 @@
     }
     assert (klass->is_instance_klass() || klass->is_array_klass(),
             "must be an instance or array klass ");
-    return ciConstant(T_OBJECT, klass);
+    return ciConstant(T_OBJECT, klass->java_mirror());
   } else if (tag.is_object()) {
     oop obj = cpool->object_at(index);
     assert(obj->is_instance(), "must be an instance");
     ciObject* ciobj = get_object(obj);
     return ciConstant(T_OBJECT, ciobj);
+  } else if (tag.is_method_type()) {
+    // must execute Java code to link this CP entry into cache[i].f1
+    ciSymbol* signature = get_object(cpool->method_type_signature_at(index))->as_symbol();
+    ciObject* ciobj = get_unloaded_method_type_constant(signature);
+    return ciConstant(T_OBJECT, ciobj);
+  } else if (tag.is_method_handle()) {
+    // must execute Java code to link this CP entry into cache[i].f1
+    int ref_kind        = cpool->method_handle_ref_kind_at(index);
+    int callee_index    = cpool->method_handle_klass_index_at(index);
+    ciKlass* callee     = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor);
+    ciSymbol* name      = get_object(cpool->method_handle_name_ref_at(index))->as_symbol();
+    ciSymbol* signature = get_object(cpool->method_handle_signature_ref_at(index))->as_symbol();
+    ciObject* ciobj     = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
+    return ciConstant(T_OBJECT, ciobj);
   } else {
     ShouldNotReachHere();
     return ciConstant();
@@ -562,61 +588,15 @@
 }
 
 // ------------------------------------------------------------------
-// ciEnv::is_unresolved_string_impl
-//
-// Implementation of is_unresolved_string().
-bool ciEnv::is_unresolved_string_impl(instanceKlass* accessor, int index) const {
-  EXCEPTION_CONTEXT;
-  assert(accessor->is_linked(), "must be linked before accessing constant pool");
-  constantPoolOop cpool = accessor->constants();
-  constantTag tag = cpool->tag_at(index);
-  return tag.is_unresolved_string();
-}
-
-// ------------------------------------------------------------------
-// ciEnv::is_unresolved_klass_impl
-//
-// Implementation of is_unresolved_klass().
-bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
-  EXCEPTION_CONTEXT;
-  assert(accessor->is_linked(), "must be linked before accessing constant pool");
-  constantPoolOop cpool = accessor->constants();
-  constantTag tag = cpool->tag_at(index);
-  return tag.is_unresolved_klass();
-}
-
-// ------------------------------------------------------------------
 // ciEnv::get_constant_by_index
 //
 // Pull a constant out of the constant pool.  How appropriate.
 //
 // Implementation note: this query is currently in no way cached.
 ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
-                                        int index,
+                                        int pool_index, int cache_index,
                                         ciInstanceKlass* accessor) {
-  GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);)
-}
-
-// ------------------------------------------------------------------
-// ciEnv::is_unresolved_string
-//
-// Check constant pool
-//
-// Implementation note: this query is currently in no way cached.
-bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
-                                 int index) const {
-  GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); )
-}
-
-// ------------------------------------------------------------------
-// ciEnv::is_unresolved_klass
-//
-// Check constant pool
-//
-// Implementation note: this query is currently in no way cached.
-bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor,
-                                int index) const {
-  GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); )
+  GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);)
 }
 
 // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -116,12 +116,8 @@
                                 bool& is_accessible,
                                 ciInstanceKlass* loading_klass);
   ciConstant get_constant_by_index(constantPoolHandle cpool,
-                                   int constant_index,
+                                   int pool_index, int cache_index,
                                    ciInstanceKlass* accessor);
-  bool       is_unresolved_string(ciInstanceKlass* loading_klass,
-                                   int constant_index) const;
-  bool       is_unresolved_klass(ciInstanceKlass* loading_klass,
-                                   int constant_index) const;
   ciField*   get_field_by_index(ciInstanceKlass* loading_klass,
                                 int field_index);
   ciMethod*  get_method_by_index(constantPoolHandle cpool,
@@ -137,12 +133,8 @@
                                      bool& is_accessible,
                                      ciInstanceKlass* loading_klass);
   ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
-                                        int constant_index,
+                                        int pool_index, int cache_index,
                                         ciInstanceKlass* loading_klass);
-  bool       is_unresolved_string_impl (instanceKlass* loading_klass,
-                                        int constant_index) const;
-  bool       is_unresolved_klass_impl (instanceKlass* loading_klass,
-                                        int constant_index) const;
   ciField*   get_field_by_index_impl(ciInstanceKlass* loading_klass,
                                      int field_index);
   ciMethod*  get_method_by_index_impl(constantPoolHandle cpool,
@@ -190,6 +182,25 @@
     return _factory->get_unloaded_klass(accessing_klass, name, true);
   }
 
+  // Get a ciKlass representing an unloaded klass mirror.
+  // Result is not necessarily unique, but will be unloaded.
+  ciInstance* get_unloaded_klass_mirror(ciKlass* type) {
+    return _factory->get_unloaded_klass_mirror(type);
+  }
+
+  // Get a ciInstance representing an unresolved method handle constant.
+  ciInstance* get_unloaded_method_handle_constant(ciKlass*  holder,
+                                                  ciSymbol* name,
+                                                  ciSymbol* signature,
+                                                  int       ref_kind) {
+    return _factory->get_unloaded_method_handle_constant(holder, name, signature, ref_kind);
+  }
+
+  // Get a ciInstance representing an unresolved method type constant.
+  ciInstance* get_unloaded_method_type_constant(ciSymbol* signature) {
+    return _factory->get_unloaded_method_type_constant(signature);
+  }
+
   // See if we already have an unloaded klass for the given name
   // or return NULL if not.
   ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -44,9 +44,7 @@
   _flags = ciFlags(access_flags);
   _has_finalizer = access_flags.has_finalizer();
   _has_subklass = ik->subklass() != NULL;
-  _is_initialized = ik->is_initialized();
-  // Next line must follow and use the result of the previous line:
-  _is_linked = _is_initialized || ik->is_linked();
+  _init_state = (instanceKlass::ClassState)ik->get_init_state();
   _nonstatic_field_size = ik->nonstatic_field_size();
   _has_nonstatic_fields = ik->has_nonstatic_fields();
   _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
@@ -91,8 +89,7 @@
   : ciKlass(name, ciInstanceKlassKlass::make())
 {
   assert(name->byte_at(0) != '[', "not an instance klass");
-  _is_initialized = false;
-  _is_linked = false;
+  _init_state = (instanceKlass::ClassState)0;
   _nonstatic_field_size = -1;
   _has_nonstatic_fields = false;
   _nonstatic_fields = NULL;
@@ -109,21 +106,10 @@
 
 // ------------------------------------------------------------------
 // ciInstanceKlass::compute_shared_is_initialized
-bool ciInstanceKlass::compute_shared_is_initialized() {
+void ciInstanceKlass::compute_shared_init_state() {
   GUARDED_VM_ENTRY(
     instanceKlass* ik = get_instanceKlass();
-    _is_initialized = ik->is_initialized();
-    return _is_initialized;
-  )
-}
-
-// ------------------------------------------------------------------
-// ciInstanceKlass::compute_shared_is_linked
-bool ciInstanceKlass::compute_shared_is_linked() {
-  GUARDED_VM_ENTRY(
-    instanceKlass* ik = get_instanceKlass();
-    _is_linked = ik->is_linked();
-    return _is_linked;
+    _init_state = (instanceKlass::ClassState)ik->get_init_state();
   )
 }
 
@@ -323,8 +309,8 @@
 // ciInstanceKlass::java_mirror
 //
 // Get the instance of java.lang.Class corresponding to this klass.
+// Cache it on this->_java_mirror.
 ciInstance* ciInstanceKlass::java_mirror() {
-  assert(is_loaded(), "must be loaded");
   if (_java_mirror == NULL) {
     _java_mirror = ciKlass::java_mirror();
   }
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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,9 +39,8 @@
   jobject                _loader;
   jobject                _protection_domain;
 
+  instanceKlass::ClassState _init_state;           // state of class
   bool                   _is_shared;
-  bool                   _is_initialized;
-  bool                   _is_linked;
   bool                   _has_finalizer;
   bool                   _has_subklass;
   bool                   _has_nonstatic_fields;
@@ -87,27 +86,34 @@
 
   bool is_shared() { return _is_shared; }
 
-  bool compute_shared_is_initialized();
-  bool compute_shared_is_linked();
+  void compute_shared_init_state();
   bool compute_shared_has_subklass();
   int  compute_shared_nof_implementors();
   int  compute_nonstatic_fields();
   GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
 
+  // Update the init_state for shared klasses
+  void update_if_shared(instanceKlass::ClassState expected) {
+    if (_is_shared && _init_state != expected) {
+      if (is_loaded()) compute_shared_init_state();
+    }
+  }
+
 public:
   // Has this klass been initialized?
   bool                   is_initialized() {
-    if (_is_shared && !_is_initialized) {
-      return is_loaded() && compute_shared_is_initialized();
-    }
-    return _is_initialized;
+    update_if_shared(instanceKlass::fully_initialized);
+    return _init_state == instanceKlass::fully_initialized;
+  }
+  // Is this klass being initialized?
+  bool                   is_being_initialized() {
+    update_if_shared(instanceKlass::being_initialized);
+    return _init_state == instanceKlass::being_initialized;
   }
   // Has this klass been linked?
   bool                   is_linked() {
-    if (_is_shared && !_is_linked) {
-      return is_loaded() && compute_shared_is_linked();
-    }
-    return _is_linked;
+    update_if_shared(instanceKlass::linked);
+    return _init_state >= instanceKlass::linked;
   }
 
   // General klass information.
--- a/hotspot/src/share/vm/ci/ciKlass.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciKlass.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -192,8 +192,14 @@
 
 // ------------------------------------------------------------------
 // ciKlass::java_mirror
+//
+// Get the instance of java.lang.Class corresponding to this klass.
+// If it is an unloaded instance or array klass, return an unloaded
+// mirror object of type Class.
 ciInstance* ciKlass::java_mirror() {
   GUARDED_VM_ENTRY(
+    if (!is_loaded())
+      return ciEnv::current()->get_unloaded_klass_mirror(this);
     oop java_mirror = get_Klass()->java_mirror();
     return CURRENT_ENV->get_object(java_mirror)->as_instance();
   )
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -54,10 +54,10 @@
   _code               = NULL;
   _exception_handlers = NULL;
   _liveness           = NULL;
-  _bcea = NULL;
   _method_blocks = NULL;
 #ifdef COMPILER2
   _flow               = NULL;
+  _bcea               = NULL;
 #endif // COMPILER2
 
   ciEnv *env = CURRENT_ENV;
@@ -121,11 +121,11 @@
   _intrinsic_id = vmIntrinsics::_none;
   _liveness = NULL;
   _can_be_statically_bound = false;
-  _bcea = NULL;
   _method_blocks = NULL;
   _method_data = NULL;
 #ifdef COMPILER2
   _flow = NULL;
+  _bcea = NULL;
 #endif // COMPILER2
 }
 
@@ -1033,10 +1033,15 @@
 bool ciMethod::is_initializer () const {         FETCH_FLAG_FROM_VM(is_initializer); }
 
 BCEscapeAnalyzer  *ciMethod::get_bcea() {
+#ifdef COMPILER2
   if (_bcea == NULL) {
     _bcea = new (CURRENT_ENV->arena()) BCEscapeAnalyzer(this, NULL);
   }
   return _bcea;
+#else // COMPILER2
+  ShouldNotReachHere();
+  return NULL;
+#endif // COMPILER2
 }
 
 ciMethodBlocks  *ciMethod::get_method_blocks() {
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -48,7 +48,6 @@
   ciInstanceKlass* _holder;
   ciSignature*     _signature;
   ciMethodData*    _method_data;
-  BCEscapeAnalyzer* _bcea;
   ciMethodBlocks*   _method_blocks;
 
   // Code attributes.
@@ -72,7 +71,8 @@
   // Optional liveness analyzer.
   MethodLiveness* _liveness;
 #ifdef COMPILER2
-  ciTypeFlow*     _flow;
+  ciTypeFlow*         _flow;
+  BCEscapeAnalyzer*   _bcea;
 #endif
 
   ciMethod(methodHandle h_m);
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -70,6 +70,7 @@
 
   _unloaded_methods = new (arena) GrowableArray<ciMethod*>(arena, 4, 0, NULL);
   _unloaded_klasses = new (arena) GrowableArray<ciKlass*>(arena, 8, 0, NULL);
+  _unloaded_instances = new (arena) GrowableArray<ciInstance*>(arena, 4, 0, NULL);
   _return_addresses =
     new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL);
 }
@@ -443,6 +444,74 @@
   return new_klass;
 }
 
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_instance
+//
+// Get a ciInstance representing an as-yet undetermined instance of a given class.
+//
+ciInstance* ciObjectFactory::get_unloaded_instance(ciInstanceKlass* instance_klass) {
+  for (int i=0; i<_unloaded_instances->length(); i++) {
+    ciInstance* entry = _unloaded_instances->at(i);
+    if (entry->klass()->equals(instance_klass)) {
+      // We've found a match.
+      return entry;
+    }
+  }
+
+  // This is a new unloaded instance.  Create it and stick it in
+  // the cache.
+  ciInstance* new_instance = new (arena()) ciInstance(instance_klass);
+
+  init_ident_of(new_instance);
+  _unloaded_instances->append(new_instance);
+
+  // make sure it looks the way we want:
+  assert(!new_instance->is_loaded(), "");
+  assert(new_instance->klass() == instance_klass, "");
+
+  return new_instance;
+}
+
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_klass_mirror
+//
+// Get a ciInstance representing an unresolved klass mirror.
+//
+// Currently, this ignores the parameters and returns a unique unloaded instance.
+ciInstance* ciObjectFactory::get_unloaded_klass_mirror(ciKlass*  type) {
+  assert(ciEnv::_Class_klass != NULL, "");
+  return get_unloaded_instance(ciEnv::_Class_klass->as_instance_klass());
+}
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_method_handle_constant
+//
+// Get a ciInstance representing an unresolved method handle constant.
+//
+// Currently, this ignores the parameters and returns a unique unloaded instance.
+ciInstance* ciObjectFactory::get_unloaded_method_handle_constant(ciKlass*  holder,
+                                                                 ciSymbol* name,
+                                                                 ciSymbol* signature,
+                                                                 int       ref_kind) {
+  if (ciEnv::_MethodHandle_klass == NULL)  return NULL;
+  return get_unloaded_instance(ciEnv::_MethodHandle_klass->as_instance_klass());
+}
+
+//------------------------------------------------------------------
+// ciObjectFactory::get_unloaded_method_type_constant
+//
+// Get a ciInstance representing an unresolved method type constant.
+//
+// Currently, this ignores the parameters and returns a unique unloaded instance.
+ciInstance* ciObjectFactory::get_unloaded_method_type_constant(ciSymbol* signature) {
+  if (ciEnv::_MethodType_klass == NULL)  return NULL;
+  return get_unloaded_instance(ciEnv::_MethodType_klass->as_instance_klass());
+}
+
+
+
 //------------------------------------------------------------------
 // ciObjectFactory::get_empty_methodData
 //
@@ -637,7 +706,8 @@
 //
 // Print debugging information about the object factory
 void ciObjectFactory::print() {
-  tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_klasses=%d>",
+  tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_instances=%d unloaded_klasses=%d>",
              _ci_objects->length(), _unloaded_methods->length(),
+             _unloaded_instances->length(),
              _unloaded_klasses->length());
 }
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -39,6 +39,7 @@
   GrowableArray<ciObject*>* _ci_objects;
   GrowableArray<ciMethod*>* _unloaded_methods;
   GrowableArray<ciKlass*>* _unloaded_klasses;
+  GrowableArray<ciInstance*>* _unloaded_instances;
   GrowableArray<ciReturnAddress*>* _return_addresses;
   int                       _next_ident;
 
@@ -73,6 +74,8 @@
 
   void print_contents_impl();
 
+  ciInstance* get_unloaded_instance(ciInstanceKlass* klass);
+
 public:
   static bool is_initialized() { return _initialized; }
 
@@ -98,6 +101,18 @@
                               ciSymbol* name,
                               bool create_if_not_found);
 
+  // Get a ciInstance representing an unresolved klass mirror.
+  ciInstance* get_unloaded_klass_mirror(ciKlass* type);
+
+  // Get a ciInstance representing an unresolved method handle constant.
+  ciInstance* get_unloaded_method_handle_constant(ciKlass*  holder,
+                                                  ciSymbol* name,
+                                                  ciSymbol* signature,
+                                                  int       ref_kind);
+
+  // Get a ciInstance representing an unresolved method type constant.
+  ciInstance* get_unloaded_method_type_constant(ciSymbol* signature);
+
 
   // Get the ciMethodData representing the methodData for a method
   // with none.
--- a/hotspot/src/share/vm/ci/ciStreams.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -186,12 +186,13 @@
 }
 
 // ------------------------------------------------------------------
-// ciBytecodeStream::get_constant_index
+// ciBytecodeStream::get_constant_raw_index
 //
 // If this bytecode is one of the ldc variants, get the index of the
 // referenced constant.
-int ciBytecodeStream::get_constant_index() const {
-  switch(cur_bc()) {
+int ciBytecodeStream::get_constant_raw_index() const {
+  // work-alike for Bytecode_loadconstant::raw_index()
+  switch (cur_bc()) {
   case Bytecodes::_ldc:
     return get_index_u1();
   case Bytecodes::_ldc_w:
@@ -202,25 +203,52 @@
     return 0;
   }
 }
+
+// ------------------------------------------------------------------
+// ciBytecodeStream::get_constant_pool_index
+// Decode any CP cache index into a regular pool index.
+int ciBytecodeStream::get_constant_pool_index() const {
+  // work-alike for Bytecode_loadconstant::pool_index()
+  int index = get_constant_raw_index();
+  if (has_cache_index()) {
+    return get_cpcache()->get_pool_index(index);
+  }
+  return index;
+}
+
+// ------------------------------------------------------------------
+// ciBytecodeStream::get_constant_cache_index
+// Return the CP cache index, or -1 if there isn't any.
+int ciBytecodeStream::get_constant_cache_index() const {
+  // work-alike for Bytecode_loadconstant::cache_index()
+  return has_cache_index() ? get_constant_raw_index() : -1;
+}
+
 // ------------------------------------------------------------------
 // ciBytecodeStream::get_constant
 //
 // If this bytecode is one of the ldc variants, get the referenced
 // constant.
 ciConstant ciBytecodeStream::get_constant() {
+  int pool_index = get_constant_raw_index();
+  int cache_index = -1;
+  if (has_cache_index()) {
+    cache_index = pool_index;
+    pool_index = -1;
+  }
   VM_ENTRY_MARK;
   constantPoolHandle cpool(_method->get_methodOop()->constants());
-  return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder);
+  return CURRENT_ENV->get_constant_by_index(cpool, pool_index, cache_index, _holder);
 }
 
 // ------------------------------------------------------------------
-bool ciBytecodeStream::is_unresolved_string() const {
-  return CURRENT_ENV->is_unresolved_string(_holder, get_constant_index());
-}
-
-// ------------------------------------------------------------------
-bool ciBytecodeStream::is_unresolved_klass() const {
-  return CURRENT_ENV->is_unresolved_klass(_holder, get_klass_index());
+// ciBytecodeStream::get_constant_pool_tag
+//
+// If this bytecode is one of the ldc variants, get the referenced
+// constant.
+constantTag ciBytecodeStream::get_constant_pool_tag(int index) const {
+  VM_ENTRY_MARK;
+  return _method->get_methodOop()->constants()->tag_at(index);
 }
 
 // ------------------------------------------------------------------
@@ -378,13 +406,16 @@
 
 // ------------------------------------------------------------------
 // ciBytecodeStream::get_cpcache
-ciCPCache* ciBytecodeStream::get_cpcache() {
-  VM_ENTRY_MARK;
-  // Get the constant pool.
-  constantPoolOop      cpool   = _holder->get_instanceKlass()->constants();
-  constantPoolCacheOop cpcache = cpool->cache();
+ciCPCache* ciBytecodeStream::get_cpcache() const {
+  if (_cpcache == NULL) {
+    VM_ENTRY_MARK;
+    // Get the constant pool.
+    constantPoolOop      cpool   = _holder->get_instanceKlass()->constants();
+    constantPoolCacheOop cpcache = cpool->cache();
 
-  return CURRENT_ENV->get_object(cpcache)->as_cpcache();
+    *(ciCPCache**)&_cpcache = CURRENT_ENV->get_object(cpcache)->as_cpcache();
+  }
+  return _cpcache;
 }
 
 // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciStreams.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -46,6 +46,7 @@
 
   ciMethod* _method;           // the method
   ciInstanceKlass* _holder;
+  ciCPCache* _cpcache;
   address _bc_start;            // Start of current bytecode for table
   address _was_wide;            // Address past last wide bytecode
   jint* _table_base;            // Aligned start of last table or switch
@@ -58,7 +59,9 @@
 
   void reset( address base, unsigned int size ) {
     _bc_start =_was_wide = 0;
-    _start = _pc = base; _end = base + size; }
+    _start = _pc = base; _end = base + size;
+    _cpcache = NULL;
+  }
 
   void assert_wide(bool require_wide) const {
     if (require_wide)
@@ -136,15 +139,20 @@
   bool is_wide() const { return ( _pc == _was_wide ); }
 
   // Does this instruction contain an index which refes into the CP cache?
-  bool uses_cp_cache() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
+  bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
 
   int get_index_u1() const {
     return bytecode()->get_index_u1(cur_bc_raw());
   }
 
+  int get_index_u1_cpcache() const {
+    return bytecode()->get_index_u1_cpcache(cur_bc_raw());
+  }
+
   // Get a byte index following this bytecode.
   // If prefixed with a wide bytecode, get a wide index.
   int get_index() const {
+    assert(!has_cache_index(), "else use cpcache variant");
     return (_pc == _was_wide)   // was widened?
       ? get_index_u2(true)      // yes, return wide index
       : get_index_u1();         // no, return narrow index
@@ -207,7 +215,9 @@
     return cur_bci() + get_int_table(index); }
 
   // --- Constant pool access ---
-  int get_constant_index() const;
+  int get_constant_raw_index() const;
+  int get_constant_pool_index() const;
+  int get_constant_cache_index() const;
   int get_field_index();
   int get_method_index();
 
@@ -217,12 +227,17 @@
   int get_klass_index() const;
 
   // If this bytecode is one of the ldc variants, get the referenced
-  // constant
+  // constant.  Do not attempt to resolve it, since that would require
+  // execution of Java code.  If it is not resolved, return an unloaded
+  // object (ciConstant.as_object()->is_loaded() == false).
   ciConstant get_constant();
-  // True if the ldc variant points to an unresolved string
-  bool is_unresolved_string() const;
-  // True if the ldc variant points to an unresolved klass
-  bool is_unresolved_klass() const;
+  constantTag get_constant_pool_tag(int index) const;
+
+  // True if the klass-using bytecode points to an unresolved klass
+  bool is_unresolved_klass() const {
+    constantTag tag = get_constant_pool_tag(get_klass_index());
+    return tag.is_unresolved_klass();
+  }
 
   // If this bytecode is one of get_field, get_static, put_field,
   // or put_static, get the referenced field.
@@ -238,7 +253,7 @@
   int       get_method_holder_index();
   int       get_method_signature_index();
 
-  ciCPCache*  get_cpcache();
+  ciCPCache*  get_cpcache() const;
   ciCallSite* get_call_site();
 };
 
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -712,10 +712,8 @@
     ciObject* obj = con.as_object();
     if (obj->is_null_object()) {
       push_null();
-    } else if (obj->is_klass()) {
-      // The type of ldc <class> is java.lang.Class
-      push_object(outer()->env()->Class_klass());
     } else {
+      assert(!obj->is_klass(), "must be java_mirror of klass");
       push_object(obj->klass());
     }
   } else {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -117,6 +117,29 @@
           cp->string_index_at_put(index, string_index);
         }
         break;
+      case JVM_CONSTANT_MethodHandle :
+      case JVM_CONSTANT_MethodType :
+        if (!EnableMethodHandles ||
+            _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
+          classfile_parse_error(
+            (!EnableInvokeDynamic ?
+             "This JVM does not support constant tag %u in class file %s" :
+             "Class file version does not support constant tag %u in class file %s"),
+            tag, CHECK);
+        }
+        if (tag == JVM_CONSTANT_MethodHandle) {
+          cfs->guarantee_more(4, CHECK);  // ref_kind, method_index, tag/access_flags
+          u1 ref_kind = cfs->get_u1_fast();
+          u2 method_index = cfs->get_u2_fast();
+          cp->method_handle_index_at_put(index, ref_kind, method_index);
+        } else if (tag == JVM_CONSTANT_MethodType) {
+          cfs->guarantee_more(3, CHECK);  // signature_index, tag/access_flags
+          u2 signature_index = cfs->get_u2_fast();
+          cp->method_type_index_at_put(index, signature_index);
+        } else {
+          ShouldNotReachHere();
+        }
+        break;
       case JVM_CONSTANT_Integer :
         {
           cfs->guarantee_more(5, CHECK);  // bytes, tag/access_flags
@@ -337,6 +360,60 @@
           cp->unresolved_string_at_put(index, sym);
         }
         break;
+      case JVM_CONSTANT_MethodHandle :
+        {
+          int ref_index = cp->method_handle_index_at(index);
+          check_property(
+            valid_cp_range(ref_index, length) &&
+                EnableMethodHandles,
+              "Invalid constant pool index %u in class file %s",
+              ref_index, CHECK_(nullHandle));
+          constantTag tag = cp->tag_at(ref_index);
+          int ref_kind  = cp->method_handle_ref_kind_at(index);
+          switch (ref_kind) {
+          case JVM_REF_getField:
+          case JVM_REF_getStatic:
+          case JVM_REF_putField:
+          case JVM_REF_putStatic:
+            check_property(
+              tag.is_field(),
+              "Invalid constant pool index %u in class file %s (not a field)",
+              ref_index, CHECK_(nullHandle));
+            break;
+          case JVM_REF_invokeVirtual:
+          case JVM_REF_invokeStatic:
+          case JVM_REF_invokeSpecial:
+          case JVM_REF_newInvokeSpecial:
+            check_property(
+              tag.is_method(),
+              "Invalid constant pool index %u in class file %s (not a method)",
+              ref_index, CHECK_(nullHandle));
+            break;
+          case JVM_REF_invokeInterface:
+            check_property(
+              tag.is_interface_method(),
+              "Invalid constant pool index %u in class file %s (not an interface method)",
+              ref_index, CHECK_(nullHandle));
+            break;
+          default:
+            classfile_parse_error(
+              "Bad method handle kind at constant pool index %u in class file %s",
+              index, CHECK_(nullHandle));
+          }
+          // Keep the ref_index unchanged.  It will be indirected at link-time.
+        }
+        break;
+      case JVM_CONSTANT_MethodType :
+        {
+          int ref_index = cp->method_type_index_at(index);
+          check_property(
+            valid_cp_range(ref_index, length) &&
+                cp->tag_at(ref_index).is_utf8() &&
+                EnableMethodHandles,
+              "Invalid constant pool index %u in class file %s",
+              ref_index, CHECK_(nullHandle));
+        }
+        break;
       default:
         fatal(err_msg("bad constant pool tag value %u",
                       cp->tag_at(index).value()));
@@ -452,6 +529,43 @@
         }
         break;
       }
+      case JVM_CONSTANT_MethodHandle: {
+        int ref_index = cp->method_handle_index_at(index);
+        int ref_kind  = cp->method_handle_ref_kind_at(index);
+        switch (ref_kind) {
+        case JVM_REF_invokeVirtual:
+        case JVM_REF_invokeStatic:
+        case JVM_REF_invokeSpecial:
+        case JVM_REF_newInvokeSpecial:
+          {
+            int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index);
+            int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
+            symbolHandle name(THREAD, cp->symbol_at(name_ref_index));
+            if (ref_kind == JVM_REF_newInvokeSpecial) {
+              if (name() != vmSymbols::object_initializer_name()) {
+                classfile_parse_error(
+                  "Bad constructor name at constant pool index %u in class file %s",
+                  name_ref_index, CHECK_(nullHandle));
+              }
+            } else {
+              if (name() == vmSymbols::object_initializer_name()) {
+                classfile_parse_error(
+                  "Bad method name at constant pool index %u in class file %s",
+                  name_ref_index, CHECK_(nullHandle));
+              }
+            }
+          }
+          break;
+          // Other ref_kinds are already fully checked in previous pass.
+        }
+        break;
+      }
+      case JVM_CONSTANT_MethodType: {
+        symbolHandle no_name = vmSymbolHandles::type_name(); // place holder
+        symbolHandle signature(THREAD, cp->method_type_signature_at(index));
+        verify_legal_method_signature(no_name, signature, CHECK_(nullHandle));
+        break;
+      }
     }  // end of switch
   }  // end of for
 
@@ -467,7 +581,7 @@
   case JVM_CONSTANT_UnresolvedClass :
     // Patching a class means pre-resolving it.
     // The name in the constant pool is ignored.
-    if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance
+    if (java_lang_Class::is_instance(patch())) {
       guarantee_property(!java_lang_Class::is_primitive(patch()),
                          "Illegal class patch at %d in class file %s",
                          index, CHECK);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -832,7 +832,6 @@
 
 
 instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
-  VTuneClassLoadMarker clm;
   ResourceMark rm(THREAD);
   EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
   ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -2454,6 +2454,48 @@
   return Handle(THREAD, (oop) result.get_jobject());
 }
 
+// Ask Java code to find or construct a method handle constant.
+Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
+                                                     int ref_kind, //e.g., JVM_REF_invokeVirtual
+                                                     KlassHandle callee,
+                                                     symbolHandle name_sym,
+                                                     symbolHandle signature,
+                                                     TRAPS) {
+  Handle empty;
+  Handle name = java_lang_String::create_from_symbol(name_sym(), CHECK_(empty));
+  Handle type;
+  if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
+    bool ignore_is_on_bcp = false;
+    type = find_method_handle_type(signature, caller, ignore_is_on_bcp, CHECK_(empty));
+  } else {
+    SignatureStream ss(signature(), false);
+    if (!ss.is_done()) {
+      oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(),
+                                     SignatureStream::NCDFError, CHECK_(empty));
+      type = Handle(THREAD, mirror);
+      ss.next();
+      if (!ss.is_done())  type = Handle();  // error!
+    }
+  }
+  if (type.is_null()) {
+    THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad signature", empty);
+  }
+
+  // call sun.dyn.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle
+  JavaCallArguments args;
+  args.push_oop(caller->java_mirror());  // the referring class
+  args.push_int(ref_kind);
+  args.push_oop(callee->java_mirror());  // the target class
+  args.push_oop(name());
+  args.push_oop(type());
+  JavaValue result(T_OBJECT);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::MethodHandleNatives_klass(),
+                         vmSymbols::linkMethodHandleConstant_name(),
+                         vmSymbols::linkMethodHandleConstant_signature(),
+                         &args, CHECK_(empty));
+  return Handle(THREAD, (oop) result.get_jobject());
+}
 
 // Ask Java code to find or construct a java.dyn.CallSite for the given
 // name and signature, as interpreted relative to the given class loader.
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -473,6 +473,13 @@
                                            KlassHandle accessing_klass,
                                            bool& return_bcp_flag,
                                            TRAPS);
+  // ask Java to compute a java.dyn.MethodHandle object for a given CP entry
+  static Handle    link_method_handle_constant(KlassHandle caller,
+                                               int ref_kind, //e.g., JVM_REF_invokeVirtual
+                                               KlassHandle callee,
+                                               symbolHandle name,
+                                               symbolHandle signature,
+                                               TRAPS);
   // ask Java to create a dynamic call site, while linking an invokedynamic op
   static Handle    make_dynamic_call_site(Handle bootstrap_method,
                                           // Callee information:
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1598,7 +1598,10 @@
   if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
     if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) {
       types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float)
-            | (1 << JVM_CONSTANT_String)  | (1 << JVM_CONSTANT_Class);
+            | (1 << JVM_CONSTANT_String)  | (1 << JVM_CONSTANT_Class)
+            | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType);
+      // Note:  The class file parser already verified the legality of
+      // MethodHandle and MethodType constants.
       verify_cp_type(index, cp, types, CHECK_VERIFY(this));
     }
   } else {
@@ -1632,6 +1635,14 @@
     current_frame->push_stack_2(
       VerificationType::long_type(),
       VerificationType::long2_type(), CHECK_VERIFY(this));
+  } else if (tag.is_method_handle()) {
+    current_frame->push_stack(
+      VerificationType::reference_type(
+        vmSymbols::java_dyn_MethodHandle()), CHECK_VERIFY(this));
+  } else if (tag.is_method_type()) {
+    current_frame->push_stack(
+      VerificationType::reference_type(
+        vmSymbols::java_dyn_MethodType()), CHECK_VERIFY(this));
   } else {
     verify_error(bci, "Invalid index in ldc");
     return;
@@ -1920,9 +1931,12 @@
   // Get referenced class type
   VerificationType ref_class_type;
   if (opcode == Bytecodes::_invokedynamic) {
-    if (!EnableInvokeDynamic) {
+    if (!EnableInvokeDynamic ||
+        _klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
       class_format_error(
-        "invokedynamic instructions not enabled on this JVM",
+        (!EnableInvokeDynamic ?
+         "invokedynamic instructions not enabled in this JVM" :
+         "invokedynamic instructions not supported by this class file version"),
         _klass->external_name());
       return;
     }
--- a/hotspot/src/share/vm/classfile/verifier.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -25,7 +25,10 @@
 // The verifier class
 class Verifier : AllStatic {
  public:
-  enum { STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50 };
+  enum {
+    STACKMAP_ATTRIBUTE_MAJOR_VERSION    = 50,
+    INVOKEDYNAMIC_MAJOR_VERSION         = 51
+  };
   typedef enum { ThrowException, NoException } Mode;
 
   /**
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -246,6 +246,8 @@
   /* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */            \
   template(findMethodHandleType_name,                 "findMethodHandleType")                     \
   template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
+  template(linkMethodHandleConstant_name,             "linkMethodHandleConstant")                 \
+  template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \
   template(makeDynamicCallSite_name,                  "makeDynamicCallSite")                      \
   template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \
   NOT_LP64(  do_alias(machine_word_signature,         int_signature)  )                           \
--- a/hotspot/src/share/vm/code/codeBlob.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -210,6 +210,7 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) AdapterBlob(size, cb);
+    CodeCache::commit(blob);
   }
   // Track memory usage statistic after releasing CodeCache_lock
   MemoryService::track_code_cache_memory_usage();
@@ -281,7 +282,6 @@
       tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, stub);
       Disassembler::decode(stub->instructions_begin(), stub->instructions_end());
     }
-    VTune::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
     Forte::register_stub(stub_id, stub->instructions_begin(), stub->instructions_end());
 
     if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -356,7 +356,6 @@
       tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
       Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
     }
-    VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
     Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
 
     if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -414,7 +413,6 @@
       tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
       Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
     }
-    VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
     Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
 
     if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -474,7 +472,6 @@
       tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
       Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
     }
-    VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
     Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
 
     if (JvmtiExport::should_post_dynamic_code_generated()) {
@@ -533,7 +530,6 @@
       tty->print_cr("Decoding %s " INTPTR_FORMAT, blob_id, blob);
       Disassembler::decode(blob->instructions_begin(), blob->instructions_end());
     }
-    VTune::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
     Forte::register_stub(blob_id, blob->instructions_begin(), blob->instructions_end());
 
     if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/code/codeCache.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -93,6 +93,8 @@
 
 CodeHeap * CodeCache::_heap = new CodeHeap();
 int CodeCache::_number_of_blobs = 0;
+int CodeCache::_number_of_adapters = 0;
+int CodeCache::_number_of_nmethods = 0;
 int CodeCache::_number_of_nmethods_with_dependencies = 0;
 bool CodeCache::_needs_cache_clean = false;
 nmethod* CodeCache::_scavenge_root_nmethods = NULL;
@@ -176,8 +178,14 @@
   verify_if_often();
 
   print_trace("free", cb);
-  if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
-    _number_of_nmethods_with_dependencies--;
+  if (cb->is_nmethod()) {
+    _number_of_nmethods--;
+    if (((nmethod *)cb)->has_dependencies()) {
+      _number_of_nmethods_with_dependencies--;
+    }
+  }
+  if (cb->is_adapter_blob()) {
+    _number_of_adapters--;
   }
   _number_of_blobs--;
 
@@ -191,9 +199,16 @@
 void CodeCache::commit(CodeBlob* cb) {
   // this is called by nmethod::nmethod, which must already own CodeCache_lock
   assert_locked_or_safepoint(CodeCache_lock);
-  if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
-    _number_of_nmethods_with_dependencies++;
+  if (cb->is_nmethod()) {
+    _number_of_nmethods++;
+    if (((nmethod *)cb)->has_dependencies()) {
+      _number_of_nmethods_with_dependencies++;
+    }
   }
+  if (cb->is_adapter_blob()) {
+    _number_of_adapters++;
+  }
+
   // flush the hardware I-cache
   ICache::invalidate_range(cb->instructions_begin(), cb->instructions_size());
 }
--- a/hotspot/src/share/vm/code/codeCache.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -43,6 +43,8 @@
   // 4422213 or 4436291 for details.
   static CodeHeap * _heap;
   static int _number_of_blobs;
+  static int _number_of_adapters;
+  static int _number_of_nmethods;
   static int _number_of_nmethods_with_dependencies;
   static bool _needs_cache_clean;
   static nmethod* _scavenge_root_nmethods;  // linked via nm->scavenge_root_link()
@@ -105,6 +107,8 @@
   static nmethod* first_nmethod();
   static nmethod* next_nmethod (CodeBlob* cb);
   static int       nof_blobs()                 { return _number_of_blobs; }
+  static int       nof_adapters()              { return _number_of_adapters; }
+  static int       nof_nmethods()              { return _number_of_nmethods; }
 
   // GC support
   static void gc_epilogue();
--- a/hotspot/src/share/vm/code/nmethod.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -397,11 +397,6 @@
 //-------------end of code for ExceptionCache--------------
 
 
-void nmFlags::clear() {
-  assert(sizeof(nmFlags) == sizeof(int), "using more than one word for nmFlags");
-  *(jint*)this = 0;
-}
-
 int nmethod::total_size() const {
   return
     code_size()          +
@@ -419,8 +414,32 @@
   return NULL;
 }
 
-// %%% This variable is no longer used?
-int nmethod::_zombie_instruction_size = NativeJump::instruction_size;
+// Fill in default values for various flag fields
+void nmethod::init_defaults() {
+  _state                      = alive;
+  _marked_for_reclamation     = 0;
+  _has_flushed_dependencies   = 0;
+  _speculatively_disconnected = 0;
+  _has_unsafe_access          = 0;
+  _has_method_handle_invokes  = 0;
+  _marked_for_deoptimization  = 0;
+  _lock_count                 = 0;
+  _stack_traversal_mark       = 0;
+  _unload_reported            = false;           // jvmti state
+
+  NOT_PRODUCT(_has_debug_info = false);
+  _oops_do_mark_link       = NULL;
+  _jmethod_id              = NULL;
+  _osr_link                = NULL;
+  _scavenge_root_link      = NULL;
+  _scavenge_root_state     = 0;
+  _saved_nmethod_link      = NULL;
+  _compiler                = NULL;
+
+#ifdef HAVE_DTRACE_H
+  _trap_offset             = 0;
+#endif // def HAVE_DTRACE_H
+}
 
 
 nmethod* nmethod::new_native_nmethod(methodHandle method,
@@ -580,24 +599,16 @@
     debug_only(No_Safepoint_Verifier nsv;)
     assert_locked_or_safepoint(CodeCache_lock);
 
-    NOT_PRODUCT(_has_debug_info = false);
-    _oops_do_mark_link       = NULL;
+    init_defaults();
     _method                  = method;
     _entry_bci               = InvocationEntryBci;
-    _osr_link                = NULL;
-    _scavenge_root_link      = NULL;
-    _scavenge_root_state     = 0;
-    _saved_nmethod_link      = NULL;
-    _compiler                = NULL;
     // We have no exception handler or deopt handler make the
     // values something that will never match a pc like the nmethod vtable entry
     _exception_offset        = 0;
     _deoptimize_offset       = 0;
     _deoptimize_mh_offset    = 0;
     _orig_pc_offset          = 0;
-#ifdef HAVE_DTRACE_H
-    _trap_offset             = 0;
-#endif // def HAVE_DTRACE_H
+
     _stub_offset             = data_offset();
     _consts_offset           = data_offset();
     _oops_offset             = data_offset();
@@ -615,17 +626,9 @@
     _exception_cache         = NULL;
     _pc_desc_cache.reset_to(NULL);
 
-    flags.clear();
-    flags.state              = alive;
-    _markedForDeoptimization = 0;
-
-    _lock_count = 0;
-    _stack_traversal_mark    = 0;
-
     code_buffer->copy_oops_to(this);
     debug_only(verify_scavenge_root_oops());
     CodeCache::commit(this);
-    VTune::create_nmethod(this);
   }
 
   if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -673,14 +676,9 @@
     debug_only(No_Safepoint_Verifier nsv;)
     assert_locked_or_safepoint(CodeCache_lock);
 
-    NOT_PRODUCT(_has_debug_info = false);
-    _oops_do_mark_link       = NULL;
+    init_defaults();
     _method                  = method;
     _entry_bci               = InvocationEntryBci;
-    _osr_link                = NULL;
-    _scavenge_root_link      = NULL;
-    _scavenge_root_state     = 0;
-    _compiler                = NULL;
     // We have no exception handler or deopt handler make the
     // values something that will never match a pc like the nmethod vtable entry
     _exception_offset        = 0;
@@ -706,17 +704,9 @@
     _exception_cache         = NULL;
     _pc_desc_cache.reset_to(NULL);
 
-    flags.clear();
-    flags.state              = alive;
-    _markedForDeoptimization = 0;
-
-    _lock_count = 0;
-    _stack_traversal_mark    = 0;
-
     code_buffer->copy_oops_to(this);
     debug_only(verify_scavenge_root_oops());
     CodeCache::commit(this);
-    VTune::create_nmethod(this);
   }
 
   if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -781,20 +771,13 @@
     debug_only(No_Safepoint_Verifier nsv;)
     assert_locked_or_safepoint(CodeCache_lock);
 
-    NOT_PRODUCT(_has_debug_info = false);
-    _oops_do_mark_link       = NULL;
+    init_defaults();
     _method                  = method;
+    _entry_bci               = entry_bci;
     _compile_id              = compile_id;
     _comp_level              = comp_level;
-    _entry_bci               = entry_bci;
-    _osr_link                = NULL;
-    _scavenge_root_link      = NULL;
-    _scavenge_root_state     = 0;
     _compiler                = compiler;
     _orig_pc_offset          = orig_pc_offset;
-#ifdef HAVE_DTRACE_H
-    _trap_offset             = 0;
-#endif // def HAVE_DTRACE_H
     _stub_offset             = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
 
     // Exception handler and deopt handler are in the stub section
@@ -821,15 +804,6 @@
     _exception_cache         = NULL;
     _pc_desc_cache.reset_to(scopes_pcs_begin());
 
-    flags.clear();
-    flags.state              = alive;
-    _markedForDeoptimization = 0;
-
-    _unload_reported         = false;           // jvmti state
-
-    _lock_count = 0;
-    _stack_traversal_mark    = 0;
-
     // Copy contents of ScopeDescRecorder to nmethod
     code_buffer->copy_oops_to(this);
     debug_info->copy_to(this);
@@ -841,8 +815,6 @@
 
     CodeCache::commit(this);
 
-    VTune::create_nmethod(this);
-
     // Copy contents of ExceptionHandlerTable to nmethod
     handler_table->copy_to(this);
     nul_chk_table->copy_to(this);
@@ -988,11 +960,6 @@
 }
 
 
-void nmethod::set_version(int v) {
-  flags.version = v;
-}
-
-
 // Promote one word from an assembly-time handle to a live embedded oop.
 inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
   if (handle == NULL ||
@@ -1139,6 +1106,8 @@
 // This is a private interface with the sweeper.
 void nmethod::mark_as_seen_on_stack() {
   assert(is_not_entrant(), "must be a non-entrant method");
+  // Set the traversal mark to ensure that the sweeper does 2
+  // cleaning passes before moving to zombie.
   set_stack_traversal_mark(NMethodSweeper::traversal_count());
 }
 
@@ -1207,7 +1176,7 @@
     // for later on.
     CodeCache::set_needs_cache_clean(true);
   }
-  flags.state = unloaded;
+  _state = unloaded;
 
   // Log the unloading.
   log_state_change();
@@ -1233,21 +1202,21 @@
   if (LogCompilation) {
     if (xtty != NULL) {
       ttyLocker ttyl;  // keep the following output all in one block
-      if (flags.state == unloaded) {
+      if (_state == unloaded) {
         xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'",
                          os::current_thread_id());
       } else {
         xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s",
                          os::current_thread_id(),
-                         (flags.state == zombie ? " zombie='1'" : ""));
+                         (_state == zombie ? " zombie='1'" : ""));
       }
       log_identity(xtty);
       xtty->stamp();
       xtty->end_elem();
     }
   }
-  if (PrintCompilation && flags.state != unloaded) {
-    print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant ");
+  if (PrintCompilation && _state != unloaded) {
+    print_on(tty, _state == zombie ? "made zombie " : "made not entrant ");
     tty->cr();
   }
 }
@@ -1258,8 +1227,9 @@
 
   bool was_alive = false;
 
-  // Make sure the nmethod is not flushed in case of a safepoint in code below.
+  // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
   nmethodLocker nml(this);
+  methodHandle the_method(method());
 
   {
     // If the method is already zombie there is nothing to do
@@ -1279,7 +1249,7 @@
     // Enter critical section.  Does not block for safepoint.
     MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
 
-    if (flags.state == state) {
+    if (_state == state) {
       // another thread already performed this transition so nothing
       // to do, but return false to indicate this.
       return false;
@@ -1290,17 +1260,37 @@
     if (!is_osr_method() && !is_not_entrant()) {
       NativeJump::patch_verified_entry(entry_point(), verified_entry_point(),
                   SharedRuntime::get_handle_wrong_method_stub());
-      assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, "");
     }
 
-    was_alive = is_in_use(); // Read state under lock
+    if (is_in_use()) {
+      // It's a true state change, so mark the method as decompiled.
+      // Do it only for transition from alive.
+      inc_decompile_count();
+    }
 
     // Change state
-    flags.state = state;
+    _state = state;
 
     // Log the transition once
     log_state_change();
 
+    // Remove nmethod from method.
+    // We need to check if both the _code and _from_compiled_code_entry_point
+    // refer to this nmethod because there is a race in setting these two fields
+    // in methodOop as seen in bugid 4947125.
+    // If the vep() points to the zombie nmethod, the memory for the nmethod
+    // could be flushed and the compiler and vtable stubs could still call
+    // through it.
+    if (method() != NULL && (method()->code() == this ||
+                             method()->from_compiled_entry() == verified_entry_point())) {
+      HandleMark hm;
+      method()->clear_code();
+    }
+
+    if (state == not_entrant) {
+      mark_as_seen_on_stack();
+    }
+
   } // leave critical region under Patching_lock
 
   // When the nmethod becomes zombie it is no longer alive so the
@@ -1308,18 +1298,17 @@
   // state will be flushed later when the transition to zombie
   // happens or they get unloaded.
   if (state == zombie) {
+    // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
+    // and it hasn't already been reported for this nmethod then report it now.
+    // (the event may have been reported earilier if the GC marked it for unloading).
+    post_compiled_method_unload();
+
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     flush_dependencies(NULL);
   } else {
     assert(state == not_entrant, "other cases may need to be handled differently");
   }
 
-  if (state == not_entrant) {
-    Events::log("Make nmethod not entrant " INTPTR_FORMAT, this);
-  } else {
-    Events::log("Make nmethod zombie " INTPTR_FORMAT, this);
-  }
-
   if (TraceCreateZombies) {
     tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie");
   }
@@ -1327,47 +1316,6 @@
   // Make sweeper aware that there is a zombie method that needs to be removed
   NMethodSweeper::notify(this);
 
-  // not_entrant only stuff
-  if (state == not_entrant) {
-    mark_as_seen_on_stack();
-  }
-
-  if (was_alive) {
-    // It's a true state change, so mark the method as decompiled.
-    // Do it only for transition from alive.
-    inc_decompile_count();
-  }
-
-  // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
-  // and it hasn't already been reported for this nmethod then report it now.
-  // (the event may have been reported earilier if the GC marked it for unloading).
-  if (state == zombie) {
-    post_compiled_method_unload();
-  }
-
-
-  // Zombie only stuff
-  if (state == zombie) {
-    VTune::delete_nmethod(this);
-  }
-
-  // Check whether method got unloaded at a safepoint before this,
-  // if so we can skip the flushing steps below
-  if (method() == NULL) return true;
-
-  // Remove nmethod from method.
-  // We need to check if both the _code and _from_compiled_code_entry_point
-  // refer to this nmethod because there is a race in setting these two fields
-  // in methodOop as seen in bugid 4947125.
-  // If the vep() points to the zombie nmethod, the memory for the nmethod
-  // could be flushed and the compiler and vtable stubs could still call
-  // through it.
-  if (method()->code() == this ||
-      method()->from_compiled_entry() == verified_entry_point()) {
-    HandleMark hm;
-    method()->clear_code();
-  }
-
   return true;
 }
 
@@ -1488,11 +1436,25 @@
       moop->signature()->utf8_length(),
       code_begin(), code_size());
 
+  if (JvmtiExport::should_post_compiled_method_load() ||
+      JvmtiExport::should_post_compiled_method_unload()) {
+    get_and_cache_jmethod_id();
+  }
+
   if (JvmtiExport::should_post_compiled_method_load()) {
     JvmtiExport::post_compiled_method_load(this);
   }
 }
 
+jmethodID nmethod::get_and_cache_jmethod_id() {
+  if (_jmethod_id == NULL) {
+    // Cache the jmethod_id since it can no longer be looked up once the
+    // method itself has been marked for unloading.
+    _jmethod_id = method()->jmethod_id();
+  }
+  return _jmethod_id;
+}
+
 void nmethod::post_compiled_method_unload() {
   if (unload_reported()) {
     // During unloading we transition to unloaded and then to zombie
@@ -1504,12 +1466,17 @@
   DTRACE_METHOD_UNLOAD_PROBE(method());
 
   // If a JVMTI agent has enabled the CompiledMethodUnload event then
-  // post the event. Sometime later this nmethod will be made a zombie by
-  // the sweeper but the methodOop will not be valid at that point.
-  if (JvmtiExport::should_post_compiled_method_unload()) {
+  // post the event. Sometime later this nmethod will be made a zombie
+  // by the sweeper but the methodOop will not be valid at that point.
+  // If the _jmethod_id is null then no load event was ever requested
+  // so don't bother posting the unload.  The main reason for this is
+  // that the jmethodID is a weak reference to the methodOop so if
+  // it's being unloaded there's no way to look it up since the weak
+  // ref will have been cleared.
+  if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) {
     assert(!unload_reported(), "already unloaded");
     HandleMark hm;
-    JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin());
+    JvmtiExport::post_compiled_method_unload(_jmethod_id, code_begin());
   }
 
   // The JVMTI CompiledMethodUnload event can be enabled or disabled at
@@ -2087,7 +2054,6 @@
 
 void nmethod_init() {
   // make sure you didn't forget to adjust the filler fields
-  assert(sizeof(nmFlags) <= 4,           "nmFlags occupies more than a word");
   assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
 }
 
@@ -2323,7 +2289,6 @@
     tty->print("((nmethod*) "INTPTR_FORMAT ") ", this);
     tty->print(" for method " INTPTR_FORMAT , (address)method());
     tty->print(" { ");
-    if (version())        tty->print("v%d ", version());
     if (is_in_use())      tty->print("in_use ");
     if (is_not_entrant()) tty->print("not_entrant ");
     if (is_zombie())      tty->print("zombie ");
@@ -2659,13 +2624,10 @@
         case Bytecodes::_getstatic:
         case Bytecodes::_putstatic:
           {
-            methodHandle sdm = sd->method();
-            Bytecode_field* field = Bytecode_field_at(sdm(), sdm->bcp_from(sd->bci()));
-            constantPoolOop sdmc = sdm->constants();
-            symbolOop name = sdmc->name_ref_at(field->index());
+            Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci());
             st->print(" ");
-            if (name != NULL)
-              name->print_symbol_on(st);
+            if (field->name() != NULL)
+              field->name()->print_symbol_on(st);
             else
               st->print("<UNKNOWN>");
           }
--- a/hotspot/src/share/vm/code/nmethod.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -78,29 +78,8 @@
 
 
 // nmethods (native methods) are the compiled code versions of Java methods.
-
-struct nmFlags {
-  friend class VMStructs;
-  unsigned int version:8;                    // version number (0 = first version)
-  unsigned int age:4;                        // age (in # of sweep steps)
-
-  unsigned int state:2;                      // {alive, zombie, unloaded)
-
-  unsigned int isUncommonRecompiled:1;       // recompiled because of uncommon trap?
-  unsigned int isToBeRecompiled:1;           // to be recompiled as soon as it matures
-  unsigned int hasFlushedDependencies:1;     // Used for maintenance of dependencies
-  unsigned int markedForReclamation:1;       // Used by NMethodSweeper
-
-  unsigned int has_unsafe_access:1;          // May fault due to unsafe access.
-  unsigned int has_method_handle_invokes:1;  // Has this method MethodHandle invokes?
-
-  unsigned int speculatively_disconnected:1; // Marked for potential unload
-
-  void clear();
-};
-
-
-// A nmethod contains:
+//
+// An nmethod contains:
 //  - header                 (the nmethod structure)
 //  [Relocation]
 //  - relocation information
@@ -131,10 +110,9 @@
   friend class CodeCache;  // non-perm oops
  private:
   // Shared fields for all nmethod's
-  static int _zombie_instruction_size;
-
   methodOop _method;
   int       _entry_bci;        // != InvocationEntryBci if this nmethod is an on-stack replacement method
+  jmethodID _jmethod_id;       // Cache of method()->jmethod_id()
 
   // To support simple linked-list chaining of nmethods:
   nmethod*  _osr_link;         // from instanceKlass::osr_nmethods_head
@@ -146,6 +124,11 @@
 
   AbstractCompiler* _compiler; // The compiler which compiled this nmethod
 
+  // offsets for entry points
+  address _entry_point;                      // entry point with class check
+  address _verified_entry_point;             // entry point without class check
+  address _osr_entry_point;                  // entry point for on stack replacement
+
   // Offsets for different nmethod parts
   int _exception_offset;
   // All deoptee's will resume execution at this location described by
@@ -174,23 +157,31 @@
   // pc during a deopt.
   int _orig_pc_offset;
 
-  int _compile_id;                     // which compilation made this nmethod
-  int _comp_level;                     // compilation level
+  int _compile_id;                           // which compilation made this nmethod
+  int _comp_level;                           // compilation level
+
+  // protected by CodeCache_lock
+  bool _has_flushed_dependencies;            // Used for maintenance of dependencies (CodeCache_lock)
+  bool _speculatively_disconnected;          // Marked for potential unload
+
+  bool _marked_for_reclamation;              // Used by NMethodSweeper (set only by sweeper)
+  bool _marked_for_deoptimization;           // Used for stack deoptimization
 
-  // offsets for entry points
-  address _entry_point;                // entry point with class check
-  address _verified_entry_point;       // entry point without class check
-  address _osr_entry_point;            // entry point for on stack replacement
+  // used by jvmti to track if an unload event has been posted for this nmethod.
+  bool _unload_reported;
 
-  nmFlags flags;           // various flags to keep track of nmethod state
-  bool _markedForDeoptimization;       // Used for stack deoptimization
+  // set during construction
+  unsigned int _has_unsafe_access:1;         // May fault due to unsafe access.
+  unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?
+
+  // Protected by Patching_lock
+  unsigned char _state;                      // {alive, not_entrant, zombie, unloaded)
+
   enum { alive        = 0,
          not_entrant  = 1, // uncommon trap has happened but activations may still exist
          zombie       = 2,
          unloaded     = 3 };
 
-  // used by jvmti to track if an unload event has been posted for this nmethod.
-  bool _unload_reported;
 
   jbyte _scavenge_root_state;
 
@@ -269,15 +260,15 @@
   bool make_not_entrant_or_zombie(unsigned int state);
   void inc_decompile_count();
 
-  // used to check that writes to nmFlags are done consistently.
-  static void check_safepoint() PRODUCT_RETURN;
-
   // Used to manipulate the exception cache
   void add_exception_cache_entry(ExceptionCache* new_entry);
   ExceptionCache* exception_cache_entry_for_exception(Handle exception);
 
   // Inform external interfaces that a compiled method has been unloaded
-  inline void post_compiled_method_unload();
+  void post_compiled_method_unload();
+
+  // Initailize fields to their default values
+  void init_defaults();
 
  public:
   // create nmethod with entry_bci
@@ -392,11 +383,11 @@
   address verified_entry_point() const            { return _verified_entry_point;    } // if klass is correct
 
   // flag accessing and manipulation
-  bool  is_in_use() const                         { return flags.state == alive; }
-  bool  is_alive() const                          { return flags.state == alive || flags.state == not_entrant; }
-  bool  is_not_entrant() const                    { return flags.state == not_entrant; }
-  bool  is_zombie() const                         { return flags.state == zombie; }
-  bool  is_unloaded() const                       { return flags.state == unloaded;   }
+  bool  is_in_use() const                         { return _state == alive; }
+  bool  is_alive() const                          { return _state == alive || _state == not_entrant; }
+  bool  is_not_entrant() const                    { return _state == not_entrant; }
+  bool  is_zombie() const                         { return _state == zombie; }
+  bool  is_unloaded() const                       { return _state == unloaded;   }
 
   // Make the nmethod non entrant. The nmethod will continue to be
   // alive.  It is used when an uncommon trap happens.  Returns true
@@ -409,37 +400,33 @@
   bool  unload_reported()                         { return _unload_reported; }
   void  set_unload_reported()                     { _unload_reported = true; }
 
-  bool  is_marked_for_deoptimization() const      { return _markedForDeoptimization; }
-  void  mark_for_deoptimization()                 { _markedForDeoptimization = true; }
+  bool  is_marked_for_deoptimization() const      { return _marked_for_deoptimization; }
+  void  mark_for_deoptimization()                 { _marked_for_deoptimization = true; }
 
   void  make_unloaded(BoolObjectClosure* is_alive, oop cause);
 
   bool has_dependencies()                         { return dependencies_size() != 0; }
   void flush_dependencies(BoolObjectClosure* is_alive);
-  bool  has_flushed_dependencies()                { return flags.hasFlushedDependencies; }
-  void  set_has_flushed_dependencies()            {
+  bool has_flushed_dependencies()                 { return _has_flushed_dependencies; }
+  void set_has_flushed_dependencies()             {
     assert(!has_flushed_dependencies(), "should only happen once");
-    flags.hasFlushedDependencies = 1;
+    _has_flushed_dependencies = 1;
   }
 
-  bool  is_marked_for_reclamation() const         { return flags.markedForReclamation; }
-  void  mark_for_reclamation()                    { flags.markedForReclamation = 1; }
-  void  unmark_for_reclamation()                  { flags.markedForReclamation = 0; }
+  bool  is_marked_for_reclamation() const         { return _marked_for_reclamation; }
+  void  mark_for_reclamation()                    { _marked_for_reclamation = 1; }
+
+  bool  has_unsafe_access() const                 { return _has_unsafe_access; }
+  void  set_has_unsafe_access(bool z)             { _has_unsafe_access = z; }
 
-  bool  has_unsafe_access() const                 { return flags.has_unsafe_access; }
-  void  set_has_unsafe_access(bool z)             { flags.has_unsafe_access = z; }
+  bool  has_method_handle_invokes() const         { return _has_method_handle_invokes; }
+  void  set_has_method_handle_invokes(bool z)     { _has_method_handle_invokes = z; }
 
-  bool  has_method_handle_invokes() const         { return flags.has_method_handle_invokes; }
-  void  set_has_method_handle_invokes(bool z)     { flags.has_method_handle_invokes = z; }
-
-  bool  is_speculatively_disconnected() const     { return flags.speculatively_disconnected; }
-  void  set_speculatively_disconnected(bool z)     { flags.speculatively_disconnected = z; }
+  bool  is_speculatively_disconnected() const     { return _speculatively_disconnected; }
+  void  set_speculatively_disconnected(bool z)     { _speculatively_disconnected = z; }
 
   int   comp_level() const                        { return _comp_level; }
 
-  int   version() const                           { return flags.version; }
-  void  set_version(int v);
-
   // Support for oops in scopes and relocs:
   // Note: index 0 is reserved for null.
   oop   oop_at(int index) const                   { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
@@ -599,6 +586,7 @@
 
   // jvmti support:
   void post_compiled_method_load_event();
+  jmethodID get_and_cache_jmethod_id();
 
   // verify operations
   void verify();
--- a/hotspot/src/share/vm/code/vtableStubs.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/code/vtableStubs.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -50,7 +50,6 @@
     }
     _chunk = blob->instructions_begin();
     _chunk_end = _chunk + bytes;
-    VTune::register_stub("vtable stub", _chunk, _chunk_end);
     Forte::register_stub("vtable stub", _chunk, _chunk_end);
     // Notify JVMTI about this stub. The event will be recorded by the enclosing
     // JvmtiDynamicCodeEventCollector and posted when this thread has released
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -3972,6 +3972,10 @@
 
   void work(int i) {
     if (i >= _n_workers) return;  // no work needed this round
+
+    double start_time_ms = os::elapsedTime() * 1000.0;
+    _g1h->g1_policy()->record_gc_worker_start_time(i, start_time_ms);
+
     ResourceMark rm;
     HandleMark   hm;
 
@@ -4019,7 +4023,7 @@
       double elapsed_ms = (os::elapsedTime()-start)*1000.0;
       double term_ms = pss.term_time()*1000.0;
       _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms);
-      _g1h->g1_policy()->record_termination_time(i, term_ms);
+      _g1h->g1_policy()->record_termination(i, term_ms, pss.term_attempts());
     }
     _g1h->g1_policy()->record_thread_age_table(pss.age_table());
     _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
@@ -4043,7 +4047,8 @@
       double term         = pss.term_time();
       gclog_or_tty->print("  Elapsed: %7.2f ms.\n"
                           "    Strong roots: %7.2f ms (%6.2f%%)\n"
-                          "    Termination:  %7.2f ms (%6.2f%%) (in %d entries)\n",
+                          "    Termination:  %7.2f ms (%6.2f%%) "
+                                                 "(in "SIZE_FORMAT" entries)\n",
                           elapsed * 1000.0,
                           strong_roots * 1000.0, (strong_roots*100.0/elapsed),
                           term * 1000.0, (term*100.0/elapsed),
@@ -4059,6 +4064,8 @@
 
     assert(pss.refs_to_scan() == 0, "Task queue should be empty");
     assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
+    double end_time_ms = os::elapsedTime() * 1000.0;
+    _g1h->g1_policy()->record_gc_worker_end_time(i, end_time_ms);
   }
 };
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1549,7 +1549,7 @@
   int _hash_seed;
   int _queue_num;
 
-  int _term_attempts;
+  size_t _term_attempts;
 #if G1_DETAILED_STATS
   int _pushes, _pops, _steals, _steal_attempts;
   int _overflow_pushes;
@@ -1727,8 +1727,8 @@
   int* hash_seed() { return &_hash_seed; }
   int  queue_num() { return _queue_num; }
 
-  int term_attempts()   { return _term_attempts; }
-  void note_term_attempt()  { _term_attempts++; }
+  size_t term_attempts()   { return _term_attempts; }
+  void note_term_attempt() { _term_attempts++; }
 
 #if G1_DETAILED_STATS
   int pushes()          { return _pushes; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -231,20 +231,21 @@
   _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
   _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
 
+  _par_last_gc_worker_start_times_ms = new double[_parallel_gc_threads];
   _par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads];
   _par_last_mark_stack_scan_times_ms = new double[_parallel_gc_threads];
 
-  _par_last_update_rs_start_times_ms = new double[_parallel_gc_threads];
   _par_last_update_rs_times_ms = new double[_parallel_gc_threads];
   _par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
 
-  _par_last_scan_rs_start_times_ms = new double[_parallel_gc_threads];
   _par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
   _par_last_scan_new_refs_times_ms = new double[_parallel_gc_threads];
 
   _par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
 
   _par_last_termination_times_ms = new double[_parallel_gc_threads];
+  _par_last_termination_attempts = new double[_parallel_gc_threads];
+  _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
 
   // start conservatively
   _expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
@@ -274,10 +275,64 @@
 
   // </NEW PREDICTION>
 
-  double time_slice  = (double) GCPauseIntervalMillis / 1000.0;
+  // Below, we might need to calculate the pause time target based on
+  // the pause interval. When we do so we are going to give G1 maximum
+  // flexibility and allow it to do pauses when it needs to. So, we'll
+  // arrange that the pause interval to be pause time target + 1 to
+  // ensure that a) the pause time target is maximized with respect to
+  // the pause interval and b) we maintain the invariant that pause
+  // time target < pause interval. If the user does not want this
+  // maximum flexibility, they will have to set the pause interval
+  // explicitly.
+
+  // First make sure that, if either parameter is set, its value is
+  // reasonable.
+  if (!FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
+    if (MaxGCPauseMillis < 1) {
+      vm_exit_during_initialization("MaxGCPauseMillis should be "
+                                    "greater than 0");
+    }
+  }
+  if (!FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
+    if (GCPauseIntervalMillis < 1) {
+      vm_exit_during_initialization("GCPauseIntervalMillis should be "
+                                    "greater than 0");
+    }
+  }
+
+  // Then, if the pause time target parameter was not set, set it to
+  // the default value.
+  if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
+    if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
+      // The default pause time target in G1 is 200ms
+      FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
+    } else {
+      // We do not allow the pause interval to be set without the
+      // pause time target
+      vm_exit_during_initialization("GCPauseIntervalMillis cannot be set "
+                                    "without setting MaxGCPauseMillis");
+    }
+  }
+
+  // Then, if the interval parameter was not set, set it according to
+  // the pause time target (this will also deal with the case when the
+  // pause time target is the default value).
+  if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
+    FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
+  }
+
+  // Finally, make sure that the two parameters are consistent.
+  if (MaxGCPauseMillis >= GCPauseIntervalMillis) {
+    char buffer[256];
+    jio_snprintf(buffer, 256,
+                 "MaxGCPauseMillis (%u) should be less than "
+                 "GCPauseIntervalMillis (%u)",
+                 MaxGCPauseMillis, GCPauseIntervalMillis);
+    vm_exit_during_initialization(buffer);
+  }
+
   double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
-  guarantee(max_gc_time < time_slice,
-            "Max GC time should not be greater than the time slice");
+  double time_slice  = (double) GCPauseIntervalMillis / 1000.0;
   _mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
   _sigma = (double) G1ConfidencePercent / 100.0;
 
@@ -782,16 +837,17 @@
   // if they are not set properly
 
   for (int i = 0; i < _parallel_gc_threads; ++i) {
-    _par_last_ext_root_scan_times_ms[i] = -666.0;
-    _par_last_mark_stack_scan_times_ms[i] = -666.0;
-    _par_last_update_rs_start_times_ms[i] = -666.0;
-    _par_last_update_rs_times_ms[i] = -666.0;
-    _par_last_update_rs_processed_buffers[i] = -666.0;
-    _par_last_scan_rs_start_times_ms[i] = -666.0;
-    _par_last_scan_rs_times_ms[i] = -666.0;
-    _par_last_scan_new_refs_times_ms[i] = -666.0;
-    _par_last_obj_copy_times_ms[i] = -666.0;
-    _par_last_termination_times_ms[i] = -666.0;
+    _par_last_gc_worker_start_times_ms[i] = -1234.0;
+    _par_last_ext_root_scan_times_ms[i] = -1234.0;
+    _par_last_mark_stack_scan_times_ms[i] = -1234.0;
+    _par_last_update_rs_times_ms[i] = -1234.0;
+    _par_last_update_rs_processed_buffers[i] = -1234.0;
+    _par_last_scan_rs_times_ms[i] = -1234.0;
+    _par_last_scan_new_refs_times_ms[i] = -1234.0;
+    _par_last_obj_copy_times_ms[i] = -1234.0;
+    _par_last_termination_times_ms[i] = -1234.0;
+    _par_last_termination_attempts[i] = -1234.0;
+    _par_last_gc_worker_end_times_ms[i] = -1234.0;
   }
 #endif
 
@@ -942,9 +998,9 @@
   return sum;
 }
 
-void G1CollectorPolicy::print_par_stats (int level,
-                                         const char* str,
-                                         double* data,
+void G1CollectorPolicy::print_par_stats(int level,
+                                        const char* str,
+                                        double* data,
                                          bool summary) {
   double min = data[0], max = data[0];
   double total = 0.0;
@@ -973,10 +1029,10 @@
   gclog_or_tty->print_cr("]");
 }
 
-void G1CollectorPolicy::print_par_buffers (int level,
-                                         const char* str,
-                                         double* data,
-                                         bool summary) {
+void G1CollectorPolicy::print_par_sizes(int level,
+                                        const char* str,
+                                        double* data,
+                                        bool summary) {
   double min = data[0], max = data[0];
   double total = 0.0;
   int j;
@@ -1321,15 +1377,22 @@
       }
       if (parallel) {
         print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
-        print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false);
+        print_par_stats(2, "GC Worker Start Time",
+                        _par_last_gc_worker_start_times_ms, false);
         print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
-        print_par_buffers(3, "Processed Buffers",
-                          _par_last_update_rs_processed_buffers, true);
-        print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
-        print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
+        print_par_sizes(3, "Processed Buffers",
+                        _par_last_update_rs_processed_buffers, true);
+        print_par_stats(2, "Ext Root Scanning",
+                        _par_last_ext_root_scan_times_ms);
+        print_par_stats(2, "Mark Stack Scanning",
+                        _par_last_mark_stack_scan_times_ms);
         print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
         print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
         print_par_stats(2, "Termination", _par_last_termination_times_ms);
+        print_par_sizes(3, "Termination Attempts",
+                        _par_last_termination_attempts, true);
+        print_par_stats(2, "GC Worker End Time",
+                        _par_last_gc_worker_end_times_ms, false);
         print_stats(2, "Other", parallel_other_time);
         print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
       } else {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -171,16 +171,17 @@
   double*    _cur_aux_times_ms;
   bool*      _cur_aux_times_set;
 
+  double* _par_last_gc_worker_start_times_ms;
   double* _par_last_ext_root_scan_times_ms;
   double* _par_last_mark_stack_scan_times_ms;
-  double* _par_last_update_rs_start_times_ms;
   double* _par_last_update_rs_times_ms;
   double* _par_last_update_rs_processed_buffers;
-  double* _par_last_scan_rs_start_times_ms;
   double* _par_last_scan_rs_times_ms;
   double* _par_last_scan_new_refs_times_ms;
   double* _par_last_obj_copy_times_ms;
   double* _par_last_termination_times_ms;
+  double* _par_last_termination_attempts;
+  double* _par_last_gc_worker_end_times_ms;
 
   // indicates that we are in young GC mode
   bool _in_young_gc_mode;
@@ -559,13 +560,14 @@
   }
 
 protected:
-  void print_stats (int level, const char* str, double value);
-  void print_stats (int level, const char* str, int value);
-  void print_par_stats (int level, const char* str, double* data) {
+  void print_stats(int level, const char* str, double value);
+  void print_stats(int level, const char* str, int value);
+
+  void print_par_stats(int level, const char* str, double* data) {
     print_par_stats(level, str, data, true);
   }
-  void print_par_stats (int level, const char* str, double* data, bool summary);
-  void print_par_buffers (int level, const char* str, double* data, bool summary);
+  void print_par_stats(int level, const char* str, double* data, bool summary);
+  void print_par_sizes(int level, const char* str, double* data, bool summary);
 
   void check_other_times(int level,
                          NumberSeq* other_times_ms,
@@ -891,6 +893,10 @@
   virtual void record_full_collection_start();
   virtual void record_full_collection_end();
 
+  void record_gc_worker_start_time(int worker_i, double ms) {
+    _par_last_gc_worker_start_times_ms[worker_i] = ms;
+  }
+
   void record_ext_root_scan_time(int worker_i, double ms) {
     _par_last_ext_root_scan_times_ms[worker_i] = ms;
   }
@@ -912,10 +918,6 @@
     _all_mod_union_times_ms->add(ms);
   }
 
-  void record_update_rs_start_time(int thread, double ms) {
-    _par_last_update_rs_start_times_ms[thread] = ms;
-  }
-
   void record_update_rs_time(int thread, double ms) {
     _par_last_update_rs_times_ms[thread] = ms;
   }
@@ -925,10 +927,6 @@
     _par_last_update_rs_processed_buffers[thread] = processed_buffers;
   }
 
-  void record_scan_rs_start_time(int thread, double ms) {
-    _par_last_scan_rs_start_times_ms[thread] = ms;
-  }
-
   void record_scan_rs_time(int thread, double ms) {
     _par_last_scan_rs_times_ms[thread] = ms;
   }
@@ -953,16 +951,13 @@
     _par_last_obj_copy_times_ms[thread] += ms;
   }
 
-  void record_obj_copy_time(double ms) {
-    record_obj_copy_time(0, ms);
+  void record_termination(int thread, double ms, size_t attempts) {
+    _par_last_termination_times_ms[thread] = ms;
+    _par_last_termination_attempts[thread] = (double) attempts;
   }
 
-  void record_termination_time(int thread, double ms) {
-    _par_last_termination_times_ms[thread] = ms;
-  }
-
-  void record_termination_time(double ms) {
-    record_termination_time(0, ms);
+  void record_gc_worker_end_time(int worker_i, double ms) {
+    _par_last_gc_worker_end_times_ms[worker_i] = ms;
   }
 
   void record_pause_time_ms(double ms) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -303,7 +303,6 @@
   assert( _cards_scanned != NULL, "invariant" );
   _cards_scanned[worker_i] = scanRScl.cards_done();
 
-  _g1p->record_scan_rs_start_time(worker_i, rs_time_start * 1000.0);
   _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
 }
 
@@ -311,8 +310,6 @@
   ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
 
   double start = os::elapsedTime();
-  _g1p->record_update_rs_start_time(worker_i, start * 1000.0);
-
   // Apply the appropriate closure to all remaining log entries.
   _g1->iterate_dirty_card_closure(false, worker_i);
   // Now there should be no dirty cards.
@@ -471,7 +468,6 @@
       updateRS(worker_i);
       scanNewRefsRS(oc, worker_i);
     } else {
-      _g1p->record_update_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
       _g1p->record_update_rs_processed_buffers(worker_i, 0.0);
       _g1p->record_update_rs_time(worker_i, 0.0);
       _g1p->record_scan_new_refs_time(worker_i, 0.0);
@@ -479,7 +475,6 @@
     if (G1UseParallelRSetScanning || (worker_i == 0)) {
       scanRS(oc, worker_i);
     } else {
-      _g1p->record_scan_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
       _g1p->record_scan_rs_time(worker_i, 0.0);
     }
   } else {
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Wed Jul 05 17:17:57 2017 +0200
@@ -270,7 +270,7 @@
 psParallelCompact.cpp			pcTasks.hpp
 psParallelCompact.cpp			psMarkSweep.hpp
 psParallelCompact.cpp			psMarkSweepDecorator.hpp
-psParallelCompact.cpp			psCompactionManager.hpp
+psParallelCompact.cpp			psCompactionManager.inline.hpp
 psParallelCompact.cpp                   psPromotionManager.inline.hpp
 psParallelCompact.cpp			psOldGen.hpp
 psParallelCompact.cpp			psParallelCompact.hpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -566,14 +566,14 @@
 #endif
 
   // Commit new or uncommit old pages, if necessary.
-  resize_commit_uncommit(changed_region, new_region);
+  if (resize_commit_uncommit(changed_region, new_region)) {
+    // Set the new start of the committed region
+    resize_update_committed_table(changed_region, new_region);
+  }
 
   // Update card table entries
   resize_update_card_table_entries(changed_region, new_region);
 
-  // Set the new start of the committed region
-  resize_update_committed_table(changed_region, new_region);
-
   // Update the covered region
   resize_update_covered_table(changed_region, new_region);
 
@@ -604,8 +604,9 @@
   debug_only(verify_guard();)
 }
 
-void CardTableExtension::resize_commit_uncommit(int changed_region,
+bool CardTableExtension::resize_commit_uncommit(int changed_region,
                                                 MemRegion new_region) {
+  bool result = false;
   // Commit new or uncommit old pages, if necessary.
   MemRegion cur_committed = _committed[changed_region];
   assert(_covered[changed_region].end() == new_region.end(),
@@ -675,20 +676,31 @@
                               "card table expansion");
       }
     }
+    result = true;
   } else if (new_start_aligned > cur_committed.start()) {
     // Shrink the committed region
+#if 0 // uncommitting space is currently unsafe because of the interactions
+      // of growing and shrinking regions.  One region A can uncommit space
+      // that it owns but which is being used by another region B (maybe).
+      // Region B has not committed the space because it was already
+      // committed by region A.
     MemRegion uncommit_region = committed_unique_to_self(changed_region,
       MemRegion(cur_committed.start(), new_start_aligned));
     if (!uncommit_region.is_empty()) {
       if (!os::uncommit_memory((char*)uncommit_region.start(),
                                uncommit_region.byte_size())) {
-        vm_exit_out_of_memory(uncommit_region.byte_size(),
-          "card table contraction");
+        // If the uncommit fails, ignore it.  Let the
+        // committed table resizing go even though the committed
+        // table will over state the committed space.
       }
     }
+#else
+    assert(!result, "Should be false with current workaround");
+#endif
   }
   assert(_committed[changed_region].end() == cur_committed.end(),
     "end should not change");
+  return result;
 }
 
 void CardTableExtension::resize_update_committed_table(int changed_region,
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -30,7 +30,9 @@
 class CardTableExtension : public CardTableModRefBS {
  private:
   // Support methods for resizing the card table.
-  void resize_commit_uncommit(int changed_region, MemRegion new_region);
+  // resize_commit_uncommit() returns true if the pages were committed or
+  // uncommitted
+  bool resize_commit_uncommit(int changed_region, MemRegion new_region);
   void resize_update_card_table_entries(int changed_region,
                                         MemRegion new_region);
   void resize_update_committed_table(int changed_region, MemRegion new_region);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -32,7 +32,7 @@
   ParCompactionManager::_objarray_queues = NULL;
 ObjectStartArray*    ParCompactionManager::_start_array = NULL;
 ParMarkBitMap*       ParCompactionManager::_mark_bitmap = NULL;
-RegionTaskQueueSet*   ParCompactionManager::_region_array = NULL;
+RegionTaskQueueSet*  ParCompactionManager::_region_array = NULL;
 
 ParCompactionManager::ParCompactionManager() :
     _action(CopyAndUpdate) {
@@ -43,25 +43,9 @@
   _old_gen = heap->old_gen();
   _start_array = old_gen()->start_array();
 
-
   marking_stack()->initialize();
-
-  // We want the overflow stack to be permanent
-  _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
-
-  _objarray_queue.initialize();
-  _objarray_overflow_stack =
-    new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true);
-
-#ifdef USE_RegionTaskQueueWithOverflow
+  _objarray_stack.initialize();
   region_stack()->initialize();
-#else
-  region_stack()->initialize();
-
-  // We want the overflow stack to be permanent
-  _region_overflow_stack =
-    new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true);
-#endif
 
   // Note that _revisit_klass_stack is allocated out of the
   // C heap (as opposed to out of ResourceArena).
@@ -71,12 +55,9 @@
   // From some experiments (#klass/k)^2 for k = 10 seems a better fit, but this will
   // have to do for now until we are able to investigate a more optimal setting.
   _revisit_mdo_stack = new (ResourceObj::C_HEAP) GrowableArray<DataLayout*>(size*2, true);
-
 }
 
 ParCompactionManager::~ParCompactionManager() {
-  delete _overflow_stack;
-  delete _objarray_overflow_stack;
   delete _revisit_klass_stack;
   delete _revisit_mdo_stack;
   // _manager_array and _stack_array are statics
@@ -108,12 +89,8 @@
     _manager_array[i] = new ParCompactionManager();
     guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");
     stack_array()->register_queue(i, _manager_array[i]->marking_stack());
-    _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue);
-#ifdef USE_RegionTaskQueueWithOverflow
-    region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue());
-#else
+    _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack);
     region_array()->register_queue(i, _manager_array[i]->region_stack());
-#endif
   }
 
   // The VMThread gets its own ParCompactionManager, which is not available
@@ -149,57 +126,6 @@
   return action() == ParCompactionManager::ResetObjects;
 }
 
-// For now save on a stack
-void ParCompactionManager::save_for_scanning(oop m) {
-  stack_push(m);
-}
-
-void ParCompactionManager::stack_push(oop obj) {
-
-  if(!marking_stack()->push(obj)) {
-    overflow_stack()->push(obj);
-  }
-}
-
-oop ParCompactionManager::retrieve_for_scanning() {
-
-  // Should not be used in the parallel case
-  ShouldNotReachHere();
-  return NULL;
-}
-
-// Save region on a stack
-void ParCompactionManager::save_for_processing(size_t region_index) {
-#ifdef ASSERT
-  const ParallelCompactData& sd = PSParallelCompact::summary_data();
-  ParallelCompactData::RegionData* const region_ptr = sd.region(region_index);
-  assert(region_ptr->claimed(), "must be claimed");
-  assert(region_ptr->_pushed++ == 0, "should only be pushed once");
-#endif
-  region_stack_push(region_index);
-}
-
-void ParCompactionManager::region_stack_push(size_t region_index) {
-
-#ifdef USE_RegionTaskQueueWithOverflow
-  region_stack()->save(region_index);
-#else
-  if(!region_stack()->push(region_index)) {
-    region_overflow_stack()->push(region_index);
-  }
-#endif
-}
-
-bool ParCompactionManager::retrieve_for_processing(size_t& region_index) {
-#ifdef USE_RegionTaskQueueWithOverflow
-  return region_stack()->retrieve(region_index);
-#else
-  // Should not be used in the parallel case
-  ShouldNotReachHere();
-  return false;
-#endif
-}
-
 ParCompactionManager*
 ParCompactionManager::gc_thread_compaction_manager(int index) {
   assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");
@@ -218,8 +144,8 @@
   do {
     // Drain the overflow stack first, to allow stealing from the marking stack.
     oop obj;
-    while (!overflow_stack()->is_empty()) {
-      overflow_stack()->pop()->follow_contents(this);
+    while (marking_stack()->pop_overflow(obj)) {
+      obj->follow_contents(this);
     }
     while (marking_stack()->pop_local(obj)) {
       obj->follow_contents(this);
@@ -227,11 +153,10 @@
 
     // Process ObjArrays one at a time to avoid marking stack bloat.
     ObjArrayTask task;
-    if (!_objarray_overflow_stack->is_empty()) {
-      task = _objarray_overflow_stack->pop();
+    if (_objarray_stack.pop_overflow(task)) {
       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
       k->oop_follow_contents(this, task.obj(), task.index());
-    } else if (_objarray_queue.pop_local(task)) {
+    } else if (_objarray_stack.pop_local(task)) {
       objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
       k->oop_follow_contents(this, task.obj(), task.index());
     }
@@ -240,68 +165,18 @@
   assert(marking_stacks_empty(), "Sanity");
 }
 
-void ParCompactionManager::drain_region_overflow_stack() {
-  size_t region_index = (size_t) -1;
-  while(region_stack()->retrieve_from_overflow(region_index)) {
-    PSParallelCompact::fill_and_update_region(this, region_index);
-  }
-}
-
 void ParCompactionManager::drain_region_stacks() {
-#ifdef ASSERT
-  ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
-  MutableSpace* to_space = heap->young_gen()->to_space();
-  MutableSpace* old_space = heap->old_gen()->object_space();
-  MutableSpace* perm_space = heap->perm_gen()->object_space();
-#endif /* ASSERT */
-
-#if 1 // def DO_PARALLEL - the serial code hasn't been updated
   do {
-
-#ifdef USE_RegionTaskQueueWithOverflow
-    // Drain overflow stack first, so other threads can steal from
-    // claimed stack while we work.
-    size_t region_index = (size_t) -1;
-    while(region_stack()->retrieve_from_overflow(region_index)) {
+    // Drain overflow stack first so other threads can steal.
+    size_t region_index;
+    while (region_stack()->pop_overflow(region_index)) {
       PSParallelCompact::fill_and_update_region(this, region_index);
     }
 
-    while (region_stack()->retrieve_from_stealable_queue(region_index)) {
+    while (region_stack()->pop_local(region_index)) {
       PSParallelCompact::fill_and_update_region(this, region_index);
     }
   } while (!region_stack()->is_empty());
-#else
-    // Drain overflow stack first, so other threads can steal from
-    // claimed stack while we work.
-    while(!region_overflow_stack()->is_empty()) {
-      size_t region_index = region_overflow_stack()->pop();
-      PSParallelCompact::fill_and_update_region(this, region_index);
-    }
-
-    size_t region_index = -1;
-    // obj is a reference!!!
-    while (region_stack()->pop_local(region_index)) {
-      // It would be nice to assert about the type of objects we might
-      // pop, but they can come from anywhere, unfortunately.
-      PSParallelCompact::fill_and_update_region(this, region_index);
-    }
-  } while((region_stack()->size() != 0) ||
-          (region_overflow_stack()->length() != 0));
-#endif
-
-#ifdef USE_RegionTaskQueueWithOverflow
-  assert(region_stack()->is_empty(), "Sanity");
-#else
-  assert(region_stack()->size() == 0, "Sanity");
-  assert(region_overflow_stack()->length() == 0, "Sanity");
-#endif
-#else
-  oop obj;
-  while (obj = retrieve_for_scanning()) {
-    obj->follow_contents(this);
-  }
-#endif
 }
 
 #ifdef ASSERT
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -59,10 +59,10 @@
 
  private:
   // 32-bit:  4K * 8 = 32KiB; 64-bit:  8K * 16 = 128KiB
-  #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
-  typedef GenericTaskQueue<ObjArrayTask, OBJARRAY_QUEUE_SIZE> ObjArrayTaskQueue;
-  typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
-  #undef OBJARRAY_QUEUE_SIZE
+  #define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
+  typedef OverflowTaskQueue<ObjArrayTask, QUEUE_SIZE> ObjArrayTaskQueue;
+  typedef GenericTaskQueueSet<ObjArrayTaskQueue>      ObjArrayTaskQueueSet;
+  #undef QUEUE_SIZE
 
   static ParCompactionManager** _manager_array;
   static OopTaskQueueSet*       _stack_array;
@@ -72,23 +72,13 @@
   static PSOldGen*              _old_gen;
 
 private:
-  OopTaskQueue                  _marking_stack;
-  GrowableArray<oop>*           _overflow_stack;
-
-  typedef GrowableArray<ObjArrayTask> ObjArrayOverflowStack;
-  ObjArrayTaskQueue             _objarray_queue;
-  ObjArrayOverflowStack*        _objarray_overflow_stack;
+  OverflowTaskQueue<oop>        _marking_stack;
+  ObjArrayTaskQueue             _objarray_stack;
 
   // Is there a way to reuse the _marking_stack for the
   // saving empty regions?  For now just create a different
   // type of TaskQueue.
-
-#ifdef USE_RegionTaskQueueWithOverflow
-  RegionTaskQueueWithOverflow   _region_stack;
-#else
   RegionTaskQueue               _region_stack;
-  GrowableArray<size_t>*        _region_overflow_stack;
-#endif
 
 #if 1  // does this happen enough to need a per thread stack?
   GrowableArray<Klass*>*        _revisit_klass_stack;
@@ -107,16 +97,8 @@
  protected:
   // Array of tasks.  Needed by the ParallelTaskTerminator.
   static RegionTaskQueueSet* region_array()      { return _region_array; }
-  OopTaskQueue*  marking_stack()                 { return &_marking_stack; }
-  GrowableArray<oop>* overflow_stack()           { return _overflow_stack; }
-#ifdef USE_RegionTaskQueueWithOverflow
-  RegionTaskQueueWithOverflow* region_stack()    { return &_region_stack; }
-#else
-  RegionTaskQueue*  region_stack()               { return &_region_stack; }
-  GrowableArray<size_t>* region_overflow_stack() {
-    return _region_overflow_stack;
-  }
-#endif
+  OverflowTaskQueue<oop>*  marking_stack()       { return &_marking_stack; }
+  RegionTaskQueue* region_stack()                { return &_region_stack; }
 
   // Pushes onto the marking stack.  If the marking stack is full,
   // pushes onto the overflow stack.
@@ -124,11 +106,7 @@
   // Do not implement an equivalent stack_pop.  Deal with the
   // marking stack and overflow stack directly.
 
-  // Pushes onto the region stack.  If the region stack is full,
-  // pushes onto the region overflow stack.
-  void region_stack_push(size_t region_index);
-
-public:
+ public:
   Action action() { return _action; }
   void set_action(Action v) { _action = v; }
 
@@ -157,22 +135,15 @@
   GrowableArray<DataLayout*>* revisit_mdo_stack() { return _revisit_mdo_stack; }
 #endif
 
-  // Save oop for later processing.  Must not fail.
-  void save_for_scanning(oop m);
-  // Get a oop for scanning.  If returns null, no oop were found.
-  oop retrieve_for_scanning();
-
-  inline void push_objarray(oop obj, size_t index);
-
-  // Save region for later processing.  Must not fail.
-  void save_for_processing(size_t region_index);
-  // Get a region for processing.  If returns null, no region were found.
-  bool retrieve_for_processing(size_t& region_index);
+  // Save for later processing.  Must not fail.
+  inline void push(oop obj) { _marking_stack.push(obj); }
+  inline void push_objarray(oop objarray, size_t index);
+  inline void push_region(size_t index);
 
   // Access function for compaction managers
   static ParCompactionManager* gc_thread_compaction_manager(int index);
 
-  static bool steal(int queue_num, int* seed, Task& t) {
+  static bool steal(int queue_num, int* seed, oop& t) {
     return stack_array()->steal(queue_num, seed, t);
   }
 
@@ -180,8 +151,8 @@
     return _objarray_queues->steal(queue_num, seed, t);
   }
 
-  static bool steal(int queue_num, int* seed, RegionTask& t) {
-    return region_array()->steal(queue_num, seed, t);
+  static bool steal(int queue_num, int* seed, size_t& region) {
+    return region_array()->steal(queue_num, seed, region);
   }
 
   // Process tasks remaining on any marking stack
@@ -191,9 +162,6 @@
   // Process tasks remaining on any stack
   void drain_region_stacks();
 
-  // Process tasks remaining on any stack
-  void drain_region_overflow_stack();
-
   // Debugging support
 #ifdef ASSERT
   bool stacks_have_been_allocated();
@@ -208,6 +176,5 @@
 }
 
 bool ParCompactionManager::marking_stacks_empty() const {
-  return _marking_stack.size() == 0 && _overflow_stack->is_empty() &&
-    _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty();
+  return _marking_stack.is_empty() && _objarray_stack.is_empty();
 }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -26,7 +26,16 @@
 {
   ObjArrayTask task(obj, index);
   assert(task.is_valid(), "bad ObjArrayTask");
-  if (!_objarray_queue.push(task)) {
-    _objarray_overflow_stack->push(task);
-  }
+  _objarray_stack.push(task);
 }
+
+void ParCompactionManager::push_region(size_t index)
+{
+#ifdef ASSERT
+  const ParallelCompactData& sd = PSParallelCompact::summary_data();
+  ParallelCompactData::RegionData* const region_ptr = sd.region(index);
+  assert(region_ptr->claimed(), "must be claimed");
+  assert(region_ptr->_pushed++ == 0, "should only be pushed once");
+#endif
+  region_stack()->push(index);
+}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -2474,7 +2474,7 @@
     for (size_t cur = end_region - 1; cur >= beg_region; --cur) {
       if (sd.region(cur)->claim_unsafe()) {
         ParCompactionManager* cm = ParCompactionManager::manager_array(which);
-        cm->save_for_processing(cur);
+        cm->push_region(cur);
 
         if (TraceParallelOldGCCompactionPhase && Verbose) {
           const size_t count_mod_8 = fillable_regions & 7;
@@ -3138,7 +3138,7 @@
     assert(cur->data_size() > 0, "region must have live data");
     cur->decrement_destination_count();
     if (cur < enqueue_end && cur->available() && cur->claim()) {
-      cm->save_for_processing(sd.region(cur));
+      cm->push_region(sd.region(cur));
     }
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -1297,11 +1297,8 @@
   T heap_oop = oopDesc::load_heap_oop(p);
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    if (mark_bitmap()->is_unmarked(obj)) {
-      if (mark_obj(obj)) {
-        // This thread marked the object and owns the subsequent processing of it.
-        cm->save_for_scanning(obj);
-      }
+    if (mark_bitmap()->is_unmarked(obj) && mark_obj(obj)) {
+      cm->push(obj);
     }
   }
 }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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,45 +94,13 @@
   print_stats();
 #endif // PS_PM_STATS
 
-  for(uint i=0; i<ParallelGCThreads+1; i++) {
+  for (uint i = 0; i < ParallelGCThreads + 1; i++) {
     PSPromotionManager* manager = manager_array(i);
-
-    // the guarantees are a bit gratuitous but, if one fires, we'll
-    // have a better idea of what went wrong
-    if (i < ParallelGCThreads) {
-      guarantee((!UseDepthFirstScavengeOrder ||
-                 manager->overflow_stack_depth()->length() <= 0),
-                "promotion manager overflow stack must be empty");
-      guarantee((UseDepthFirstScavengeOrder ||
-                 manager->overflow_stack_breadth()->length() <= 0),
-                "promotion manager overflow stack must be empty");
-
-      guarantee((!UseDepthFirstScavengeOrder ||
-                 manager->claimed_stack_depth()->size() <= 0),
-                "promotion manager claimed stack must be empty");
-      guarantee((UseDepthFirstScavengeOrder ||
-                 manager->claimed_stack_breadth()->size() <= 0),
-                "promotion manager claimed stack must be empty");
+    if (UseDepthFirstScavengeOrder) {
+      assert(manager->claimed_stack_depth()->is_empty(), "should be empty");
     } else {
-      guarantee((!UseDepthFirstScavengeOrder ||
-                 manager->overflow_stack_depth()->length() <= 0),
-                "VM Thread promotion manager overflow stack "
-                "must be empty");
-      guarantee((UseDepthFirstScavengeOrder ||
-                 manager->overflow_stack_breadth()->length() <= 0),
-                "VM Thread promotion manager overflow stack "
-                "must be empty");
-
-      guarantee((!UseDepthFirstScavengeOrder ||
-                 manager->claimed_stack_depth()->size() <= 0),
-                "VM Thread promotion manager claimed stack "
-                "must be empty");
-      guarantee((UseDepthFirstScavengeOrder ||
-                 manager->claimed_stack_breadth()->size() <= 0),
-                "VM Thread promotion manager claimed stack "
-                "must be empty");
+      assert(manager->claimed_stack_breadth()->is_empty(), "should be empty");
     }
-
     manager->flush_labs();
   }
 }
@@ -181,15 +149,9 @@
   if (depth_first()) {
     claimed_stack_depth()->initialize();
     queue_size = claimed_stack_depth()->max_elems();
-    // We want the overflow stack to be permanent
-    _overflow_stack_depth = new (ResourceObj::C_HEAP) GrowableArray<StarTask>(10, true);
-    _overflow_stack_breadth = NULL;
   } else {
     claimed_stack_breadth()->initialize();
     queue_size = claimed_stack_breadth()->max_elems();
-    // We want the overflow stack to be permanent
-    _overflow_stack_breadth = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true);
-    _overflow_stack_depth = NULL;
   }
 
   _totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0);
@@ -209,8 +171,7 @@
 }
 
 void PSPromotionManager::reset() {
-  assert(claimed_stack_empty(), "reset of non-empty claimed stack");
-  assert(overflow_stack_empty(), "reset of non-empty overflow stack");
+  assert(stacks_empty(), "reset of non-empty stack");
 
   // We need to get an assert in here to make sure the labs are always flushed.
 
@@ -243,7 +204,7 @@
 
 void PSPromotionManager::drain_stacks_depth(bool totally_drain) {
   assert(depth_first(), "invariant");
-  assert(overflow_stack_depth() != NULL, "invariant");
+  assert(claimed_stack_depth()->overflow_stack() != NULL, "invariant");
   totally_drain = totally_drain || _totally_drain;
 
 #ifdef ASSERT
@@ -254,41 +215,35 @@
   MutableSpace* perm_space = heap->perm_gen()->object_space();
 #endif /* ASSERT */
 
+  OopStarTaskQueue* const tq = claimed_stack_depth();
   do {
     StarTask p;
 
     // Drain overflow stack first, so other threads can steal from
     // claimed stack while we work.
-    while(!overflow_stack_depth()->is_empty()) {
-      // linux compiler wants different overloaded operator= in taskqueue to
-      // assign to p that the other compilers don't like.
-      StarTask ptr = overflow_stack_depth()->pop();
-      process_popped_location_depth(ptr);
+    while (tq->pop_overflow(p)) {
+      process_popped_location_depth(p);
     }
 
     if (totally_drain) {
-      while (claimed_stack_depth()->pop_local(p)) {
+      while (tq->pop_local(p)) {
         process_popped_location_depth(p);
       }
     } else {
-      while (claimed_stack_depth()->size() > _target_stack_size &&
-             claimed_stack_depth()->pop_local(p)) {
+      while (tq->size() > _target_stack_size && tq->pop_local(p)) {
         process_popped_location_depth(p);
       }
     }
-  } while( (totally_drain && claimed_stack_depth()->size() > 0) ||
-           (overflow_stack_depth()->length() > 0) );
+  } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
 
-  assert(!totally_drain || claimed_stack_empty(), "Sanity");
-  assert(totally_drain ||
-         claimed_stack_depth()->size() <= _target_stack_size,
-         "Sanity");
-  assert(overflow_stack_empty(), "Sanity");
+  assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
+  assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
+  assert(tq->overflow_empty(), "Sanity");
 }
 
 void PSPromotionManager::drain_stacks_breadth(bool totally_drain) {
   assert(!depth_first(), "invariant");
-  assert(overflow_stack_breadth() != NULL, "invariant");
+  assert(claimed_stack_breadth()->overflow_stack() != NULL, "invariant");
   totally_drain = totally_drain || _totally_drain;
 
 #ifdef ASSERT
@@ -299,51 +254,39 @@
   MutableSpace* perm_space = heap->perm_gen()->object_space();
 #endif /* ASSERT */
 
+  OverflowTaskQueue<oop>* const tq = claimed_stack_breadth();
   do {
     oop obj;
 
     // Drain overflow stack first, so other threads can steal from
     // claimed stack while we work.
-    while(!overflow_stack_breadth()->is_empty()) {
-      obj = overflow_stack_breadth()->pop();
+    while (tq->pop_overflow(obj)) {
       obj->copy_contents(this);
     }
 
     if (totally_drain) {
-      // obj is a reference!!!
-      while (claimed_stack_breadth()->pop_local(obj)) {
-        // It would be nice to assert about the type of objects we might
-        // pop, but they can come from anywhere, unfortunately.
+      while (tq->pop_local(obj)) {
         obj->copy_contents(this);
       }
     } else {
-      // obj is a reference!!!
-      while (claimed_stack_breadth()->size() > _target_stack_size &&
-             claimed_stack_breadth()->pop_local(obj)) {
-        // It would be nice to assert about the type of objects we might
-        // pop, but they can come from anywhere, unfortunately.
+      while (tq->size() > _target_stack_size && tq->pop_local(obj)) {
         obj->copy_contents(this);
       }
     }
 
     // If we could not find any other work, flush the prefetch queue
-    if (claimed_stack_breadth()->size() == 0 &&
-        (overflow_stack_breadth()->length() == 0)) {
+    if (tq->is_empty()) {
       flush_prefetch_queue();
     }
-  } while((totally_drain && claimed_stack_breadth()->size() > 0) ||
-          (overflow_stack_breadth()->length() > 0));
+  } while (totally_drain && !tq->taskqueue_empty() || !tq->overflow_empty());
 
-  assert(!totally_drain || claimed_stack_empty(), "Sanity");
-  assert(totally_drain ||
-         claimed_stack_breadth()->size() <= _target_stack_size,
-         "Sanity");
-  assert(overflow_stack_empty(), "Sanity");
+  assert(!totally_drain || tq->taskqueue_empty(), "Sanity");
+  assert(totally_drain || tq->size() <= _target_stack_size, "Sanity");
+  assert(tq->overflow_empty(), "Sanity");
 }
 
 void PSPromotionManager::flush_labs() {
-  assert(claimed_stack_empty(), "Attempt to flush lab with live stack");
-  assert(overflow_stack_empty(), "Attempt to flush lab with live overflow stack");
+  assert(stacks_empty(), "Attempt to flush lab with live stack");
 
   // If either promotion lab fills up, we can flush the
   // lab but not refill it, so check first.
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, 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
@@ -78,9 +78,7 @@
   PrefetchQueue                       _prefetch_queue;
 
   OopStarTaskQueue                    _claimed_stack_depth;
-  GrowableArray<StarTask>*            _overflow_stack_depth;
-  OopTaskQueue                        _claimed_stack_breadth;
-  GrowableArray<oop>*                 _overflow_stack_breadth;
+  OverflowTaskQueue<oop>              _claimed_stack_breadth;
 
   bool                                _depth_first;
   bool                                _totally_drain;
@@ -97,9 +95,6 @@
   template <class T> inline void claim_or_forward_internal_depth(T* p);
   template <class T> inline void claim_or_forward_internal_breadth(T* p);
 
-  GrowableArray<StarTask>* overflow_stack_depth() { return _overflow_stack_depth; }
-  GrowableArray<oop>*  overflow_stack_breadth()   { return _overflow_stack_breadth; }
-
   // On the task queues we push reference locations as well as
   // partially-scanned arrays (in the latter case, we push an oop to
   // the from-space image of the array and the length on the
@@ -151,18 +146,19 @@
 
 #if PS_PM_STATS
     ++_total_pushes;
+    int stack_length = claimed_stack_depth()->overflow_stack()->length();
 #endif // PS_PM_STATS
 
-    if (!claimed_stack_depth()->push(p)) {
-      overflow_stack_depth()->push(p);
+    claimed_stack_depth()->push(p);
+
 #if PS_PM_STATS
+    if (claimed_stack_depth()->overflow_stack()->length() != stack_length) {
       ++_overflow_pushes;
-      uint stack_length = (uint) overflow_stack_depth()->length();
-      if (stack_length > _max_overflow_length) {
-        _max_overflow_length = stack_length;
+      if ((uint)stack_length + 1 > _max_overflow_length) {
+        _max_overflow_length = (uint)stack_length + 1;
       }
+    }
 #endif // PS_PM_STATS
-    }
   }
 
   void push_breadth(oop o) {
@@ -170,18 +166,19 @@
 
 #if PS_PM_STATS
     ++_total_pushes;
+    int stack_length = claimed_stack_breadth()->overflow_stack()->length();
 #endif // PS_PM_STATS
 
-    if(!claimed_stack_breadth()->push(o)) {
-      overflow_stack_breadth()->push(o);
+    claimed_stack_breadth()->push(o);
+
 #if PS_PM_STATS
+    if (claimed_stack_breadth()->overflow_stack()->length() != stack_length) {
       ++_overflow_pushes;
-      uint stack_length = (uint) overflow_stack_breadth()->length();
-      if (stack_length > _max_overflow_length) {
-        _max_overflow_length = stack_length;
+      if ((uint)stack_length + 1 > _max_overflow_length) {
+        _max_overflow_length = (uint)stack_length + 1;
       }
+    }
 #endif // PS_PM_STATS
-    }
   }
 
  protected:
@@ -199,12 +196,10 @@
   static PSPromotionManager* vm_thread_promotion_manager();
 
   static bool steal_depth(int queue_num, int* seed, StarTask& t) {
-    assert(stack_array_depth() != NULL, "invariant");
     return stack_array_depth()->steal(queue_num, seed, t);
   }
 
-  static bool steal_breadth(int queue_num, int* seed, Task& t) {
-    assert(stack_array_breadth() != NULL, "invariant");
+  static bool steal_breadth(int queue_num, int* seed, oop& t) {
     return stack_array_breadth()->steal(queue_num, seed, t);
   }
 
@@ -214,7 +209,7 @@
   OopStarTaskQueue* claimed_stack_depth() {
     return &_claimed_stack_depth;
   }
-  OopTaskQueue* claimed_stack_breadth() {
+  OverflowTaskQueue<oop>* claimed_stack_breadth() {
     return &_claimed_stack_breadth;
   }
 
@@ -246,25 +241,13 @@
   void drain_stacks_depth(bool totally_drain);
   void drain_stacks_breadth(bool totally_drain);
 
-  bool claimed_stack_empty() {
-    if (depth_first()) {
-      return claimed_stack_depth()->size() <= 0;
-    } else {
-      return claimed_stack_breadth()->size() <= 0;
-    }
-  }
-  bool overflow_stack_empty() {
-    if (depth_first()) {
-      return overflow_stack_depth()->length() <= 0;
-    } else {
-      return overflow_stack_breadth()->length() <= 0;
-    }
+  bool depth_first() const {
+    return _depth_first;
   }
   bool stacks_empty() {
-    return claimed_stack_empty() && overflow_stack_empty();
-  }
-  bool depth_first() {
-    return _depth_first;
+    return depth_first() ?
+      claimed_stack_depth()->is_empty() :
+      claimed_stack_breadth()->is_empty();
   }
 
   inline void process_popped_location_depth(StarTask p);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -414,7 +414,6 @@
     }
 
     // Finally, flush the promotion_manager's labs, and deallocate its stacks.
-    assert(promotion_manager->claimed_stack_empty(), "Sanity");
     PSPromotionManager::post_scavenge();
 
     promotion_failure_occurred = promotion_failed();
--- a/hotspot/src/share/vm/includeDB_compiler2	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler2	Wed Jul 05 17:17:57 2017 +0200
@@ -89,6 +89,21 @@
 
 allocation.hpp                          c2_globals.hpp
 
+bcEscapeAnalyzer.cpp                    bcEscapeAnalyzer.hpp
+bcEscapeAnalyzer.cpp                    bitMap.inline.hpp
+bcEscapeAnalyzer.cpp                    bytecode.hpp
+bcEscapeAnalyzer.cpp                    ciConstant.hpp
+bcEscapeAnalyzer.cpp                    ciField.hpp
+bcEscapeAnalyzer.cpp                    ciMethodBlocks.hpp
+bcEscapeAnalyzer.cpp                    ciStreams.hpp
+
+bcEscapeAnalyzer.hpp                    allocation.hpp
+bcEscapeAnalyzer.hpp                    ciMethod.hpp
+bcEscapeAnalyzer.hpp                    ciMethodData.hpp
+bcEscapeAnalyzer.hpp                    dependencies.hpp
+bcEscapeAnalyzer.hpp                    growableArray.hpp
+bcEscapeAnalyzer.hpp                    vectset.hpp
+
 block.cpp                               allocation.inline.hpp
 block.cpp                               block.hpp
 block.cpp                               cfgnode.hpp
@@ -239,6 +254,7 @@
 ciEnv.cpp                               compileLog.hpp
 ciEnv.cpp                               runtime.hpp
 
+ciMethod.cpp                            bcEscapeAnalyzer.hpp
 ciMethod.cpp                            ciTypeFlow.hpp
 ciMethod.cpp                            methodOop.hpp
 
--- a/hotspot/src/share/vm/includeDB_core	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_core	Wed Jul 05 17:17:57 2017 +0200
@@ -301,20 +301,6 @@
 barrierSet.inline.hpp                   barrierSet.hpp
 barrierSet.inline.hpp                   cardTableModRefBS.hpp
 
-bcEscapeAnalyzer.cpp                    bcEscapeAnalyzer.hpp
-bcEscapeAnalyzer.cpp                    bitMap.inline.hpp
-bcEscapeAnalyzer.cpp                    bytecode.hpp
-bcEscapeAnalyzer.cpp                    ciConstant.hpp
-bcEscapeAnalyzer.cpp                    ciField.hpp
-bcEscapeAnalyzer.cpp                    ciMethodBlocks.hpp
-bcEscapeAnalyzer.cpp                    ciStreams.hpp
-
-bcEscapeAnalyzer.hpp                    allocation.hpp
-bcEscapeAnalyzer.hpp                    ciMethod.hpp
-bcEscapeAnalyzer.hpp                    ciMethodData.hpp
-bcEscapeAnalyzer.hpp                    dependencies.hpp
-bcEscapeAnalyzer.hpp                    growableArray.hpp
-
 biasedLocking.cpp                       biasedLocking.hpp
 biasedLocking.cpp                       klass.inline.hpp
 biasedLocking.cpp                       markOop.hpp
@@ -545,6 +531,7 @@
 
 ciCPCache.hpp                           ciClassList.hpp
 ciCPCache.hpp                           ciObject.hpp
+ciCPCache.hpp                           cpCacheOop.hpp
 
 ciEnv.cpp                               allocation.inline.hpp
 ciEnv.cpp                               ciConstant.hpp
@@ -664,7 +651,6 @@
 
 ciMethod.cpp                            abstractCompiler.hpp
 ciMethod.cpp                            allocation.inline.hpp
-ciMethod.cpp                            bcEscapeAnalyzer.hpp
 ciMethod.cpp                            bitMap.inline.hpp
 ciMethod.cpp                            ciCallProfile.hpp
 ciMethod.cpp                            ciExceptionHandler.hpp
@@ -823,6 +809,7 @@
 
 ciStreams.cpp                           ciCallSite.hpp
 ciStreams.cpp                           ciConstant.hpp
+ciStreams.cpp                           ciCPCache.hpp
 ciStreams.cpp                           ciField.hpp
 ciStreams.cpp                           ciStreams.hpp
 ciStreams.cpp                           ciUtilities.hpp
@@ -962,7 +949,6 @@
 classLoader.cpp                         timer.hpp
 classLoader.cpp                         universe.inline.hpp
 classLoader.cpp                         vmSymbols.hpp
-classLoader.cpp                         vtune.hpp
 
 classLoader.hpp                         classFileParser.hpp
 classLoader.hpp                         perfData.hpp
@@ -1002,7 +988,6 @@
 codeBlob.cpp                            safepoint.hpp
 codeBlob.cpp                            sharedRuntime.hpp
 codeBlob.cpp                            vframe.hpp
-codeBlob.cpp                            vtune.hpp
 
 codeBlob.hpp                            codeBuffer.hpp
 codeBlob.hpp                            frame.hpp
@@ -2165,7 +2150,6 @@
 interpreter.cpp                         stubRoutines.hpp
 interpreter.cpp                         templateTable.hpp
 interpreter.cpp                         timer.hpp
-interpreter.cpp                         vtune.hpp
 
 interpreter.hpp                         cppInterpreter.hpp
 interpreter.hpp                         stubs.hpp
@@ -2321,7 +2305,6 @@
 java.cpp                                vmError.hpp
 java.cpp                                vm_operations.hpp
 java.cpp                                vm_version_<arch>.hpp
-java.cpp                                vtune.hpp
 
 java.hpp                                os.hpp
 
@@ -3048,7 +3031,6 @@
 nmethod.cpp                             scopeDesc.hpp
 nmethod.cpp                             sharedRuntime.hpp
 nmethod.cpp                             sweeper.hpp
-nmethod.cpp                             vtune.hpp
 nmethod.cpp                             xmlstream.hpp
 
 nmethod.hpp                             codeBlob.hpp
@@ -3771,7 +3753,6 @@
 sharedRuntime.cpp                       vmSymbols.hpp
 sharedRuntime.cpp                       vmreg_<arch>.inline.hpp
 sharedRuntime.cpp                       vtableStubs.hpp
-sharedRuntime.cpp                       vtune.hpp
 sharedRuntime.cpp                       xmlstream.hpp
 
 sharedRuntime.hpp                       allocation.hpp
@@ -3935,7 +3916,6 @@
 stubCodeGenerator.cpp                   forte.hpp
 stubCodeGenerator.cpp                   oop.inline.hpp
 stubCodeGenerator.cpp                   stubCodeGenerator.hpp
-stubCodeGenerator.cpp                   vtune.hpp
 
 stubCodeGenerator.hpp                   allocation.hpp
 stubCodeGenerator.hpp                   assembler.hpp
@@ -4456,7 +4436,6 @@
 universe.cpp                            universe.inline.hpp
 universe.cpp                            vmSymbols.hpp
 universe.cpp                            vm_operations.hpp
-universe.cpp                            vtune.hpp
 
 universe.hpp                            growableArray.hpp
 universe.hpp                            handles.hpp
@@ -4719,7 +4698,6 @@
 vtableStubs.cpp                         resourceArea.hpp
 vtableStubs.cpp                         sharedRuntime.hpp
 vtableStubs.cpp                         vtableStubs.hpp
-vtableStubs.cpp                         vtune.hpp
 
 vtableStubs.hpp                         allocation.hpp
 
@@ -4733,11 +4711,6 @@
 vtableStubs_<arch_model>.cpp            vmreg_<arch>.inline.hpp
 vtableStubs_<arch_model>.cpp            vtableStubs.hpp
 
-vtune.hpp                               allocation.hpp
-
-vtune_<os_family>.cpp                   interpreter.hpp
-vtune_<os_family>.cpp                   vtune.hpp
-
 watermark.hpp                           allocation.hpp
 watermark.hpp                           globalDefinitions.hpp
 
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -136,25 +136,24 @@
 // Implementation of Bytecode_invoke
 
 void Bytecode_invoke::verify() const {
-  Bytecodes::Code bc = adjusted_invoke_code();
   assert(is_valid(), "check invoke");
   assert(method()->constants()->cache() != NULL, "do not call this from verifier or rewriter");
 }
 
 
-symbolOop Bytecode_invoke::signature() const {
+symbolOop Bytecode_member_ref::signature() const {
   constantPoolOop constants = method()->constants();
   return constants->signature_ref_at(index());
 }
 
 
-symbolOop Bytecode_invoke::name() const {
+symbolOop Bytecode_member_ref::name() const {
   constantPoolOop constants = method()->constants();
   return constants->name_ref_at(index());
 }
 
 
-BasicType Bytecode_invoke::result_type(Thread *thread) const {
+BasicType Bytecode_member_ref::result_type(Thread *thread) const {
   symbolHandle sh(thread, signature());
   ResultTypeFinder rts(sh);
   rts.iterate();
@@ -167,9 +166,9 @@
   KlassHandle resolved_klass;
   constantPoolHandle constants(THREAD, _method->constants());
 
-  if (adjusted_invoke_code() == Bytecodes::_invokedynamic) {
+  if (java_code() == Bytecodes::_invokedynamic) {
     LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
-  } else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
+  } else if (java_code() != Bytecodes::_invokeinterface) {
     LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
   } else {
     LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
@@ -178,51 +177,68 @@
 }
 
 
-int Bytecode_invoke::index() const {
+int Bytecode_member_ref::index() const {
   // Note:  Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
   // at the same time it allocates per-call-site CP cache entries.
-  Bytecodes::Code stdc = Bytecodes::java_code(code());
-  Bytecode* invoke = Bytecode_at(bcp());
-  if (invoke->has_index_u4(stdc))
-    return invoke->get_index_u4(stdc);
+  Bytecodes::Code rawc = code();
+  Bytecode* invoke = bytecode();
+  if (invoke->has_index_u4(rawc))
+    return invoke->get_index_u4(rawc);
   else
-    return invoke->get_index_u2_cpcache(stdc);
+    return invoke->get_index_u2_cpcache(rawc);
 }
 
+int Bytecode_member_ref::pool_index() const {
+  int index = this->index();
+  DEBUG_ONLY({
+      if (!bytecode()->has_index_u4(code()))
+        index -= constantPoolOopDesc::CPCACHE_INDEX_TAG;
+    });
+  return _method->constants()->cache()->entry_at(index)->constant_pool_index();
+}
 
 // Implementation of Bytecode_field
 
 void Bytecode_field::verify() const {
-  Bytecodes::Code stdc = Bytecodes::java_code(code());
-  assert(stdc == Bytecodes::_putstatic || stdc == Bytecodes::_getstatic ||
-         stdc == Bytecodes::_putfield  || stdc == Bytecodes::_getfield, "check field");
-}
-
-
-bool Bytecode_field::is_static() const {
-  Bytecodes::Code stdc = Bytecodes::java_code(code());
-  return stdc == Bytecodes::_putstatic || stdc == Bytecodes::_getstatic;
+  assert(is_valid(), "check field");
 }
 
 
-int Bytecode_field::index() const {
-  Bytecode* invoke = Bytecode_at(bcp());
-  return invoke->get_index_u2_cpcache(Bytecodes::_getfield);
+// Implementation of Bytecode_loadconstant
+
+int Bytecode_loadconstant::raw_index() const {
+  Bytecode* bcp = bytecode();
+  Bytecodes::Code rawc = bcp->code();
+  assert(rawc != Bytecodes::_wide, "verifier prevents this");
+  if (Bytecodes::java_code(rawc) == Bytecodes::_ldc)
+    return bcp->get_index_u1(rawc);
+  else
+    return bcp->get_index_u2(rawc, false);
 }
 
-
-// Implementation of Bytecodes loac constant
+int Bytecode_loadconstant::pool_index() const {
+  int index = raw_index();
+  if (has_cache_index()) {
+    return _method->constants()->cache()->entry_at(index)->constant_pool_index();
+  }
+  return index;
+}
 
-int Bytecode_loadconstant::index() const {
-  Bytecodes::Code stdc = Bytecodes::java_code(code());
-  if (stdc != Bytecodes::_wide) {
-    if (Bytecodes::java_code(stdc) == Bytecodes::_ldc)
-      return get_index_u1(stdc);
-    else
-      return get_index_u2(stdc, false);
+BasicType Bytecode_loadconstant::result_type() const {
+  int index = pool_index();
+  constantTag tag = _method->constants()->tag_at(index);
+  return tag.basic_type();
+}
+
+oop Bytecode_loadconstant::resolve_constant(TRAPS) const {
+  assert(_method.not_null(), "must supply method to resolve constant");
+  int index = raw_index();
+  constantPoolOop constants = _method->constants();
+  if (has_cache_index()) {
+    return constants->resolve_cached_constant_at(index, THREAD);
+  } else {
+    return constants->resolve_constant_at(index, THREAD);
   }
-  stdc = Bytecodes::code_at(addr_at(1));
-  return get_index_u2(stdc, true);
 }
 
 //------------------------------------------------------------------------------
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -76,9 +76,13 @@
           return Bytes::get_native_u2(p);
     else  return Bytes::get_Java_u2(p);
   }
+  int get_index_u1_cpcache(Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_index_size(1, bc);
+    return *(jubyte*)addr_at(1) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
+  }
   int get_index_u2_cpcache(Bytecodes::Code bc) const {
     assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc);
-    return Bytes::get_native_u2(addr_at(1)) DEBUG_ONLY(+ constantPoolOopDesc::CPCACHE_INDEX_TAG);
+    return Bytes::get_native_u2(addr_at(1)) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
   }
   int get_index_u4(Bytecodes::Code bc) const {
     assert_same_format_as(bc); assert_index_size(4, bc);
@@ -152,7 +156,7 @@
 
 inline Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp) {
   Bytecode_lookupswitch* b = (Bytecode_lookupswitch*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -174,44 +178,56 @@
 
 inline Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp) {
   Bytecode_tableswitch* b = (Bytecode_tableswitch*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
 
-// Abstraction for invoke_{virtual, static, interface, special}
+// Common code for decoding invokes and field references.
 
-class Bytecode_invoke: public ResourceObj {
+class Bytecode_member_ref: public ResourceObj {
  protected:
   methodHandle _method;                          // method containing the bytecode
   int          _bci;                             // position of the bytecode
 
-  Bytecode_invoke(methodHandle method, int bci)  : _method(method), _bci(bci) {}
+  Bytecode_member_ref(methodHandle method, int bci)  : _method(method), _bci(bci) {}
+
+ public:
+  // Attributes
+  methodHandle method() const                    { return _method; }
+  int          bci() const                       { return _bci; }
+  address      bcp() const                       { return _method->bcp_from(bci()); }
+  Bytecode*    bytecode() const                  { return Bytecode_at(bcp()); }
+
+  int          index() const;                    // cache index (loaded from instruction)
+  int          pool_index() const;               // constant pool index
+  symbolOop    name() const;                     // returns the name of the method or field
+  symbolOop    signature() const;                // returns the signature of the method or field
+
+  BasicType    result_type(Thread* thread) const; // returns the result type of the getfield or invoke
+
+  Bytecodes::Code code() const                   { return Bytecodes::code_at(bcp(), _method()); }
+  Bytecodes::Code java_code() const              { return Bytecodes::java_code(code()); }
+};
+
+// Abstraction for invoke_{virtual, static, interface, special}
+
+class Bytecode_invoke: public Bytecode_member_ref {
+ protected:
+  Bytecode_invoke(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) {}
 
  public:
   void verify() const;
 
   // Attributes
-  methodHandle method() const                    { return _method; }
-  int          bci() const                       { return _bci; }
-  address      bcp() const                       { return _method->bcp_from(bci()); }
-
-  int          index() const;                    // the constant pool index for the invoke
-  symbolOop    name() const;                     // returns the name of the invoked method
-  symbolOop    signature() const;                // returns the signature of the invoked method
-  BasicType    result_type(Thread *thread) const; // returns the result type of the invoke
-
-  Bytecodes::Code code() const                   { return Bytecodes::code_at(bcp(), _method()); }
-  Bytecodes::Code adjusted_invoke_code() const   { return Bytecodes::java_code(code()); }
-
   methodHandle static_target(TRAPS);             // "specified" method   (from constant pool)
 
   // Testers
-  bool is_invokeinterface() const                { return adjusted_invoke_code() == Bytecodes::_invokeinterface; }
-  bool is_invokevirtual() const                  { return adjusted_invoke_code() == Bytecodes::_invokevirtual; }
-  bool is_invokestatic() const                   { return adjusted_invoke_code() == Bytecodes::_invokestatic; }
-  bool is_invokespecial() const                  { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
-  bool is_invokedynamic() const                  { return adjusted_invoke_code() == Bytecodes::_invokedynamic; }
+  bool is_invokeinterface() const                { return java_code() == Bytecodes::_invokeinterface; }
+  bool is_invokevirtual() const                  { return java_code() == Bytecodes::_invokevirtual; }
+  bool is_invokestatic() const                   { return java_code() == Bytecodes::_invokestatic; }
+  bool is_invokespecial() const                  { return java_code() == Bytecodes::_invokespecial; }
+  bool is_invokedynamic() const                  { return java_code() == Bytecodes::_invokedynamic; }
 
   bool has_receiver() const                      { return !is_invokestatic() && !is_invokedynamic(); }
 
@@ -230,7 +246,7 @@
 
 inline Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci) {
   Bytecode_invoke* b = new Bytecode_invoke(method, bci);
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -240,21 +256,34 @@
 }
 
 
-// Abstraction for all field accesses (put/get field/static_
-class Bytecode_field: public Bytecode {
-public:
+// Abstraction for all field accesses (put/get field/static)
+class Bytecode_field: public Bytecode_member_ref {
+ protected:
+  Bytecode_field(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) {}
+
+ public:
+  // Testers
+  bool is_getfield() const                       { return java_code() == Bytecodes::_getfield; }
+  bool is_putfield() const                       { return java_code() == Bytecodes::_putfield; }
+  bool is_getstatic() const                      { return java_code() == Bytecodes::_getstatic; }
+  bool is_putstatic() const                      { return java_code() == Bytecodes::_putstatic; }
+
+  bool is_getter() const                         { return is_getfield()  || is_getstatic(); }
+  bool is_static() const                         { return is_getstatic() || is_putstatic(); }
+
+  bool is_valid() const                          { return is_getfield()   ||
+                                                          is_putfield()   ||
+                                                          is_getstatic()  ||
+                                                          is_putstatic(); }
   void verify() const;
 
-  int  index() const;
-  bool is_static() const;
-
   // Creation
-  inline friend Bytecode_field* Bytecode_field_at(const methodOop method, address bcp);
+  inline friend Bytecode_field* Bytecode_field_at(methodHandle method, int bci);
 };
 
-inline Bytecode_field* Bytecode_field_at(const methodOop method, address bcp) {
-  Bytecode_field* b = (Bytecode_field*)bcp;
-  debug_only(b->verify());
+inline Bytecode_field* Bytecode_field_at(methodHandle method, int bci) {
+  Bytecode_field* b = new Bytecode_field(method, bci);
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -274,7 +303,7 @@
 
 inline Bytecode_checkcast* Bytecode_checkcast_at(address bcp) {
   Bytecode_checkcast* b = (Bytecode_checkcast*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -294,7 +323,7 @@
 
 inline Bytecode_instanceof* Bytecode_instanceof_at(address bcp) {
   Bytecode_instanceof* b = (Bytecode_instanceof*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -312,7 +341,7 @@
 
 inline Bytecode_new* Bytecode_new_at(address bcp) {
   Bytecode_new* b = (Bytecode_new*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -330,7 +359,7 @@
 
 inline Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp) {
   Bytecode_multianewarray* b = (Bytecode_multianewarray*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
@@ -348,29 +377,57 @@
 
 inline Bytecode_anewarray* Bytecode_anewarray_at(address bcp) {
   Bytecode_anewarray* b = (Bytecode_anewarray*)bcp;
-  debug_only(b->verify());
+  DEBUG_ONLY(b->verify());
   return b;
 }
 
 
 // Abstraction for ldc, ldc_w and ldc2_w
 
-class Bytecode_loadconstant: public Bytecode {
+class Bytecode_loadconstant: public ResourceObj {
+ private:
+  int          _bci;
+  methodHandle _method;
+
+  Bytecodes::Code code() const                   { return bytecode()->code(); }
+
+  int raw_index() const;
+
+  Bytecode_loadconstant(methodHandle method, int bci) : _method(method), _bci(bci) {}
+
  public:
+  // Attributes
+  methodHandle method() const                    { return _method; }
+  int          bci() const                       { return _bci; }
+  address      bcp() const                       { return _method->bcp_from(bci()); }
+  Bytecode*    bytecode() const                  { return Bytecode_at(bcp()); }
+
   void verify() const {
+    assert(_method.not_null(), "must supply method");
     Bytecodes::Code stdc = Bytecodes::java_code(code());
     assert(stdc == Bytecodes::_ldc ||
            stdc == Bytecodes::_ldc_w ||
            stdc == Bytecodes::_ldc2_w, "load constant");
   }
 
-  int index() const;
+  // Only non-standard bytecodes (fast_aldc) have CP cache indexes.
+  bool has_cache_index() const { return code() >= Bytecodes::number_of_java_codes; }
 
-  inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(const methodOop method, address bcp);
+  int pool_index() const;               // index into constant pool
+  int cache_index() const {             // index into CP cache (or -1 if none)
+    return has_cache_index() ? raw_index() : -1;
+  }
+
+  BasicType result_type() const;        // returns the result type of the ldc
+
+  oop resolve_constant(TRAPS) const;
+
+  // Creation
+  inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci);
 };
 
-inline Bytecode_loadconstant* Bytecode_loadconstant_at(const methodOop method, address bcp) {
-  Bytecode_loadconstant* b = (Bytecode_loadconstant*)bcp;
-  debug_only(b->verify());
+inline Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci) {
+  Bytecode_loadconstant* b = new Bytecode_loadconstant(method, bci);
+  DEBUG_ONLY(b->verify());
   return b;
 }
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -49,6 +49,7 @@
 
   int       get_index_u1()           { return *(address)_next_pc++; }
   int       get_index_u2()           { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
+  int       get_index_u1_cpcache()   { return get_index_u1() + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
   int       get_index_u2_cpcache()   { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
   int       get_index_u4()           { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
   int       get_index_special()      { return (is_wide()) ? get_index_u2() : get_index_u1(); }
@@ -60,6 +61,7 @@
   bool      check_index(int i, int& cp_index, outputStream* st = tty);
   void      print_constant(int i, outputStream* st = tty);
   void      print_field_or_method(int i, outputStream* st = tty);
+  void      print_field_or_method(int orig_i, int i, outputStream* st = tty);
   void      print_attributes(int bci, outputStream* st = tty);
   void      bytecode_epilog(int bci, outputStream* st = tty);
 
@@ -177,18 +179,29 @@
   _closure->trace(method, bcp, st);
 }
 
+void print_symbol(symbolOop sym, outputStream* st) {
+  char buf[40];
+  int len = sym->utf8_length();
+  if (len >= (int)sizeof(buf)) {
+    st->print_cr(" %s...[%d]", sym->as_C_string(buf, sizeof(buf)), len);
+  } else {
+    st->print(" ");
+    sym->print_on(st); st->cr();
+  }
+}
+
 void print_oop(oop value, outputStream* st) {
   if (value == NULL) {
     st->print_cr(" NULL");
-  } else {
+  } else if (java_lang_String::is_instance(value)) {
     EXCEPTION_MARK;
     Handle h_value (THREAD, value);
     symbolHandle sym = java_lang_String::as_symbol(h_value, CATCH);
-    if (sym->utf8_length() > 32) {
-      st->print_cr(" ....");
-    } else {
-      sym->print_on(st); st->cr();
-    }
+    print_symbol(sym(), st);
+  } else if (value->is_symbol()) {
+    print_symbol(symbolOop(value), st);
+  } else {
+    st->print_cr(" " PTR_FORMAT, (intptr_t) value);
   }
 }
 
@@ -279,16 +292,27 @@
   } else if (tag.is_double()) {
     st->print_cr(" %f", constants->double_at(i));
   } else if (tag.is_string()) {
-    oop string = constants->resolved_string_at(i);
+    oop string = constants->pseudo_string_at(i);
     print_oop(string, st);
   } else if (tag.is_unresolved_string()) {
-    st->print_cr(" <unresolved string at %d>", i);
+    const char* string = constants->string_at_noresolve(i);
+    st->print_cr(" %s", string);
   } else if (tag.is_klass()) {
     st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
   } else if (tag.is_unresolved_klass()) {
     st->print_cr(" <unresolved klass at %d>", i);
   } else if (tag.is_object()) {
-    st->print_cr(" " PTR_FORMAT, constants->object_at(i));
+    st->print(" <Object>");
+    print_oop(constants->object_at(i), st);
+  } else if (tag.is_method_type()) {
+    int i2 = constants->method_type_index_at(i);
+    st->print(" <MethodType> %d", i2);
+    print_oop(constants->symbol_at(i2), st);
+  } else if (tag.is_method_handle()) {
+    int kind = constants->method_handle_ref_kind_at(i);
+    int i2 = constants->method_handle_index_at(i);
+    st->print(" <MethodHandle of kind %d>", kind, i2);
+    print_field_or_method(-i, i2, st);
   } else {
     st->print_cr(" bad tag=%d at %d", tag.value(), i);
   }
@@ -297,7 +321,10 @@
 void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
   int orig_i = i;
   if (!check_index(orig_i, i, st))  return;
+  print_field_or_method(orig_i, i, st);
+}
 
+void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) {
   constantPoolOop constants = method()->constants();
   constantTag tag = constants->tag_at(i);
 
@@ -314,9 +341,11 @@
     return;
   }
 
+  symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
   symbolOop name = constants->uncached_name_ref_at(i);
   symbolOop signature = constants->uncached_signature_ref_at(i);
-  st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
+  const char* sep = (tag.is_field() ? "/" : "");
+  st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string());
 }
 
 
@@ -340,12 +369,20 @@
       st->print_cr(" " INT32_FORMAT, get_short());
       break;
     case Bytecodes::_ldc:
-      print_constant(get_index_u1(), st);
+      if (Bytecodes::uses_cp_cache(raw_code())) {
+        print_constant(get_index_u1_cpcache(), st);
+      } else {
+        print_constant(get_index_u1(), st);
+      }
       break;
 
     case Bytecodes::_ldc_w:
     case Bytecodes::_ldc2_w:
-      print_constant(get_index_u2(), st);
+      if (Bytecodes::uses_cp_cache(raw_code())) {
+        print_constant(get_index_u2_cpcache(), st);
+      } else {
+        print_constant(get_index_u2(), st);
+      }
       break;
 
     case Bytecodes::_iload:
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -489,6 +489,9 @@
 
   def(_return_register_finalizer , "return_register_finalizer" , "b"    , NULL    , T_VOID   ,  0, true, _return);
 
+  def(_fast_aldc           , "fast_aldc"           , "bj"   , NULL    , T_OBJECT,   1, true,  _ldc   );
+  def(_fast_aldc_w         , "fast_aldc_w"         , "bJJ"  , NULL    , T_OBJECT,   1, true,  _ldc_w );
+
   def(_shouldnotreachhere  , "_shouldnotreachhere" , "b"    , NULL    , T_VOID   ,  0, false);
 
   // platform specific JVM bytecodes
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -270,6 +270,10 @@
     _fast_linearswitch    ,
     _fast_binaryswitch    ,
 
+    // special handling of oop constants:
+    _fast_aldc            ,
+    _fast_aldc_w          ,
+
     _return_register_finalizer    ,
 
     _shouldnotreachhere,      // For debugging
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -99,11 +99,6 @@
 #endif // PRODUCT
   // need to hit every safepoint in order to call zapping routine
   // register the interpreter
-  VTune::register_stub(
-    "Interpreter",
-    AbstractInterpreter::code()->code_start(),
-    AbstractInterpreter::code()->code_end()
-  );
   Forte::register_stub(
     "Interpreter",
     AbstractInterpreter::code()->code_start(),
@@ -267,20 +262,6 @@
 }
 #endif // PRODUCT
 
-static BasicType constant_pool_type(methodOop method, int index) {
-  constantTag tag = method->constants()->tag_at(index);
-       if (tag.is_int              ()) return T_INT;
-  else if (tag.is_float            ()) return T_FLOAT;
-  else if (tag.is_long             ()) return T_LONG;
-  else if (tag.is_double           ()) return T_DOUBLE;
-  else if (tag.is_string           ()) return T_OBJECT;
-  else if (tag.is_unresolved_string()) return T_OBJECT;
-  else if (tag.is_klass            ()) return T_OBJECT;
-  else if (tag.is_unresolved_klass ()) return T_OBJECT;
-  ShouldNotReachHere();
-  return T_ILLEGAL;
-}
-
 
 //------------------------------------------------------------------------------------------------------------------------
 // Deoptimization support
@@ -330,13 +311,15 @@
     }
 
     case Bytecodes::_ldc   :
-      type = constant_pool_type( method, *(bcp+1) );
-      break;
-
     case Bytecodes::_ldc_w : // fall through
     case Bytecodes::_ldc2_w:
-      type = constant_pool_type( method, Bytes::get_Java_u2(bcp+1) );
-      break;
+      {
+        Thread *thread = Thread::current();
+        ResourceMark rm(thread);
+        methodHandle mh(thread, method);
+        type = Bytecode_loadconstant_at(mh, bci)->result_type();
+        break;
+      }
 
     default:
       type = Bytecodes::result_type(code);
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -83,6 +83,18 @@
   }
 IRT_END
 
+IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::Code bytecode)) {
+  assert(bytecode == Bytecodes::_fast_aldc ||
+         bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
+  ResourceMark rm(thread);
+  methodHandle m (thread, method(thread));
+  Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(m, bci(thread));
+  oop result = ldc->resolve_constant(THREAD);
+  DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc->cache_index()));
+  assert(result == cpce->f1(), "expected result for assembly code");
+}
+IRT_END
+
 
 //------------------------------------------------------------------------------------------------------------------------
 // Allocation
@@ -328,7 +340,7 @@
   typeArrayHandle    h_extable  (thread, h_method->exception_table());
   bool               should_repeat;
   int                handler_bci;
-  int                current_bci = bcp(thread) - h_method->code_base();
+  int                current_bci = bci(thread);
 
   // Need to do this check first since when _do_not_unlock_if_synchronized
   // is set, we don't want to trigger any classloading which may make calls
@@ -615,8 +627,7 @@
   if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
     ResourceMark rm(thread);
     methodHandle m (thread, method(thread));
-    int bci = m->bci_from(bcp(thread));
-    Bytecode_invoke* call = Bytecode_invoke_at(m, bci);
+    Bytecode_invoke* call = Bytecode_invoke_at(m, bci(thread));
     symbolHandle signature (thread, call->signature());
     receiver = Handle(thread,
                   thread->last_frame().interpreter_callee_receiver(signature));
@@ -1257,7 +1268,7 @@
   Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
   ArgumentSizeComputer asc(invoke->signature());
   int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
-  Copy::conjoint_bytes(src_address, dest_address,
+  Copy::conjoint_jbytes(src_address, dest_address,
                        size_of_arguments * Interpreter::stackElementSize);
 IRT_END
 #endif
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -34,6 +34,7 @@
   static frame     last_frame(JavaThread *thread)    { return thread->last_frame(); }
   static methodOop method(JavaThread *thread)        { return last_frame(thread).interpreter_frame_method(); }
   static address   bcp(JavaThread *thread)           { return last_frame(thread).interpreter_frame_bcp(); }
+  static int       bci(JavaThread *thread)           { return last_frame(thread).interpreter_frame_bci(); }
   static void      set_bcp_and_mdp(address bcp, JavaThread*thread);
   static Bytecodes::Code code(JavaThread *thread)    {
     // pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
@@ -59,6 +60,7 @@
  public:
   // Constants
   static void    ldc           (JavaThread* thread, bool wide);
+  static void    resolve_ldc   (JavaThread* thread, Bytecodes::Code bytecode);
 
   // Allocation
   static void    _new          (JavaThread* thread, constantPoolOopDesc* pool, int index);
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -38,6 +38,8 @@
       case JVM_CONSTANT_InterfaceMethodref:
       case JVM_CONSTANT_Fieldref          : // fall through
       case JVM_CONSTANT_Methodref         : // fall through
+      case JVM_CONSTANT_MethodHandle      : // fall through
+      case JVM_CONSTANT_MethodType        : // fall through
         add_cp_cache_entry(i);
         break;
     }
@@ -131,6 +133,27 @@
 }
 
 
+// Rewrite some ldc bytecodes to _fast_aldc
+void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide) {
+  assert((*bcp) == (is_wide ? Bytecodes::_ldc_w : Bytecodes::_ldc), "");
+  address p = bcp + offset;
+  int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
+  constantTag tag = _pool->tag_at(cp_index).value();
+  if (tag.is_method_handle() || tag.is_method_type()) {
+    int cache_index = cp_entry_to_cp_cache(cp_index);
+    if (is_wide) {
+      (*bcp) = Bytecodes::_fast_aldc_w;
+      assert(cache_index == (u2)cache_index, "");
+      Bytes::put_native_u2(p, cache_index);
+    } else {
+      (*bcp) = Bytecodes::_fast_aldc;
+      assert(cache_index == (u1)cache_index, "");
+      (*p) = (u1)cache_index;
+    }
+  }
+}
+
+
 // Rewrites a method given the index_map information
 void Rewriter::scan_method(methodOop method) {
 
@@ -198,6 +221,12 @@
         case Bytecodes::_invokedynamic:
           rewrite_invokedynamic(bcp, prefix_length+1);
           break;
+        case Bytecodes::_ldc:
+          maybe_rewrite_ldc(bcp, prefix_length+1, false);
+          break;
+        case Bytecodes::_ldc_w:
+          maybe_rewrite_ldc(bcp, prefix_length+1, true);
+          break;
         case Bytecodes::_jsr            : // fall through
         case Bytecodes::_jsr_w          : nof_jsrs++;                   break;
         case Bytecodes::_monitorenter   : // fall through
--- a/hotspot/src/share/vm/interpreter/rewriter.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -66,6 +66,7 @@
   void rewrite_Object_init(methodHandle m, TRAPS);
   void rewrite_member_reference(address bcp, int offset);
   void rewrite_invokedynamic(address bcp, int offset);
+  void maybe_rewrite_ldc(address bcp, int offset, bool is_wide);
 
  public:
   // Driver routine:
--- a/hotspot/src/share/vm/interpreter/templateTable.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -507,6 +507,9 @@
   def(Bytecodes::_fast_linearswitch   , ubcp|disp|____|____, itos, vtos, fast_linearswitch   ,  _           );
   def(Bytecodes::_fast_binaryswitch   , ubcp|disp|____|____, itos, vtos, fast_binaryswitch   ,  _           );
 
+  def(Bytecodes::_fast_aldc           , ubcp|____|clvm|____, vtos, atos, fast_aldc           ,  false       );
+  def(Bytecodes::_fast_aldc_w         , ubcp|____|clvm|____, vtos, atos, fast_aldc           ,  true        );
+
   def(Bytecodes::_return_register_finalizer , ____|disp|clvm|____, vtos, vtos, _return       ,  vtos        );
 
   def(Bytecodes::_shouldnotreachhere   , ____|____|____|____, vtos, vtos, shouldnotreachhere ,  _           );
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -123,6 +123,7 @@
   static void sipush();
   static void ldc(bool wide);
   static void ldc2_w();
+  static void fast_aldc(bool wide);
 
   static void locals_index(Register reg, int offset = 1);
   static void iload();
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -284,12 +284,19 @@
         committed_unique_to_self(ind, MemRegion(new_end_aligned,
                                                 cur_committed.end()));
       if (!uncommit_region.is_empty()) {
-        if (!os::uncommit_memory((char*)uncommit_region.start(),
-                                 uncommit_region.byte_size())) {
-          assert(false, "Card table contraction failed");
-          // The call failed so don't change the end of the
-          // committed region.  This is better than taking the
-          // VM down.
+        // It is not safe to uncommit cards if the boundary between
+        // the generations is moving.  A shrink can uncommit cards
+        // owned by generation A but being used by generation B.
+        if (!UseAdaptiveGCBoundary) {
+          if (!os::uncommit_memory((char*)uncommit_region.start(),
+                                   uncommit_region.byte_size())) {
+            assert(false, "Card table contraction failed");
+            // The call failed so don't change the end of the
+            // committed region.  This is better than taking the
+            // VM down.
+            new_end_aligned = _committed[ind].end();
+          }
+        } else {
           new_end_aligned = _committed[ind].end();
         }
       }
@@ -297,6 +304,19 @@
     // In any case, we can reset the end of the current committed entry.
     _committed[ind].set_end(new_end_aligned);
 
+#ifdef ASSERT
+    // Check that the last card in the new region is committed according
+    // to the tables.
+    bool covered = false;
+    for (int cr = 0; cr < _cur_covered_regions; cr++) {
+      if (_committed[cr].contains(new_end - 1)) {
+        covered = true;
+        break;
+      }
+    }
+    assert(covered, "Card for end of new region not committed");
+#endif
+
     // The default of 0 is not necessarily clean cards.
     jbyte* entry;
     if (old_region.last() < _whole_heap.start()) {
@@ -354,6 +374,9 @@
                   addr_for((jbyte*) _committed[ind].start()),
                   addr_for((jbyte*) _committed[ind].last()));
   }
+  // Touch the last card of the covered region to show that it
+  // is committed (or SEGV).
+  debug_only(*byte_for(_covered[ind].last());)
   debug_only(verify_guard();)
 }
 
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -179,9 +179,14 @@
     }
     n_covered_regions += _gen_specs[i]->n_covered_regions();
   }
-  assert(total_reserved % pageSize == 0, "Gen size");
+  assert(total_reserved % pageSize == 0,
+         err_msg("Gen size; total_reserved=" SIZE_FORMAT ", pageSize="
+                 SIZE_FORMAT, total_reserved, pageSize));
   total_reserved += perm_gen_spec->max_size();
-  assert(total_reserved % pageSize == 0, "Perm Gen size");
+  assert(total_reserved % pageSize == 0,
+         err_msg("Perm size; total_reserved=" SIZE_FORMAT ", pageSize="
+                 SIZE_FORMAT ", perm gen max=" SIZE_FORMAT, total_reserved,
+                 pageSize, perm_gen_spec->max_size()));
 
   if (total_reserved < perm_gen_spec->max_size()) {
     vm_exit_during_initialization(overflow_msg);
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -372,6 +372,13 @@
         entry->print_value_on(st);
         }
         break;
+      case JVM_CONSTANT_MethodHandle :
+        st->print("ref_kind=%d", cp->method_handle_ref_kind_at(index));
+        st->print(" ref_index=%d", cp->method_handle_index_at(index));
+        break;
+      case JVM_CONSTANT_MethodType :
+        st->print("signature_index=%d", cp->method_type_index_at(index));
+        break;
       default:
         ShouldNotReachHere();
         break;
@@ -437,6 +444,7 @@
           // can be non-perm, can be non-instance (array)
         }
       }
+      // FIXME: verify JSR 292 tags JVM_CONSTANT_MethodHandle, etc.
       base++;
     }
     guarantee(cp->tags()->is_perm(),         "should be in permspace");
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -358,6 +358,11 @@
   return klass_at_noresolve(ref_index);
 }
 
+symbolOop constantPoolOopDesc::uncached_klass_ref_at_noresolve(int which) {
+  jint ref_index = uncached_klass_ref_index_at(which);
+  return klass_at_noresolve(ref_index);
+}
+
 char* constantPoolOopDesc::string_at_noresolve(int which) {
   // Test entry type in case string is resolved while in here.
   oop entry = *(obj_at_addr(which));
@@ -384,6 +389,119 @@
   }
 }
 
+oop constantPoolOopDesc::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
+  oop result_oop = NULL;
+  if (cache_index >= 0) {
+    assert(index < 0, "only one kind of index at a time");
+    ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
+    result_oop = cpc_entry->f1();
+    if (result_oop != NULL) {
+      return result_oop;  // that was easy...
+    }
+    index = cpc_entry->constant_pool_index();
+  }
+
+  int tag_value = this_oop->tag_at(index).value();
+  switch (tag_value) {
+
+  case JVM_CONSTANT_UnresolvedClass:
+  case JVM_CONSTANT_UnresolvedClassInError:
+  case JVM_CONSTANT_Class:
+    {
+      klassOop resolved = klass_at_impl(this_oop, index, CHECK_NULL);
+      // ldc wants the java mirror.
+      result_oop = resolved->klass_part()->java_mirror();
+      break;
+    }
+
+  case JVM_CONSTANT_String:
+  case JVM_CONSTANT_UnresolvedString:
+    if (this_oop->is_pseudo_string_at(index)) {
+      result_oop = this_oop->pseudo_string_at(index);
+      break;
+    }
+    result_oop = string_at_impl(this_oop, index, CHECK_NULL);
+    break;
+
+  case JVM_CONSTANT_Object:
+    result_oop = this_oop->object_at(index);
+    break;
+
+  case JVM_CONSTANT_MethodHandle:
+    {
+      int ref_kind                 = this_oop->method_handle_ref_kind_at(index);
+      int callee_index             = this_oop->method_handle_klass_index_at(index);
+      symbolHandle name(THREAD,      this_oop->method_handle_name_ref_at(index));
+      symbolHandle signature(THREAD, this_oop->method_handle_signature_ref_at(index));
+      if (PrintMiscellaneous)
+        tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
+                      ref_kind, index, this_oop->method_handle_index_at(index),
+                      callee_index, name->as_C_string(), signature->as_C_string());
+      KlassHandle callee;
+      { klassOop k = klass_at_impl(this_oop, callee_index, CHECK_NULL);
+        callee = KlassHandle(THREAD, k);
+      }
+      KlassHandle klass(THREAD, this_oop->pool_holder());
+      Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
+                                                                   callee, name, signature,
+                                                                   CHECK_NULL);
+      result_oop = value();
+      // FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
+      break;
+    }
+
+  case JVM_CONSTANT_MethodType:
+    {
+      symbolHandle signature(THREAD, this_oop->method_type_signature_at(index));
+      if (PrintMiscellaneous)
+        tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
+                      index, this_oop->method_type_index_at(index),
+                      signature->as_C_string());
+      KlassHandle klass(THREAD, this_oop->pool_holder());
+      bool ignore_is_on_bcp = false;
+      Handle value = SystemDictionary::find_method_handle_type(signature,
+                                                               klass,
+                                                               ignore_is_on_bcp,
+                                                               CHECK_NULL);
+      result_oop = value();
+      // FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
+      break;
+    }
+
+    /* maybe some day
+  case JVM_CONSTANT_Integer:
+  case JVM_CONSTANT_Float:
+  case JVM_CONSTANT_Long:
+  case JVM_CONSTANT_Double:
+    result_oop = java_lang_boxing_object::create(...);
+    break;
+    */
+
+  default:
+    DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
+                              this_oop(), index, cache_index, tag_value) );
+    assert(false, "unexpected constant tag");
+    break;
+  }
+
+  if (cache_index >= 0) {
+    // Cache the oop here also.
+    Handle result(THREAD, result_oop);
+    result_oop = NULL;  // safety
+    ObjectLocker ol(this_oop, THREAD);
+    ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
+    oop result_oop2 = cpc_entry->f1();
+    if (result_oop2 != NULL) {
+      // Race condition:  May already be filled in while we were trying to lock.
+      return result_oop2;
+    }
+    cpc_entry->set_f1(result());
+    return result();
+  } else {
+    return result_oop;
+  }
+}
+
 oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
   oop entry = *(this_oop->obj_at_addr(which));
   if (entry->is_symbol()) {
@@ -690,6 +808,28 @@
     }
   } break;
 
+  case JVM_CONSTANT_MethodType:
+  {
+    int k1 = method_type_index_at(index1);
+    int k2 = cp2->method_type_index_at(index2);
+    if (k1 == k2) {
+      return true;
+    }
+  } break;
+
+  case JVM_CONSTANT_MethodHandle:
+  {
+    int k1 = method_handle_ref_kind_at(index1);
+    int k2 = cp2->method_handle_ref_kind_at(index2);
+    if (k1 == k2) {
+      int i1 = method_handle_index_at(index1);
+      int i2 = cp2->method_handle_index_at(index2);
+      if (i1 == i2) {
+        return true;
+      }
+    }
+  } break;
+
   case JVM_CONSTANT_UnresolvedString:
   {
     symbolOop s1 = unresolved_string_at(index1);
@@ -863,6 +1003,19 @@
     to_cp->symbol_at_put(to_i, s);
   } break;
 
+  case JVM_CONSTANT_MethodType:
+  {
+    jint k = method_type_index_at(from_i);
+    to_cp->method_type_index_at_put(to_i, k);
+  } break;
+
+  case JVM_CONSTANT_MethodHandle:
+  {
+    int k1 = method_handle_ref_kind_at(from_i);
+    int k2 = method_handle_index_at(from_i);
+    to_cp->method_handle_index_at_put(to_i, k1, k2);
+  } break;
+
   // Invalid is used as the tag for the second constant pool entry
   // occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
   // not be seen by itself.
@@ -1066,8 +1219,12 @@
     case JVM_CONSTANT_UnresolvedClassInError:
     case JVM_CONSTANT_StringIndex:
     case JVM_CONSTANT_UnresolvedString:
+    case JVM_CONSTANT_MethodType:
       return 3;
 
+    case JVM_CONSTANT_MethodHandle:
+      return 4; //tag, ref_kind, ref_index
+
     case JVM_CONSTANT_Integer:
     case JVM_CONSTANT_Float:
     case JVM_CONSTANT_Fieldref:
@@ -1271,6 +1428,22 @@
         DBG(printf("JVM_CONSTANT_StringIndex: %hd", idx1));
         break;
       }
+      case JVM_CONSTANT_MethodHandle: {
+        *bytes = JVM_CONSTANT_MethodHandle;
+        int kind = method_handle_ref_kind_at(idx);
+        idx1 = method_handle_index_at(idx);
+        *(bytes+1) = (unsigned char) kind;
+        Bytes::put_Java_u2((address) (bytes+2), idx1);
+        DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1));
+        break;
+      }
+      case JVM_CONSTANT_MethodType: {
+        *bytes = JVM_CONSTANT_MethodType;
+        idx1 = method_type_index_at(idx);
+        Bytes::put_Java_u2((address) (bytes+1), idx1);
+        DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
+        break;
+      }
     }
     DBG(printf("\n"));
     bytes += ent_size;
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -146,6 +146,16 @@
     oop_store_without_check(obj_at_addr(which), oop(s));
   }
 
+  void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
+    tag_at_put(which, JVM_CONSTANT_MethodHandle);
+    *int_at_addr(which) = ((jint) ref_index<<16) | ref_kind;
+  }
+
+  void method_type_index_at_put(int which, int ref_index) {
+    tag_at_put(which, JVM_CONSTANT_MethodType);
+    *int_at_addr(which) = ref_index;
+  }
+
   // Temporary until actual use
   void unresolved_string_at_put(int which, symbolOop s) {
     *obj_at_addr(which) = NULL;
@@ -357,6 +367,36 @@
     return *int_at_addr(which);
   }
 
+  int method_handle_ref_kind_at(int which) {
+    assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
+    return extract_low_short_from_int(*int_at_addr(which));  // mask out unwanted ref_index bits
+  }
+  int method_handle_index_at(int which) {
+    assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
+    return extract_high_short_from_int(*int_at_addr(which));  // shift out unwanted ref_kind bits
+  }
+  int method_type_index_at(int which) {
+    assert(tag_at(which).is_method_type(), "Corrupted constant pool");
+    return *int_at_addr(which);
+  }
+  // Derived queries:
+  symbolOop method_handle_name_ref_at(int which) {
+    int member = method_handle_index_at(which);
+    return impl_name_ref_at(member, true);
+  }
+  symbolOop method_handle_signature_ref_at(int which) {
+    int member = method_handle_index_at(which);
+    return impl_signature_ref_at(member, true);
+  }
+  int method_handle_klass_index_at(int which) {
+    int member = method_handle_index_at(which);
+    return impl_klass_ref_index_at(member, true);
+  }
+  symbolOop method_type_signature_at(int which) {
+    int sym = method_type_index_at(which);
+    return symbol_at(sym);
+  }
+
   // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
   // name_and_type_ref_index_at) all expect to be passed indices obtained
   // directly from the bytecode, and extracted according to java byte order.
@@ -388,6 +428,17 @@
     resolve_string_constants_impl(h_this, CHECK);
   }
 
+  // Resolve late bound constants.
+  oop resolve_constant_at(int index, TRAPS) {
+    constantPoolHandle h_this(THREAD, this);
+    return resolve_constant_at_impl(h_this, index, -1, THREAD);
+  }
+
+  oop resolve_cached_constant_at(int cache_index, TRAPS) {
+    constantPoolHandle h_this(THREAD, this);
+    return resolve_constant_at_impl(h_this, -1, cache_index, THREAD);
+  }
+
   // Klass name matches name at offset
   bool klass_name_at_matches(instanceKlassHandle k, int which);
 
@@ -420,6 +471,7 @@
   // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
   // future by other Java code. These take constant pool indices rather than possibly-byte-swapped
   // constant pool cache indices as do the peer methods above.
+  symbolOop uncached_klass_ref_at_noresolve(int which);
   symbolOop uncached_name_ref_at(int which)                 { return impl_name_ref_at(which, true); }
   symbolOop uncached_signature_ref_at(int which)            { return impl_signature_ref_at(which, true); }
   int       uncached_klass_ref_index_at(int which)          { return impl_klass_ref_index_at(which, true); }
@@ -436,6 +488,8 @@
 
 #ifdef ASSERT
   enum { CPCACHE_INDEX_TAG = 0x10000 };  // helps keep CP cache indices distinct from CP indices
+#else
+  enum { CPCACHE_INDEX_TAG = 0 };        // in product mode, this zero value is a no-op
 #endif //ASSERT
 
  private:
@@ -469,6 +523,8 @@
   // Resolve string constants (to prevent allocation during compilation)
   static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
 
+  static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
+
  public:
   // Merging constantPoolOop support:
   bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -110,6 +110,7 @@
 class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
   friend class VMStructs;
   friend class constantPoolCacheKlass;
+  friend class constantPoolOopDesc;  //resolve_constant_at_impl => set_f1
 
  private:
   volatile intx     _indices;  // constant pool index & rewrite bytecodes
--- a/hotspot/src/share/vm/opto/callnode.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1524,7 +1524,7 @@
     ConnectionGraph *cgr = phase->C->congraph();
     PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
     if (cgr != NULL)
-      es = cgr->escape_state(obj_node(), phase);
+      es = cgr->escape_state(obj_node());
     if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
       // Mark it eliminated to update any counters
       this->set_eliminated();
@@ -1627,7 +1627,7 @@
     ConnectionGraph *cgr = phase->C->congraph();
     PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
     if (cgr != NULL)
-      es = cgr->escape_state(obj_node(), phase);
+      es = cgr->escape_state(obj_node());
     if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
       // Mark it eliminated to update any counters
       this->set_eliminated();
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -472,9 +472,7 @@
             assert( n->req() == 2 &&  n->in(1) != NULL, "Only one data input expected" );
             // Break dead loop data path.
             // Eagerly replace phis with top to avoid phis copies generation.
-            igvn->add_users_to_worklist(n);
-            igvn->hash_delete(n); // Yank from hash before hacking edges
-            igvn->subsume_node(n, top);
+            igvn->replace_node(n, top);
             if( max != outcnt() ) {
               progress = true;
               j = refresh_out_pos(j);
@@ -518,18 +516,17 @@
         igvn->hash_delete(n); // Remove from worklist before modifying edges
         if( n->is_Phi() ) {   // Collapse all Phis
           // Eagerly replace phis to avoid copies generation.
-          igvn->add_users_to_worklist(n);
-          igvn->hash_delete(n); // Yank from hash before hacking edges
+          Node* in;
           if( cnt == 0 ) {
             assert( n->req() == 1, "No data inputs expected" );
-            igvn->subsume_node(n, parent_ctrl); // replaced by top
+            in = parent_ctrl; // replaced by top
           } else {
             assert( n->req() == 2 &&  n->in(1) != NULL, "Only one data input expected" );
-            Node* in1 = n->in(1);               // replaced by unique input
-            if( n->as_Phi()->is_unsafe_data_reference(in1) )
-              in1 = phase->C->top();            // replaced by top
-            igvn->subsume_node(n, in1);
+            in = n->in(1);               // replaced by unique input
+            if( n->as_Phi()->is_unsafe_data_reference(in) )
+              in = phase->C->top();      // replaced by top
           }
+          igvn->replace_node(n, in);
         }
         else if( n->is_Region() ) { // Update all incoming edges
           assert( !igvn->eqv(n, this), "Must be removed from DefUse edges");
@@ -2127,7 +2124,7 @@
     // if it's not there, there's nothing to do.
     Node* fallthru = proj_out(0);
     if (fallthru != NULL) {
-      phase->is_IterGVN()->subsume_node(fallthru, in(0));
+      phase->is_IterGVN()->replace_node(fallthru, in(0));
     }
     return phase->C->top();
   }
--- a/hotspot/src/share/vm/opto/compile.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -637,34 +637,6 @@
   if (failing())  return;
   NOT_PRODUCT( verify_graph_edges(); )
 
-  // Perform escape analysis
-  if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
-    TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
-    // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction.
-    PhaseGVN* igvn = initial_gvn();
-    Node* oop_null = igvn->zerocon(T_OBJECT);
-    Node* noop_null = igvn->zerocon(T_NARROWOOP);
-
-    _congraph = new(comp_arena()) ConnectionGraph(this);
-    bool has_non_escaping_obj = _congraph->compute_escape();
-
-#ifndef PRODUCT
-    if (PrintEscapeAnalysis) {
-      _congraph->dump();
-    }
-#endif
-    // Cleanup.
-    if (oop_null->outcnt() == 0)
-      igvn->hash_delete(oop_null);
-    if (noop_null->outcnt() == 0)
-      igvn->hash_delete(noop_null);
-
-    if (!has_non_escaping_obj) {
-      _congraph = NULL;
-    }
-
-    if (failing())  return;
-  }
   // Now optimize
   Optimize();
   if (failing())  return;
@@ -1601,6 +1573,20 @@
 
   if (failing())  return;
 
+  // Perform escape analysis
+  if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
+    TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
+    ConnectionGraph::do_analysis(this, &igvn);
+
+    if (failing())  return;
+
+    igvn.optimize();
+    print_method("Iter GVN 3", 2);
+
+    if (failing())  return;
+
+  }
+
   // Loop transforms on the ideal graph.  Range Check Elimination,
   // peeling, unrolling, etc.
 
@@ -2000,6 +1986,17 @@
     }
   }
 
+#ifdef ASSERT
+  if( n->is_Mem() ) {
+    Compile* C = Compile::current();
+    int alias_idx = C->get_alias_index(n->as_Mem()->adr_type());
+    assert( n->in(0) != NULL || alias_idx != Compile::AliasIdxRaw ||
+            // oop will be recorded in oop map if load crosses safepoint
+            n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() ||
+                             LoadNode::is_immutable_value(n->in(MemNode::Address))),
+            "raw memory operations should have control edge");
+  }
+#endif
   // Count FPU ops and common calls, implements item (3)
   switch( nop ) {
   // Count all float operations that may use FPU
--- a/hotspot/src/share/vm/opto/compile.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -362,6 +362,7 @@
   Node*         macro_node(int idx)             { return _macro_nodes->at(idx); }
   Node*         predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
   ConnectionGraph* congraph()                   { return _congraph;}
+  void set_congraph(ConnectionGraph* congraph)  { _congraph = congraph;}
   void add_macro_node(Node * n) {
     //assert(n->is_macro(), "must be a macro node");
     assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
--- a/hotspot/src/share/vm/opto/doCall.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -343,7 +343,8 @@
   // being initialized.  Uncommon-trap for not-initialized static or
   // v-calls.  Let interface calls happen.
   ciInstanceKlass* holder_klass = dest_method->holder();
-  if (!holder_klass->is_initialized() &&
+  if (!holder_klass->is_being_initialized() &&
+      !holder_klass->is_initialized() &&
       !holder_klass->is_interface()) {
     uncommon_trap(Deoptimization::Reason_uninitialized,
                   Deoptimization::Action_reinterpret,
--- a/hotspot/src/share/vm/opto/escape.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -81,18 +81,18 @@
 }
 #endif
 
-ConnectionGraph::ConnectionGraph(Compile * C) :
+ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
   _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
   _processed(C->comp_arena()),
   _collecting(true),
   _compile(C),
+  _igvn(igvn),
   _node_map(C->comp_arena()) {
 
   _phantom_object = C->top()->_idx,
   add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
 
   // Add ConP(#NULL) and ConN(#NULL) nodes.
-  PhaseGVN* igvn = C->initial_gvn();
   Node* oop_null = igvn->zerocon(T_OBJECT);
   _oop_null = oop_null->_idx;
   assert(_oop_null < C->unique(), "should be created already");
@@ -182,7 +182,7 @@
     _processed.set(n->_idx);
 }
 
-PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) {
+PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
   uint idx = n->_idx;
   PointsToNode::EscapeState es;
 
@@ -207,22 +207,26 @@
   if (n->uncast()->_idx >= nodes_size())
     return PointsToNode::UnknownEscape;
 
+  PointsToNode::EscapeState orig_es = es;
+
   // compute max escape state of anything this node could point to
   VectorSet ptset(Thread::current()->resource_area());
-  PointsTo(ptset, n, phase);
+  PointsTo(ptset, n);
   for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
     uint pt = i.elem;
     PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
     if (pes > es)
       es = pes;
   }
-  // cache the computed escape state
-  assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
-  ptnode_adr(idx)->set_escape_state(es);
+  if (orig_es != es) {
+    // cache the computed escape state
+    assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
+    ptnode_adr(idx)->set_escape_state(es);
+  } // orig_es could be PointsToNode::UnknownEscape
   return es;
 }
 
-void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) {
+void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
   VectorSet visited(Thread::current()->resource_area());
   GrowableArray<uint>  worklist;
 
@@ -990,7 +994,7 @@
   GrowableArray<Node *>  memnode_worklist;
   GrowableArray<PhiNode *>  orig_phis;
 
-  PhaseGVN  *igvn = _compile->initial_gvn();
+  PhaseGVN  *igvn = _igvn;
   uint new_index_start = (uint) _compile->num_alias_types();
   Arena* arena = Thread::current()->resource_area();
   VectorSet visited(arena);
@@ -1012,7 +1016,7 @@
       CallNode *alloc = n->as_Call();
       // copy escape information to call node
       PointsToNode* ptn = ptnode_adr(alloc->_idx);
-      PointsToNode::EscapeState es = escape_state(alloc, igvn);
+      PointsToNode::EscapeState es = escape_state(alloc);
       // We have an allocation or call which returns a Java object,
       // see if it is unescaped.
       if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
@@ -1123,7 +1127,7 @@
       }
     } else if (n->is_AddP()) {
       ptset.Clear();
-      PointsTo(ptset, get_addp_base(n), igvn);
+      PointsTo(ptset, get_addp_base(n));
       assert(ptset.Size() == 1, "AddP address is unique");
       uint elem = ptset.getelem(); // Allocation node's index
       if (elem == _phantom_object) {
@@ -1143,7 +1147,7 @@
         continue;  // already processed
       }
       ptset.Clear();
-      PointsTo(ptset, n, igvn);
+      PointsTo(ptset, n);
       if (ptset.Size() == 1) {
         uint elem = ptset.getelem(); // Allocation node's index
         if (elem == _phantom_object) {
@@ -1478,6 +1482,26 @@
   return false;
 }
 
+void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
+  // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
+  // to create space for them in ConnectionGraph::_nodes[].
+  Node* oop_null = igvn->zerocon(T_OBJECT);
+  Node* noop_null = igvn->zerocon(T_NARROWOOP);
+
+  ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
+  // Perform escape analysis
+  if (congraph->compute_escape()) {
+    // There are non escaping objects.
+    C->set_congraph(congraph);
+  }
+
+  // Cleanup.
+  if (oop_null->outcnt() == 0)
+    igvn->hash_delete(oop_null);
+  if (noop_null->outcnt() == 0)
+    igvn->hash_delete(noop_null);
+}
+
 bool ConnectionGraph::compute_escape() {
   Compile* C = _compile;
 
@@ -1492,7 +1516,7 @@
   }
 
   GrowableArray<int> cg_worklist;
-  PhaseGVN* igvn = C->initial_gvn();
+  PhaseGVN* igvn = _igvn;
   bool has_allocations = false;
 
   // Push all useful nodes onto CG list and set their type.
@@ -1661,6 +1685,12 @@
   _collecting = false;
   assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
 
+#ifndef PRODUCT
+  if (PrintEscapeAnalysis) {
+    dump(); // Dump ConnectionGraph
+  }
+#endif
+
   bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0;
   if ( has_scalar_replaceable_candidates &&
        C->AliasLevel() >= 3 && EliminateAllocations ) {
@@ -1671,10 +1701,6 @@
 
     if (C->failing())  return false;
 
-    // Clean up after split unique types.
-    ResourceMark rm;
-    PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn());
-
     C->print_method("After Escape Analysis", 2);
 
 #ifdef ASSERT
@@ -1711,7 +1737,7 @@
   int offset = ptn->offset();
   Node* base = get_addp_base(n);
   ptset.Clear();
-  PointsTo(ptset, base, phase);
+  PointsTo(ptset, base);
   int ptset_size = ptset.Size();
 
   // Check if a oop field's initializing value is recorded and add
@@ -1889,7 +1915,7 @@
             arg = get_addp_base(arg);
           }
           ptset.Clear();
-          PointsTo(ptset, arg, phase);
+          PointsTo(ptset, arg);
           for( VectorSetI j(&ptset); j.test(); ++j ) {
             uint pt = j.elem;
             set_escape_state(pt, PointsToNode::ArgEscape);
@@ -1934,7 +1960,7 @@
             }
 
             ptset.Clear();
-            PointsTo(ptset, arg, phase);
+            PointsTo(ptset, arg);
             for( VectorSetI j(&ptset); j.test(); ++j ) {
               uint pt = j.elem;
               if (global_escapes) {
@@ -1970,7 +1996,7 @@
           Node *arg = call->in(i)->uncast();
           set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
           ptset.Clear();
-          PointsTo(ptset, arg, phase);
+          PointsTo(ptset, arg);
           for( VectorSetI j(&ptset); j.test(); ++j ) {
             uint pt = j.elem;
             set_escape_state(pt, PointsToNode::GlobalEscape);
@@ -2433,7 +2459,7 @@
       Node *base = get_addp_base(n);
       // Create a field edge to this node from everything base could point to.
       VectorSet ptset(Thread::current()->resource_area());
-      PointsTo(ptset, base, phase);
+      PointsTo(ptset, base);
       for( VectorSetI i(&ptset); i.test(); ++i ) {
         uint pt = i.elem;
         add_field_edge(pt, n_idx, address_offset(n, phase));
@@ -2501,7 +2527,7 @@
       // For everything "adr_base" could point to, create a deferred edge from
       // this node to each field with the same offset.
       VectorSet ptset(Thread::current()->resource_area());
-      PointsTo(ptset, adr_base, phase);
+      PointsTo(ptset, adr_base);
       int offset = address_offset(adr, phase);
       for( VectorSetI i(&ptset); i.test(); ++i ) {
         uint pt = i.elem;
@@ -2594,7 +2620,7 @@
       // For everything "adr_base" could point to, create a deferred edge
       // to "val" from each field with the same offset.
       VectorSet ptset(Thread::current()->resource_area());
-      PointsTo(ptset, adr_base, phase);
+      PointsTo(ptset, adr_base);
       for( VectorSetI i(&ptset); i.test(); ++i ) {
         uint pt = i.elem;
         add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
@@ -2638,7 +2664,6 @@
 
 #ifndef PRODUCT
 void ConnectionGraph::dump() {
-  PhaseGVN  *igvn = _compile->initial_gvn();
   bool first = true;
 
   uint size = nodes_size();
@@ -2648,7 +2673,7 @@
 
     if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
       continue;
-    PointsToNode::EscapeState es = escape_state(ptn->_node, igvn);
+    PointsToNode::EscapeState es = escape_state(ptn->_node);
     if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
       if (first) {
         tty->cr();
--- a/hotspot/src/share/vm/opto/escape.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/escape.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -227,6 +227,7 @@
   uint                     _noop_null; // ConN(#NULL)
 
   Compile *                  _compile; // Compile object for current compilation
+  PhaseIterGVN *                _igvn; // Value numbering
 
   // Address of an element in _nodes.  Used when the element is to be modified
   PointsToNode *ptnode_adr(uint idx) const {
@@ -257,7 +258,7 @@
   // walk the connection graph starting at the node corresponding to "n" and
   // add the index of everything it could point to, to "ptset".  This may cause
   // Phi's encountered to get (re)processed  (which requires "phase".)
-  void PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase);
+  void PointsTo(VectorSet &ptset, Node * n);
 
   //  Edge manipulation.  The "from_i" and "to_i" arguments are the
   //  node indices of the source and destination of the edge
@@ -310,7 +311,7 @@
   // Node:  This assumes that escape analysis is run before
   //        PhaseIterGVN creation
   void record_for_optimizer(Node *n) {
-    _compile->record_for_igvn(n);
+    _igvn->_worklist.push(n);
   }
 
   // Set the escape state of a node
@@ -320,16 +321,20 @@
   void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase);
 
 public:
-  ConnectionGraph(Compile *C);
+  ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
 
   // Check for non-escaping candidates
   static bool has_candidates(Compile *C);
 
+  // Perform escape analysis
+  static void do_analysis(Compile *C, PhaseIterGVN *igvn);
+
   // Compute the escape information
   bool compute_escape();
 
   // escape state of a node
-  PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
+  PointsToNode::EscapeState escape_state(Node *n);
+
   // other information we have collected
   bool is_scalar_replaceable(Node *n) {
     if (_collecting || (n->_idx >= nodes_size()))
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1789,9 +1789,10 @@
 
 void GraphKit::increment_counter(Node* counter_addr) {
   int adr_type = Compile::AliasIdxRaw;
-  Node* cnt  = make_load(NULL, counter_addr, TypeInt::INT, T_INT, adr_type);
+  Node* ctrl = control();
+  Node* cnt  = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type);
   Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
-  store_to_memory( NULL, counter_addr, incr, T_INT, adr_type );
+  store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type );
 }
 
 
@@ -2771,11 +2772,7 @@
     // Update the counter for this lock.  Don't bother using an atomic
     // operation since we don't require absolute accuracy.
     lock->create_lock_counter(map()->jvms());
-    int adr_type = Compile::AliasIdxRaw;
-    Node* counter_addr = makecon(TypeRawPtr::make(lock->counter()->addr()));
-    Node* cnt  = make_load(NULL, counter_addr, TypeInt::INT, T_INT, adr_type);
-    Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
-    store_to_memory(control(), counter_addr, incr, T_INT, adr_type);
+    increment_counter(lock->counter()->addr());
   }
 #endif
 
--- a/hotspot/src/share/vm/opto/ifnode.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/ifnode.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1081,11 +1081,9 @@
 
   igvn->register_new_node_with_optimizer(new_if_f);
   igvn->register_new_node_with_optimizer(new_if_t);
-  igvn->hash_delete(old_if_f);
-  igvn->hash_delete(old_if_t);
   // Flip test, so flip trailing control
-  igvn->subsume_node(old_if_f, new_if_t);
-  igvn->subsume_node(old_if_t, new_if_f);
+  igvn->replace_node(old_if_f, new_if_t);
+  igvn->replace_node(old_if_t, new_if_f);
 
   // Progress
   return iff;
--- a/hotspot/src/share/vm/opto/library_call.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -3512,8 +3512,7 @@
 
   // Get the header out of the object, use LoadMarkNode when available
   Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
-  Node* header = make_load(NULL, header_addr, TypeRawPtr::BOTTOM, T_ADDRESS);
-  header = _gvn.transform( new (C, 2) CastP2XNode(NULL, header) );
+  Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type());
 
   // Test the header to see if it is unlocked.
   Node *lock_mask      = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
@@ -5202,7 +5201,7 @@
   // super_check_offset, for the desired klass.
   int sco_offset = Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc);
   Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset);
-  Node* n3 = new(C, 3) LoadINode(NULL, immutable_memory(), p3, TypeRawPtr::BOTTOM);
+  Node* n3 = new(C, 3) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr());
   Node* check_offset = _gvn.transform(n3);
   Node* check_value  = dest_elem_klass;
 
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -194,8 +194,7 @@
     addx = new (phase->C, 3) AddINode(x, inv);
   }
   phase->register_new_node(addx, phase->get_ctrl(x));
-  phase->_igvn.hash_delete(n1);
-  phase->_igvn.subsume_node(n1, addx);
+  phase->_igvn.replace_node(n1, addx);
   return addx;
 }
 
@@ -1586,8 +1585,7 @@
   Node *phi = cl->phi();
   Node *final = new (phase->C, 3) SubINode( cl->limit(), cl->stride() );
   phase->register_new_node(final,cl->in(LoopNode::EntryControl));
-  phase->_igvn.hash_delete(phi);
-  phase->_igvn.subsume_node(phi,final);
+  phase->_igvn.replace_node(phi,final);
   phase->C->set_major_progress();
   return true;
 }
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -400,7 +400,7 @@
     nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl));
     nphi = _igvn.register_new_node_with_optimizer(nphi);
     set_ctrl(nphi, get_ctrl(phi));
-    _igvn.subsume_node(phi, nphi);
+    _igvn.replace_node(phi, nphi);
     phi = nphi->as_Phi();
   }
   cmp = cmp->clone();
@@ -760,7 +760,7 @@
       // which in turn prevents removing an empty loop.
       Node *id_old_phi = old_phi->Identity( &igvn );
       if( id_old_phi != old_phi ) { // Found a simple identity?
-        // Note that I cannot call 'subsume_node' here, because
+        // Note that I cannot call 'replace_node' here, because
         // that will yank the edge from old_phi to the Region and
         // I'm mid-iteration over the Region's uses.
         for (DUIterator_Last imin, i = old_phi->last_outs(imin); i >= imin; ) {
@@ -1065,11 +1065,9 @@
     l = igvn.register_new_node_with_optimizer(l, _head);
     phase->set_created_loop_node();
     // Go ahead and replace _head
-    phase->_igvn.subsume_node( _head, l );
+    phase->_igvn.replace_node( _head, l );
     _head = l;
     phase->set_loop(_head, this);
-    for (DUIterator_Fast imax, i = l->fast_outs(imax); i < imax; i++)
-      phase->_igvn.add_users_to_worklist(l->fast_out(i));
   }
 
   // Now recursively beautify nested loops
@@ -1329,8 +1327,7 @@
         Node* add  = new (C, 3) AddINode(ratio_idx, diff);
         phase->_igvn.register_new_node_with_optimizer(add);
         phase->set_ctrl(add, cl);
-        phase->_igvn.hash_delete( phi2 );
-        phase->_igvn.subsume_node( phi2, add );
+        phase->_igvn.replace_node( phi2, add );
         // Sometimes an induction variable is unused
         if (add->outcnt() == 0) {
           phase->_igvn.remove_dead_node(add);
--- a/hotspot/src/share/vm/opto/loopnode.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -626,8 +626,7 @@
     _nodes.map( old_node->_idx, (Node*)((intptr_t)new_node + 1) );
   }
   void lazy_replace( Node *old_node, Node *new_node ) {
-    _igvn.hash_delete(old_node);
-    _igvn.subsume_node( old_node, new_node );
+    _igvn.replace_node( old_node, new_node );
     lazy_update( old_node, new_node );
   }
   void lazy_replace_proj( Node *old_node, Node *new_node ) {
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -354,8 +354,7 @@
     register_new_node( var_scale, n_ctrl );
     Node *var_add = new (C, 3) AddINode( var_scale, inv_scale );
     register_new_node( var_add, n_ctrl );
-    _igvn.hash_delete( n );
-    _igvn.subsume_node( n, var_add );
+    _igvn.replace_node( n, var_add );
     return var_add;
   }
 
@@ -390,8 +389,7 @@
           register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
           Node *add2 = new (C, 4) AddPNode( n->in(1), add1, n->in(2)->in(3) );
           register_new_node( add2, n_ctrl );
-          _igvn.hash_delete( n );
-          _igvn.subsume_node( n, add2 );
+          _igvn.replace_node( n, add2 );
           return add2;
         }
       }
@@ -412,8 +410,7 @@
           register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
           Node *add2 = new (C, 4) AddPNode( n->in(1), add1, V );
           register_new_node( add2, n_ctrl );
-          _igvn.hash_delete( n );
-          _igvn.subsume_node( n, add2 );
+          _igvn.replace_node( n, add2 );
           return add2;
         }
       }
@@ -555,8 +552,7 @@
     }
     Node *cmov = CMoveNode::make( C, cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi) );
     register_new_node( cmov, cmov_ctrl );
-    _igvn.hash_delete(phi);
-    _igvn.subsume_node( phi, cmov );
+    _igvn.replace_node( phi, cmov );
 #ifndef PRODUCT
     if( VerifyLoopOptimizations ) verify();
 #endif
@@ -642,8 +638,7 @@
 
   // Found a Phi to split thru!
   // Replace 'n' with the new phi
-  _igvn.hash_delete(n);
-  _igvn.subsume_node( n, phi );
+  _igvn.replace_node( n, phi );
   // Moved a load around the loop, 'en-registering' something.
   if( n_blk->Opcode() == Op_Loop && n->is_Load() &&
       !phi->in(LoopNode::LoopBackControl)->is_Load() )
@@ -789,13 +784,11 @@
 
     // Found a Phi to split thru!
     // Replace 'n' with the new phi
-    _igvn.hash_delete(n);
-    _igvn.subsume_node( n, phi );
+    _igvn.replace_node( n, phi );
 
     // Now split the bool up thru the phi
     Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
-    _igvn.hash_delete(bol);
-    _igvn.subsume_node( bol, bolphi );
+    _igvn.replace_node( bol, bolphi );
     assert( iff->in(1) == bolphi, "" );
     if( bolphi->Value(&_igvn)->singleton() )
       return;
@@ -803,8 +796,7 @@
     // Conditional-move?  Must split up now
     if( !iff->is_If() ) {
       Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 );
-      _igvn.hash_delete(iff);
-      _igvn.subsume_node( iff, cmovphi );
+      _igvn.replace_node( iff, cmovphi );
       return;
     }
 
@@ -950,9 +942,7 @@
   if( n_op == Op_Opaque2 &&
       n->in(1) != NULL &&
       get_loop(get_ctrl(n)) == get_loop(get_ctrl(n->in(1))) ) {
-    _igvn.add_users_to_worklist(n);
-    _igvn.hash_delete(n);
-    _igvn.subsume_node( n, n->in(1) );
+    _igvn.replace_node( n, n->in(1) );
   }
 }
 
@@ -1425,7 +1415,7 @@
           // IGVN does CSE).
           Node *hit = _igvn.hash_find_insert(use);
           if( hit )             // Go ahead and re-hash for hits.
-            _igvn.subsume_node( use, hit );
+            _igvn.replace_node( use, hit );
         }
 
         // If 'use' was in the loop-exit block, it now needs to be sunk
--- a/hotspot/src/share/vm/opto/macro.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/macro.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -135,8 +135,7 @@
   if (parm1 != NULL)  call->init_req(TypeFunc::Parms+1, parm1);
   copy_call_debug_info(oldcall, call);
   call->set_cnt(PROB_UNLIKELY_MAG(4));  // Same effect as RC_UNCOMMON.
-  _igvn.hash_delete(oldcall);
-  _igvn.subsume_node(oldcall, call);
+  _igvn.replace_node(oldcall, call);
   transform_later(call);
 
   return call;
@@ -523,8 +522,7 @@
         // Kill all new Phis
         while(value_phis.is_nonempty()) {
           Node* n = value_phis.node();
-          _igvn.hash_delete(n);
-          _igvn.subsume_node(n, C->top());
+          _igvn.replace_node(n, C->top());
           value_phis.pop();
         }
       }
@@ -1311,8 +1309,7 @@
   if (!always_slow) {
     call->set_cnt(PROB_UNLIKELY_MAG(4));  // Same effect as RC_UNCOMMON.
   }
-  _igvn.hash_delete(alloc);
-  _igvn.subsume_node(alloc, call);
+  _igvn.replace_node(alloc, call);
   transform_later(call);
 
   // Identify the output projections from the allocate node and
@@ -1431,7 +1428,7 @@
   Node* mark_node = NULL;
   // For now only enable fast locking for non-array types
   if (UseBiasedLocking && (length == NULL)) {
-    mark_node = make_load(NULL, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
+    mark_node = make_load(control, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
   } else {
     mark_node = makecon(TypeRawPtr::make((address)markOopDesc::prototype()));
   }
--- a/hotspot/src/share/vm/opto/memnode.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -815,6 +815,16 @@
 }
 #endif
 
+#ifdef ASSERT
+//----------------------------is_immutable_value-------------------------------
+// Helper function to allow a raw load without control edge for some cases
+bool LoadNode::is_immutable_value(Node* adr) {
+  return (adr->is_AddP() && adr->in(AddPNode::Base)->is_top() &&
+          adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
+          (adr->in(AddPNode::Offset)->find_intptr_t_con(-1) ==
+           in_bytes(JavaThread::osthread_offset())));
+}
+#endif
 
 //----------------------------LoadNode::make-----------------------------------
 // Polymorphic factory method:
@@ -828,6 +838,11 @@
   assert(!(adr_type->isa_aryptr() &&
            adr_type->offset() == arrayOopDesc::length_offset_in_bytes()),
          "use LoadRangeNode instead");
+  // Check control edge of raw loads
+  assert( ctl != NULL || C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
+          // oop will be recorded in oop map if load crosses safepoint
+          rt->isa_oopptr() || is_immutable_value(adr),
+          "raw memory operations should have control edge");
   switch (bt) {
   case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int()    );
   case T_BYTE:    return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int()    );
@@ -2064,6 +2079,8 @@
 // Polymorphic factory method:
 StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) {
   Compile* C = gvn.C;
+  assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
+          ctl != NULL, "raw memory operations should have control edge");
 
   switch (bt) {
   case T_BOOLEAN:
--- a/hotspot/src/share/vm/opto/memnode.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -189,6 +189,10 @@
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
 #endif
+#ifdef ASSERT
+  // Helper function to allow a raw load without control edge for some cases
+  static bool is_immutable_value(Node* adr);
+#endif
 protected:
   const Type* load_array_final_field(const TypeKlassPtr *tkls,
                                      ciKlass* klass) const;
--- a/hotspot/src/share/vm/opto/parse.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -480,6 +480,7 @@
   bool push_constant(ciConstant con, bool require_constant = false);
 
   // implementation of object creation bytecodes
+  void emit_guard_for_new(ciInstanceKlass* klass);
   void do_new();
   void do_newarray(BasicType elemtype);
   void do_anewarray();
--- a/hotspot/src/share/vm/opto/parse1.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -88,15 +88,16 @@
                                      Node *local_addrs_base) {
   Node *mem = memory(Compile::AliasIdxRaw);
   Node *adr = basic_plus_adr( local_addrs_base, local_addrs, -index*wordSize );
+  Node *ctl = control();
 
   // Very similar to LoadNode::make, except we handle un-aligned longs and
   // doubles on Sparc.  Intel can handle them just fine directly.
   Node *l;
   switch( bt ) {                // Signature is flattened
-  case T_INT:     l = new (C, 3) LoadINode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
-  case T_FLOAT:   l = new (C, 3) LoadFNode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
-  case T_ADDRESS: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM  ); break;
-  case T_OBJECT:  l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
+  case T_INT:     l = new (C, 3) LoadINode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
+  case T_FLOAT:   l = new (C, 3) LoadFNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
+  case T_ADDRESS: l = new (C, 3) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM  ); break;
+  case T_OBJECT:  l = new (C, 3) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
   case T_LONG:
   case T_DOUBLE: {
     // Since arguments are in reverse order, the argument address 'adr'
@@ -104,12 +105,12 @@
     adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize );
     if( Matcher::misaligned_doubles_ok ) {
       l = (bt == T_DOUBLE)
-        ? (Node*)new (C, 3) LoadDNode( 0, mem, adr, TypeRawPtr::BOTTOM )
-        : (Node*)new (C, 3) LoadLNode( 0, mem, adr, TypeRawPtr::BOTTOM );
+        ? (Node*)new (C, 3) LoadDNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
+        : (Node*)new (C, 3) LoadLNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
     } else {
       l = (bt == T_DOUBLE)
-        ? (Node*)new (C, 3) LoadD_unalignedNode( 0, mem, adr, TypeRawPtr::BOTTOM )
-        : (Node*)new (C, 3) LoadL_unalignedNode( 0, mem, adr, TypeRawPtr::BOTTOM );
+        ? (Node*)new (C, 3) LoadD_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
+        : (Node*)new (C, 3) LoadL_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
     }
     break;
   }
--- a/hotspot/src/share/vm/opto/parse2.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1324,33 +1324,21 @@
   case Bytecodes::_ldc_w:
   case Bytecodes::_ldc2_w:
     // If the constant is unresolved, run this BC once in the interpreter.
-    if (iter().is_unresolved_string()) {
-      uncommon_trap(Deoptimization::make_trap_request
-                    (Deoptimization::Reason_unloaded,
-                     Deoptimization::Action_reinterpret,
-                     iter().get_constant_index()),
-                    NULL, "unresolved_string");
-      break;
-    } else {
+    {
       ciConstant constant = iter().get_constant();
-      if (constant.basic_type() == T_OBJECT) {
-        ciObject* c = constant.as_object();
-        if (c->is_klass()) {
-          // The constant returned for a klass is the ciKlass for the
-          // entry.  We want the java_mirror so get it.
-          ciKlass* klass = c->as_klass();
-          if (klass->is_loaded()) {
-            constant = ciConstant(T_OBJECT, klass->java_mirror());
-          } else {
-            uncommon_trap(Deoptimization::make_trap_request
-                          (Deoptimization::Reason_unloaded,
-                           Deoptimization::Action_reinterpret,
-                           iter().get_constant_index()),
-                          NULL, "unresolved_klass");
-            break;
-          }
-        }
+      if (constant.basic_type() == T_OBJECT &&
+          !constant.as_object()->is_loaded()) {
+        int index = iter().get_constant_pool_index();
+        constantTag tag = iter().get_constant_pool_tag(index);
+        uncommon_trap(Deoptimization::make_trap_request
+                      (Deoptimization::Reason_unloaded,
+                       Deoptimization::Action_reinterpret,
+                       index),
+                      NULL, tag.internal_name());
+        break;
       }
+      assert(constant.basic_type() != T_OBJECT || !constant.as_object()->is_klass(),
+             "must be java_mirror of klass");
       bool pushed = push_constant(constant, true);
       guarantee(pushed, "must be possible to push this constant");
     }
--- a/hotspot/src/share/vm/opto/parseHelper.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, 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
@@ -197,6 +197,43 @@
 }
 
 
+void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
+  // Emit guarded new
+  //   if (klass->_init_thread != current_thread ||
+  //       klass->_init_state != being_initialized)
+  //      uncommon_trap
+  Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() );
+  Node* merge = new (C, 3) RegionNode(3);
+  _gvn.set_type(merge, Type::CONTROL);
+  Node* kls = makecon(TypeKlassPtr::make(klass));
+
+  Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+  Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset);
+  Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS);
+  Node *tst   = Bool( CmpP( init_thread, cur_thread), BoolTest::eq);
+  IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
+  set_control(IfTrue(iff));
+  merge->set_req(1, IfFalse(iff));
+
+  Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes());
+  adr_node = basic_plus_adr(kls, kls, init_state_offset);
+  Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT);
+  Node* being_init = _gvn.intcon(instanceKlass::being_initialized);
+  tst   = Bool( CmpI( init_state, being_init), BoolTest::eq);
+  iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN);
+  set_control(IfTrue(iff));
+  merge->set_req(2, IfFalse(iff));
+
+  PreserveJVMState pjvms(this);
+  record_for_igvn(merge);
+  set_control(merge);
+
+  uncommon_trap(Deoptimization::Reason_uninitialized,
+                Deoptimization::Action_reinterpret,
+                klass);
+}
+
+
 //------------------------------do_new-----------------------------------------
 void Parse::do_new() {
   kill_dead_locals();
@@ -206,7 +243,7 @@
   assert(will_link, "_new: typeflow responsibility");
 
   // Should initialize, or throw an InstantiationError?
-  if (!klass->is_initialized() ||
+  if (!klass->is_initialized() && !klass->is_being_initialized() ||
       klass->is_abstract() || klass->is_interface() ||
       klass->name() == ciSymbol::java_lang_Class() ||
       iter().is_unresolved_klass()) {
@@ -215,6 +252,9 @@
                   klass);
     return;
   }
+  if (klass->is_being_initialized()) {
+    emit_guard_for_new(klass);
+  }
 
   Node* kls = makecon(TypeKlassPtr::make(klass));
   Node* obj = new_instance(kls);
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1447,16 +1447,12 @@
           Node* m = n->out(i);
           if( m->is_Phi() ) {
             assert(type(m) == Type::TOP, "Unreachable region should not have live phis.");
-            add_users_to_worklist(m);
-            hash_delete(m); // Yank from hash before hacking edges
-            subsume_node(m, nn);
+            replace_node(m, nn);
             --i; // deleted this phi; rescan starting with next position
           }
         }
       }
-      add_users_to_worklist(n); // Users of about-to-be-constant 'n'
-      hash_delete(n);           // Removed 'n' from table before subsuming it
-      subsume_node(n,nn);       // Update DefUse edges for new constant
+      replace_node(n,nn);       // Update DefUse edges for new constant
     }
     return nn;
   }
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -393,6 +393,10 @@
 
   // Idealize old Node 'n' with respect to its inputs and its value
   virtual Node *transform_old( Node *a_node );
+
+  // Subsume users of node 'old' into node 'nn'
+  void subsume_node( Node *old, Node *nn );
+
 protected:
 
   // Idealize new Node 'n' with respect to its inputs and its value
@@ -439,10 +443,6 @@
     remove_globally_dead_node(dead);
   }
 
-  // Subsume users of node 'old' into node 'nn'
-  // If no Def-Use info existed for 'nn' it will after call.
-  void subsume_node( Node *old, Node *nn );
-
   // Add users of 'n' to worklist
   void add_users_to_worklist0( Node *n );
   void add_users_to_worklist ( Node *n );
@@ -450,7 +450,7 @@
   // Replace old node with new one.
   void replace_node( Node *old, Node *nn ) {
     add_users_to_worklist(old);
-    hash_delete(old);
+    hash_delete(old); // Yank from hash before hacking edges
     subsume_node(old, nn);
   }
 
--- a/hotspot/src/share/vm/opto/split_if.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/split_if.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -217,8 +217,7 @@
   register_new_node(phi, blk1);
 
   // Remove cloned-up value from optimizer; use phi instead
-  _igvn.hash_delete(n);
-  _igvn.subsume_node( n, phi );
+  _igvn.replace_node( n, phi );
 
   // (There used to be a self-recursive call to split_up() here,
   // but it is not needed.  All necessary forward walking is done
@@ -352,8 +351,7 @@
   }
 
   if (use_blk == NULL) {        // He's dead, Jim
-    _igvn.hash_delete(use);
-    _igvn.subsume_node(use, C->top());
+    _igvn.replace_node(use, C->top());
   }
 
   return use_blk;
--- a/hotspot/src/share/vm/opto/superword.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1172,8 +1172,7 @@
       _phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
       for (uint j = 0; j < p->size(); j++) {
         Node* pm = p->at(j);
-        _igvn.hash_delete(pm);
-        _igvn.subsume_node(pm, vn);
+        _igvn.replace_node(pm, vn);
       }
       _igvn._worklist.push(vn);
     }
--- a/hotspot/src/share/vm/opto/type.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -182,6 +182,8 @@
   return t->hash();
 }
 
+#define SMALLINT ((juint)3)  // a value too insignificant to consider widening
+
 //--------------------------Initialize_shared----------------------------------
 void Type::Initialize_shared(Compile* current) {
   // This method does not need to be locked because the first system
@@ -240,6 +242,7 @@
   assert( TypeInt::CC_GT == TypeInt::ONE,     "types must match for CmpL to work" );
   assert( TypeInt::CC_EQ == TypeInt::ZERO,    "types must match for CmpL to work" );
   assert( TypeInt::CC_GE == TypeInt::BOOL,    "types must match for CmpL to work" );
+  assert( (juint)(TypeInt::CC->_hi - TypeInt::CC->_lo) <= SMALLINT, "CC is truly small");
 
   TypeLong::MINUS_1 = TypeLong::make(-1);        // -1
   TypeLong::ZERO    = TypeLong::make( 0);        //  0
@@ -1054,16 +1057,21 @@
   return (TypeInt*)(new TypeInt(lo,lo,WidenMin))->hashcons();
 }
 
-#define SMALLINT ((juint)3)  // a value too insignificant to consider widening
-
-const TypeInt *TypeInt::make( jint lo, jint hi, int w ) {
+static int normalize_int_widen( jint lo, jint hi, int w ) {
   // Certain normalizations keep us sane when comparing types.
   // The 'SMALLINT' covers constants and also CC and its relatives.
-  assert(CC == NULL || (juint)(CC->_hi - CC->_lo) <= SMALLINT, "CC is truly small");
   if (lo <= hi) {
-    if ((juint)(hi - lo) <= SMALLINT)   w = Type::WidenMin;
-    if ((juint)(hi - lo) >= max_juint)  w = Type::WidenMax; // plain int
+    if ((juint)(hi - lo) <= SMALLINT)  w = Type::WidenMin;
+    if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT
+  } else {
+    if ((juint)(lo - hi) <= SMALLINT)  w = Type::WidenMin;
+    if ((juint)(lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT
   }
+  return w;
+}
+
+const TypeInt *TypeInt::make( jint lo, jint hi, int w ) {
+  w = normalize_int_widen(lo, hi, w);
   return (TypeInt*)(new TypeInt(lo,hi,w))->hashcons();
 }
 
@@ -1103,14 +1111,14 @@
 
   // Expand covered set
   const TypeInt *r = t->is_int();
-  // (Avoid TypeInt::make, to avoid the argument normalizations it enforces.)
-  return (new TypeInt( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons();
+  return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) );
 }
 
 //------------------------------xdual------------------------------------------
 // Dual: reverse hi & lo; flip widen
 const Type *TypeInt::xdual() const {
-  return new TypeInt(_hi,_lo,WidenMax-_widen);
+  int w = normalize_int_widen(_hi,_lo, WidenMax-_widen);
+  return new TypeInt(_hi,_lo,w);
 }
 
 //------------------------------widen------------------------------------------
@@ -1202,7 +1210,7 @@
 //-----------------------------filter------------------------------------------
 const Type *TypeInt::filter( const Type *kills ) const {
   const TypeInt* ft = join(kills)->isa_int();
-  if (ft == NULL || ft->_lo > ft->_hi)
+  if (ft == NULL || ft->empty())
     return Type::TOP;           // Canonical empty value
   if (ft->_widen < this->_widen) {
     // Do not allow the value of kill->_widen to affect the outcome.
@@ -1304,13 +1312,21 @@
   return (TypeLong*)(new TypeLong(lo,lo,WidenMin))->hashcons();
 }
 
-const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) {
+static int normalize_long_widen( jlong lo, jlong hi, int w ) {
   // Certain normalizations keep us sane when comparing types.
-  // The '1' covers constants.
+  // The 'SMALLINT' covers constants.
   if (lo <= hi) {
-    if ((julong)(hi - lo) <= SMALLINT)    w = Type::WidenMin;
-    if ((julong)(hi - lo) >= max_julong)  w = Type::WidenMax; // plain long
+    if ((julong)(hi - lo) <= SMALLINT)   w = Type::WidenMin;
+    if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG
+  } else {
+    if ((julong)(lo - hi) <= SMALLINT)   w = Type::WidenMin;
+    if ((julong)(lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG
   }
+  return w;
+}
+
+const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) {
+  w = normalize_long_widen(lo, hi, w);
   return (TypeLong*)(new TypeLong(lo,hi,w))->hashcons();
 }
 
@@ -1351,14 +1367,14 @@
 
   // Expand covered set
   const TypeLong *r = t->is_long(); // Turn into a TypeLong
-  // (Avoid TypeLong::make, to avoid the argument normalizations it enforces.)
-  return (new TypeLong( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons();
+  return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) );
 }
 
 //------------------------------xdual------------------------------------------
 // Dual: reverse hi & lo; flip widen
 const Type *TypeLong::xdual() const {
-  return new TypeLong(_hi,_lo,WidenMax-_widen);
+  int w = normalize_long_widen(_hi,_lo, WidenMax-_widen);
+  return new TypeLong(_hi,_lo,w);
 }
 
 //------------------------------widen------------------------------------------
@@ -1453,7 +1469,7 @@
 //-----------------------------filter------------------------------------------
 const Type *TypeLong::filter( const Type *kills ) const {
   const TypeLong* ft = join(kills)->isa_long();
-  if (ft == NULL || ft->_lo > ft->_hi)
+  if (ft == NULL || ft->empty())
     return Type::TOP;           // Canonical empty value
   if (ft->_widen < this->_widen) {
     // Do not allow the value of kill->_widen to affect the outcome.
--- a/hotspot/src/share/vm/prims/jvm.h	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h	Wed Jul 05 17:17:57 2017 +0200
@@ -1044,7 +1044,22 @@
     JVM_CONSTANT_Fieldref,
     JVM_CONSTANT_Methodref,
     JVM_CONSTANT_InterfaceMethodref,
-    JVM_CONSTANT_NameAndType
+    JVM_CONSTANT_NameAndType,
+    JVM_CONSTANT_MethodHandle           = 15,  // JSR 292
+    JVM_CONSTANT_MethodType             = 16   // JSR 292
+};
+
+/* JVM_CONSTANT_MethodHandle subtypes */
+enum {
+    JVM_REF_getField                = 1,
+    JVM_REF_getStatic               = 2,
+    JVM_REF_putField                = 3,
+    JVM_REF_putStatic               = 4,
+    JVM_REF_invokeVirtual           = 5,
+    JVM_REF_invokeStatic            = 6,
+    JVM_REF_invokeSpecial           = 7,
+    JVM_REF_newInvokeSpecial        = 8,
+    JVM_REF_invokeInterface         = 9
 };
 
 /* Used in the newarray instruction. */
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -122,30 +122,8 @@
     }
   }
 
-  // we must name the CodeBlob - some CodeBlobs already have names :-
-  // - stubs used by compiled code to call a (static) C++ runtime routine
-  // - non-relocatable machine code such as the interpreter, stubroutines, etc.
-  // - various singleton blobs
-  //
-  // others are unnamed so we create a name :-
-  // - OSR adapter (interpreter frame that has been on-stack replaced)
-  // - I2C and C2I adapters
-  const char* name = NULL;
-  if (cb->is_runtime_stub()) {
-    name = ((RuntimeStub*)cb)->name();
-  }
-  if (cb->is_buffer_blob()) {
-    name = ((BufferBlob*)cb)->name();
-  }
-  if (cb->is_deoptimization_stub() || cb->is_safepoint_stub()) {
-    name = ((SingletonBlob*)cb)->name();
-  }
-  if (cb->is_uncommon_trap_stub() || cb->is_exception_stub()) {
-    name = ((SingletonBlob*)cb)->name();
-  }
-
   // record the CodeBlob details as a JvmtiCodeBlobDesc
-  JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(name, cb->instructions_begin(),
+  JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(cb->name(), cb->instructions_begin(),
                                                  cb->instructions_end());
   _global_code_blobs->append(scb);
 }
@@ -197,7 +175,10 @@
 jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) {
   CodeBlobCollector collector;
 
-  // first collect all the code blobs
+  // First collect all the code blobs.  This has to be done in a
+  // single pass over the code cache with CodeCache_lock held because
+  // there isn't any safe way to iterate over regular CodeBlobs since
+  // they can be freed at any point.
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     collector.collect();
@@ -213,168 +194,28 @@
 }
 
 
-// Support class to describe a nmethod in the CodeCache
-
-class nmethodDesc: public CHeapObj {
- private:
-  methodHandle _method;
-  address _code_begin;
-  address _code_end;
-  jvmtiAddrLocationMap* _map;
-  jint _map_length;
- public:
-  nmethodDesc(methodHandle method, address code_begin, address code_end,
-              jvmtiAddrLocationMap* map, jint map_length) {
-    _method = method;
-    _code_begin = code_begin;
-    _code_end = code_end;
-    _map = map;
-    _map_length = map_length;
-  }
-  methodHandle method() const           { return _method; }
-  address code_begin() const            { return _code_begin; }
-  address code_end() const              { return _code_end; }
-  jvmtiAddrLocationMap* map() const     { return _map; }
-  jint map_length() const               { return _map_length; }
-};
-
-
-// Support class to collect a list of the nmethod CodeBlobs in
-// the CodeCache.
-//
-// Usage :-
-//
-// nmethodCollector collector;
-//
-// collector.collect();
-// JvmtiCodeBlobDesc* blob = collector.first();
-// while (blob != NULL) {
-//   :
-//   blob = collector.next();
-// }
-//
-class nmethodCollector : StackObj {
- private:
-  GrowableArray<nmethodDesc*>* _nmethods;           // collect nmethods
-  int _pos;                                         // iteration support
-
-  // used during a collection
-  static GrowableArray<nmethodDesc*>* _global_nmethods;
-  static void do_nmethod(nmethod* nm);
- public:
-  nmethodCollector() {
-    _nmethods = NULL;
-    _pos = -1;
-  }
-  ~nmethodCollector() {
-    if (_nmethods != NULL) {
-      for (int i=0; i<_nmethods->length(); i++) {
-        nmethodDesc* blob = _nmethods->at(i);
-        if (blob->map()!= NULL) {
-          FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, blob->map());
-        }
-      }
-      delete _nmethods;
-    }
-  }
-
-  // collect list of nmethods in the cache
-  void collect();
-
-  // iteration support - return first code blob
-  nmethodDesc* first() {
-    assert(_nmethods != NULL, "not collected");
-    if (_nmethods->length() == 0) {
-      return NULL;
-    }
-    _pos = 0;
-    return _nmethods->at(0);
-  }
-
-  // iteration support - return next code blob
-  nmethodDesc* next() {
-    assert(_pos >= 0, "iteration not started");
-    if (_pos+1 >= _nmethods->length()) {
-      return NULL;
-    }
-    return _nmethods->at(++_pos);
-  }
-};
-
-// used during collection
-GrowableArray<nmethodDesc*>* nmethodCollector::_global_nmethods;
-
-
-// called for each nmethod in the CodeCache
-//
-// This function simply adds a descriptor for each nmethod to the global list.
-
-void nmethodCollector::do_nmethod(nmethod* nm) {
-  // ignore zombies
-  if (!nm->is_alive()) {
-    return;
-  }
-
-  assert(nm->method() != NULL, "checking");
-
-  // create the location map for the nmethod.
-  jvmtiAddrLocationMap* map;
-  jint map_length;
-  JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length);
-
-  // record the nmethod details
-  methodHandle mh(nm->method());
-  nmethodDesc* snm = new nmethodDesc(mh,
-                                     nm->code_begin(),
-                                     nm->code_end(),
-                                     map,
-                                     map_length);
-  _global_nmethods->append(snm);
-}
-
-// collects a list of nmethod in the CodeCache.
-//
-// The created list is growable array of nmethodDesc - each one describes
-// a nmethod and includs its JVMTI address location map.
-
-void nmethodCollector::collect() {
-  assert_locked_or_safepoint(CodeCache_lock);
-  assert(_global_nmethods == NULL, "checking");
-
-  // create the list
-  _global_nmethods = new (ResourceObj::C_HEAP) GrowableArray<nmethodDesc*>(100,true);
-
-  // any a descriptor for each nmethod to the list.
-  CodeCache::nmethods_do(do_nmethod);
-
-  // make the list the instance list
-  _nmethods = _global_nmethods;
-  _global_nmethods = NULL;
-}
-
 // Generate a COMPILED_METHOD_LOAD event for each nnmethod
-
 jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) {
   HandleMark hm;
-  nmethodCollector collector;
-
-  // first collect all nmethods
-  {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-    collector.collect();
-  }
 
-  // iterate over the  list and post an event for each nmethod
-  nmethodDesc* nm_desc = collector.first();
-  while (nm_desc != NULL) {
-    methodOop method = nm_desc->method()();
-    jmethodID mid = method->jmethod_id();
-    assert(mid != NULL, "checking");
-    JvmtiExport::post_compiled_method_load(env, mid,
-                                           (jint)(nm_desc->code_end() - nm_desc->code_begin()),
-                                           nm_desc->code_begin(), nm_desc->map_length(),
-                                           nm_desc->map());
-    nm_desc = collector.next();
+  // Walk the CodeCache notifying for live nmethods.  The code cache
+  // may be changing while this is happening which is ok since newly
+  // created nmethod will notify normally and nmethods which are freed
+  // can be safely skipped.
+  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+  nmethod* current = CodeCache::first_nmethod();
+  while (current != NULL) {
+    // Only notify for live nmethods
+    if (current->is_alive()) {
+      // Lock the nmethod so it can't be freed
+      nmethodLocker nml(current);
+
+      // Don't hold the lock over the notify or jmethodID creation
+      MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      current->get_and_cache_jmethod_id();
+      JvmtiExport::post_compiled_method_load(current);
+    }
+    current = CodeCache::next_nmethod(current);
   }
   return JVMTI_ERROR_NONE;
 }
--- a/hotspot/src/share/vm/prims/methodComparator.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -163,10 +163,10 @@
 
   case Bytecodes::_ldc   : // fall through
   case Bytecodes::_ldc_w : {
-    Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method()(), _s_old->bcp());
-    Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method()(), _s_new->bcp());
-    int cpi_old = ldc_old->index();
-    int cpi_new = ldc_new->index();
+    Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method(), _s_old->bci());
+    Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method(), _s_new->bci());
+    int cpi_old = ldc_old->pool_index();
+    int cpi_new = ldc_new->pool_index();
     constantTag tag_old = _old_cp->tag_at(cpi_old);
     constantTag tag_new = _new_cp->tag_at(cpi_new);
     if (tag_old.is_int() || tag_old.is_float()) {
@@ -187,12 +187,30 @@
       if (strcmp(_old_cp->string_at_noresolve(cpi_old),
                  _new_cp->string_at_noresolve(cpi_new)) != 0)
         return false;
-    } else { // tag_old should be klass - 4881222
+    } else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) {
+      // tag_old should be klass - 4881222
       if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
         return false;
       if (_old_cp->klass_at_noresolve(cpi_old) !=
           _new_cp->klass_at_noresolve(cpi_new))
         return false;
+    } else if (tag_old.is_method_type() && tag_new.is_method_type()) {
+      int mti_old = _old_cp->method_type_index_at(cpi_old);
+      int mti_new = _new_cp->method_type_index_at(cpi_new);
+      if ((_old_cp->symbol_at(mti_old) != _new_cp->symbol_at(mti_new)))
+        return false;
+    } else if (tag_old.is_method_handle() && tag_new.is_method_handle()) {
+      if (_old_cp->method_handle_ref_kind_at(cpi_old) !=
+          _new_cp->method_handle_ref_kind_at(cpi_new))
+        return false;
+      int mhi_old = _old_cp->method_handle_index_at(cpi_old);
+      int mhi_new = _new_cp->method_handle_index_at(cpi_new);
+      if ((_old_cp->uncached_klass_ref_at_noresolve(mhi_old) != _new_cp->uncached_klass_ref_at_noresolve(mhi_new)) ||
+          (_old_cp->uncached_name_ref_at(mhi_old) != _new_cp->uncached_name_ref_at(mhi_new)) ||
+          (_old_cp->uncached_signature_ref_at(mhi_old) != _new_cp->uncached_signature_ref_at(mhi_new)))
+        return false;
+    } else {
+      return false;  // unknown tag
     }
     break;
   }
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1376,11 +1376,6 @@
   }
   no_shared_spaces();
 
-  // Set the maximum pause time goal to be a reasonable default.
-  if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
-    FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
-  }
-
   if (FLAG_IS_DEFAULT(MarkStackSize)) {
     FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE);
   }
@@ -1513,6 +1508,9 @@
   if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
     FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
   }
+  if (AggressiveOpts && FLAG_IS_DEFAULT(OptimizeStringConcat)) {
+    FLAG_SET_DEFAULT(OptimizeStringConcat, true);
+  }
 #endif
 
   if (AggressiveOpts) {
@@ -1697,20 +1695,21 @@
 
   status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
 
-  // Check user specified sharing option conflict with Parallel GC
-  bool cannot_share = ((UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC || UseParNewGC ||
-                       UseParallelGC || UseParallelOldGC ||
-                       SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages));
-
+  // Check whether user-specified sharing option conflicts with GC or page size.
+  // Both sharing and large pages are enabled by default on some platforms;
+  // large pages override sharing only if explicitly set on the command line.
+  const bool cannot_share = UseConcMarkSweepGC || CMSIncrementalMode ||
+          UseG1GC || UseParNewGC || UseParallelGC || UseParallelOldGC ||
+          UseLargePages && FLAG_IS_CMDLINE(UseLargePages);
   if (cannot_share) {
     // Either force sharing on by forcing the other options off, or
     // force sharing off.
     if (DumpSharedSpaces || ForceSharedSpaces) {
       jio_fprintf(defaultStream::error_stream(),
-                  "Reverting to Serial GC because of %s\n",
-                  ForceSharedSpaces ? " -Xshare:on" : "-Xshare:dump");
+                  "Using Serial GC and default page size because of %s\n",
+                  ForceSharedSpaces ? "-Xshare:on" : "-Xshare:dump");
       force_serial_gc();
-      FLAG_SET_DEFAULT(SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages), false);
+      FLAG_SET_DEFAULT(UseLargePages, false);
     } else {
       if (UseSharedSpaces && Verbose) {
         jio_fprintf(defaultStream::error_stream(),
@@ -1719,6 +1718,8 @@
       }
       no_shared_spaces();
     }
+  } else if (UseLargePages && (UseSharedSpaces || DumpSharedSpaces)) {
+    FLAG_SET_DEFAULT(UseLargePages, false);
   }
 
   status = status && check_gc_consistency();
--- a/hotspot/src/share/vm/runtime/globals.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1975,7 +1975,7 @@
           "Adaptive size policy maximum GC pause time goal in msec, "       \
           "or (G1 Only) the max. GC time per MMU time slice")               \
                                                                             \
-  product(intx, GCPauseIntervalMillis, 500,                                 \
+  product(uintx, GCPauseIntervalMillis, 0,                                  \
           "Time slice for MMU specification")                               \
                                                                             \
   product(uintx, MaxGCMinorPauseMillis, max_uintx,                          \
@@ -2541,9 +2541,6 @@
           "Enable String cache capabilities on String.java")                \
                                                                             \
   /* statistics */                                                          \
-  develop(bool, UseVTune, false,                                            \
-          "enable support for Intel's VTune profiler")                      \
-                                                                            \
   develop(bool, CountCompiledCalls, false,                                  \
           "counts method invocations")                                      \
                                                                             \
--- a/hotspot/src/share/vm/runtime/init.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/init.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -34,7 +34,6 @@
 
 // Initialization done by Java thread in init_globals()
 void management_init();
-void vtune_init();
 void bytecodes_init();
 void classLoader_init();
 void codeCache_init();
@@ -82,7 +81,6 @@
 jint init_globals() {
   HandleMark hm;
   management_init();
-  vtune_init();
   bytecodes_init();
   classLoader_init();
   codeCache_init();
--- a/hotspot/src/share/vm/runtime/java.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -432,8 +432,6 @@
   print_statistics();
   Universe::heap()->print_tracing_info();
 
-  VTune::exit();
-
   { MutexLocker ml(BeforeExit_lock);
     _before_exit_status = BEFORE_EXIT_DONE;
     BeforeExit_lock->notify_all();
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -66,6 +66,7 @@
 
 
 jobject JNIHandles::make_global(Handle obj) {
+  assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
   jobject res = NULL;
   if (!obj.is_null()) {
     // ignore null handles
@@ -81,6 +82,7 @@
 
 
 jobject JNIHandles::make_weak_global(Handle obj) {
+  assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
   jobject res = NULL;
   if (!obj.is_null()) {
     // ignore null handles
--- a/hotspot/src/share/vm/runtime/os.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -886,6 +886,11 @@
         "%/lib/jsse.jar:"
         "%/lib/jce.jar:"
         "%/lib/charsets.jar:"
+
+        // ## TEMPORARY hack to keep the legacy launcher working when
+        // ## only the boot module is installed (cf. j.l.ClassLoader)
+        "%/lib/modules/jdk.boot.jar:"
+
         "%/classes";
     char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep);
     if (sysclasspath == NULL) return false;
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -779,7 +779,7 @@
 
   // Find bytecode
   Bytecode_invoke* bytecode = Bytecode_invoke_at(caller, bci);
-  bc = bytecode->adjusted_invoke_code();
+  bc = bytecode->java_code();
   int bytecode_index = bytecode->index();
 
   // Find receiver for non-static call
@@ -2251,7 +2251,6 @@
                  B->name(),
                  fingerprint->as_string(),
                  B->instructions_begin());
-    VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
     Forte::register_stub(blob_id, B->instructions_begin(), B->instructions_end());
 
     if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -132,7 +132,6 @@
   _cdesc->set_end(_cgen->assembler()->pc());
   assert(StubCodeDesc::_list == _cdesc, "expected order on list");
   _cgen->stub_epilog(_cdesc);
-  VTune::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
   Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
 
   if (JvmtiExport::should_post_dynamic_code_generated()) {
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -135,28 +135,32 @@
 static void test_arraycopy_func(address func, int alignment) {
   int v = 0xcc;
   int v2 = 0x11;
-  jlong lbuffer[2];
-  jlong lbuffer2[2];
-  address buffer  = (address) lbuffer;
-  address buffer2 = (address) lbuffer2;
+  jlong lbuffer[8];
+  jlong lbuffer2[8];
+  address fbuffer  = (address) lbuffer;
+  address fbuffer2 = (address) lbuffer2;
   unsigned int i;
   for (i = 0; i < sizeof(lbuffer); i++) {
-    buffer[i] = v; buffer2[i] = v2;
+    fbuffer[i] = v; fbuffer2[i] = v2;
   }
+  // C++ does not guarantee jlong[] array alignment to 8 bytes.
+  // Use middle of array to check that memory before it is not modified.
+  address buffer  = (address) round_to((intptr_t)&lbuffer[4], BytesPerLong);
+  address buffer2 = (address) round_to((intptr_t)&lbuffer2[4], BytesPerLong);
   // do an aligned copy
   ((arraycopy_fn)func)(buffer, buffer2, 0);
   for (i = 0; i < sizeof(lbuffer); i++) {
-    assert(buffer[i] == v && buffer2[i] == v2, "shouldn't have copied anything");
+    assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
   }
   // adjust destination alignment
   ((arraycopy_fn)func)(buffer, buffer2 + alignment, 0);
   for (i = 0; i < sizeof(lbuffer); i++) {
-    assert(buffer[i] == v && buffer2[i] == v2, "shouldn't have copied anything");
+    assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
   }
   // adjust source alignment
   ((arraycopy_fn)func)(buffer + alignment, buffer2, 0);
   for (i = 0; i < sizeof(lbuffer); i++) {
-    assert(buffer[i] == v && buffer2[i] == v2, "shouldn't have copied anything");
+    assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
   }
 }
 #endif
@@ -183,7 +187,7 @@
   test_arraycopy_func(arrayof_##type##_arraycopy(),          sizeof(HeapWord)); \
   test_arraycopy_func(arrayof_##type##_disjoint_arraycopy(), sizeof(HeapWord))
 
-  // Make sure all the arraycopy stubs properly handle zeros
+  // Make sure all the arraycopy stubs properly handle zero count
   TEST_ARRAYCOPY(jbyte);
   TEST_ARRAYCOPY(jshort);
   TEST_ARRAYCOPY(jint);
@@ -191,6 +195,25 @@
 
 #undef TEST_ARRAYCOPY
 
+#define TEST_COPYRTN(type) \
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_##type##s_atomic),  sizeof(type)); \
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::arrayof_conjoint_##type##s), (int)MAX2(sizeof(HeapWord), sizeof(type)))
+
+  // Make sure all the copy runtime routines properly handle zero count
+  TEST_COPYRTN(jbyte);
+  TEST_COPYRTN(jshort);
+  TEST_COPYRTN(jint);
+  TEST_COPYRTN(jlong);
+
+#undef TEST_COPYRTN
+
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::conjoint_words), sizeof(HeapWord));
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words), sizeof(HeapWord));
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::disjoint_words_atomic), sizeof(HeapWord));
+  // Aligned to BytesPerLong
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong));
+  test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong));
+
 #endif
 }
 
@@ -221,15 +244,13 @@
 #ifndef PRODUCT
   SharedRuntime::_jbyte_array_copy_ctr++;      // Slow-path byte array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
-  Copy::conjoint_bytes_atomic(src, dest, count);
+  Copy::conjoint_jbytes_atomic(src, dest, count);
 JRT_END
 
 JRT_LEAF(void, StubRoutines::jshort_copy(jshort* src, jshort* dest, size_t count))
 #ifndef PRODUCT
   SharedRuntime::_jshort_array_copy_ctr++;     // Slow-path short/char array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
   Copy::conjoint_jshorts_atomic(src, dest, count);
 JRT_END
 
@@ -237,7 +258,6 @@
 #ifndef PRODUCT
   SharedRuntime::_jint_array_copy_ctr++;       // Slow-path int/float array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
   Copy::conjoint_jints_atomic(src, dest, count);
 JRT_END
 
@@ -245,7 +265,6 @@
 #ifndef PRODUCT
   SharedRuntime::_jlong_array_copy_ctr++;      // Slow-path long/double array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
   Copy::conjoint_jlongs_atomic(src, dest, count);
 JRT_END
 
@@ -263,15 +282,13 @@
 #ifndef PRODUCT
   SharedRuntime::_jbyte_array_copy_ctr++;      // Slow-path byte array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
-  Copy::arrayof_conjoint_bytes(src, dest, count);
+  Copy::arrayof_conjoint_jbytes(src, dest, count);
 JRT_END
 
 JRT_LEAF(void, StubRoutines::arrayof_jshort_copy(HeapWord* src, HeapWord* dest, size_t count))
 #ifndef PRODUCT
   SharedRuntime::_jshort_array_copy_ctr++;     // Slow-path short/char array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
   Copy::arrayof_conjoint_jshorts(src, dest, count);
 JRT_END
 
@@ -279,7 +296,6 @@
 #ifndef PRODUCT
   SharedRuntime::_jint_array_copy_ctr++;       // Slow-path int/float array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
   Copy::arrayof_conjoint_jints(src, dest, count);
 JRT_END
 
@@ -287,7 +303,6 @@
 #ifndef PRODUCT
   SharedRuntime::_jlong_array_copy_ctr++;       // Slow-path int/float array copy
 #endif // !PRODUCT
-  assert(count != 0, "count should be non-zero");
   Copy::arrayof_conjoint_jlongs(src, dest, count);
 JRT_END
 
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -26,15 +26,16 @@
 # include "incls/_sweeper.cpp.incl"
 
 long      NMethodSweeper::_traversals = 0;   // No. of stack traversals performed
-CodeBlob* NMethodSweeper::_current = NULL;   // Current nmethod
-int       NMethodSweeper::_seen = 0 ;        // No. of blobs we have currently processed in current pass of CodeCache
-int       NMethodSweeper::_invocations = 0;  // No. of invocations left until we are completed with this pass
+nmethod*  NMethodSweeper::_current = NULL;   // Current nmethod
+int       NMethodSweeper::_seen = 0 ;        // No. of nmethods we have currently processed in current pass of CodeCache
+
+volatile int NMethodSweeper::_invocations = 0;   // No. of invocations left until we are completed with this pass
+volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
 
 jint      NMethodSweeper::_locked_seen = 0;
 jint      NMethodSweeper::_not_entrant_seen_on_stack = 0;
 bool      NMethodSweeper::_rescan = false;
 bool      NMethodSweeper::_do_sweep = false;
-jint      NMethodSweeper::_sweep_started = 0;
 bool      NMethodSweeper::_was_full = false;
 jint      NMethodSweeper::_advise_to_sweep = 0;
 jlong     NMethodSweeper::_last_was_full = 0;
@@ -108,23 +109,14 @@
         // code cache is filling up
         _last_was_full = os::javaTimeMillis();
 
-        if (PrintMethodFlushing) {
-          tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
-            CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-        }
-        if (LogCompilation && (xtty != NULL)) {
-          ttyLocker ttyl;
-          xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
-                           CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-          xtty->stamp();
-          xtty->end_elem();
-        }
+        log_sweep("restart_compiler");
       }
     }
   }
 }
 
 void NMethodSweeper::possibly_sweep() {
+  assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
   if ((!MethodFlushing) || (!_do_sweep)) return;
 
   if (_invocations > 0) {
@@ -133,32 +125,31 @@
     if (old != 0) {
       return;
     }
-    sweep_code_cache();
+    if (_invocations > 0) {
+      sweep_code_cache();
+      _invocations--;
+    }
+    _sweep_started = 0;
   }
-  _sweep_started = 0;
 }
 
 void NMethodSweeper::sweep_code_cache() {
 #ifdef ASSERT
   jlong sweep_start;
-  if(PrintMethodFlushing) {
+  if (PrintMethodFlushing) {
     sweep_start = os::javaTimeMillis();
   }
 #endif
   if (PrintMethodFlushing && Verbose) {
-    tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_blobs(), _invocations);
+    tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
   }
 
-  // We want to visit all nmethods after NmethodSweepFraction invocations.
-  // If invocation is 1 we do the rest
-  int todo = CodeCache::nof_blobs();
-  if (_invocations > 1) {
-    todo = (CodeCache::nof_blobs() - _seen) / _invocations;
-  }
-
-  // Compilers may check to sweep more often than stack scans happen,
-  // don't keep trying once it is all scanned
-  _invocations--;
+  // We want to visit all nmethods after NmethodSweepFraction
+  // invocations so divide the remaining number of nmethods by the
+  // remaining number of invocations.  This is only an estimate since
+  // the number of nmethods changes during the sweep so the final
+  // stage must iterate until it there are no more nmethods.
+  int todo = (CodeCache::nof_nmethods() - _seen) / _invocations;
 
   assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
   assert(!CodeCache_lock->owned_by_self(), "just checking");
@@ -166,26 +157,25 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
-    for(int i = 0; i < todo && _current != NULL; i++) {
+    // The last invocation iterates until there are no more nmethods
+    for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) {
 
-      // Since we will give up the CodeCache_lock, always skip ahead to an nmethod.
-      // Other blobs can be deleted by other threads
-      // Read next before we potentially delete current
-      CodeBlob* next = CodeCache::next_nmethod(_current);
+      // Since we will give up the CodeCache_lock, always skip ahead
+      // to the next nmethod.  Other blobs can be deleted by other
+      // threads but nmethods are only reclaimed by the sweeper.
+      nmethod* next = CodeCache::next_nmethod(_current);
 
       // Now ready to process nmethod and give up CodeCache_lock
       {
         MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-        process_nmethod((nmethod *)_current);
+        process_nmethod(_current);
       }
       _seen++;
       _current = next;
     }
+  }
 
-    // Skip forward to the next nmethod (if any). Code blobs other than nmethods
-    // can be freed async to us and make _current invalid while we sleep.
-    _current = CodeCache::next_nmethod(_current);
-  }
+  assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache");
 
   if (_current == NULL && !_rescan && (_locked_seen || _not_entrant_seen_on_stack)) {
     // we've completed a scan without making progress but there were
@@ -205,6 +195,10 @@
     tty->print_cr("### sweeper:      sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
   }
 #endif
+
+  if (_invocations == 1) {
+    log_sweep("finished");
+  }
 }
 
 
@@ -227,7 +221,7 @@
   if (nm->is_zombie()) {
     // If it is first time, we see nmethod then we mark it. Otherwise,
     // we reclame it. When we have seen a zombie method twice, we know that
-    // there are no inline caches that referes to it.
+    // there are no inline caches that refer to it.
     if (nm->is_marked_for_reclamation()) {
       assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
       if (PrintMethodFlushing && Verbose) {
@@ -324,16 +318,8 @@
     jlong curr_interval = now - _last_was_full;
     if (curr_interval < max_interval) {
       _rescan = true;
-      if (PrintMethodFlushing) {
-        tty->print_cr("### handle full too often, turning off compiler");
-      }
-      if (LogCompilation && (xtty != NULL)) {
-        ttyLocker ttyl;
-        xtty->begin_elem("disable_compiler flushing_interval='" UINT64_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
-                         curr_interval/1000, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-        xtty->stamp();
-        xtty->end_elem();
-      }
+      log_sweep("disable_compiler", "flushing_interval='" UINT64_FORMAT "'",
+                           curr_interval/1000);
       return;
     }
   }
@@ -353,17 +339,7 @@
 
   if ((!was_full()) && (is_full)) {
     if (!CodeCache::needs_flushing()) {
-      if (PrintMethodFlushing) {
-        tty->print_cr("### sweeper: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes, restarting compiler",
-          CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-      }
-      if (LogCompilation && (xtty != NULL)) {
-        ttyLocker ttyl;
-        xtty->begin_elem("restart_compiler live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
-                         CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-        xtty->stamp();
-        xtty->end_elem();
-      }
+      log_sweep("restart_compiler");
       CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation);
       return;
     }
@@ -372,17 +348,7 @@
   // Traverse the code cache trying to dump the oldest nmethods
   uint curr_max_comp_id = CompileBroker::get_compilation_id();
   uint flush_target = ((curr_max_comp_id - _highest_marked) >> 1) + _highest_marked;
-  if (PrintMethodFlushing && Verbose) {
-    tty->print_cr("### Cleaning code cache: Live blobs:" UINT32_FORMAT "/Free code cache:" SIZE_FORMAT " bytes",
-        CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-  }
-  if (LogCompilation && (xtty != NULL)) {
-    ttyLocker ttyl;
-    xtty->begin_elem("start_cleaning_code_cache live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
-                      CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-    xtty->stamp();
-    xtty->end_elem();
-  }
+  log_sweep("start_cleaning");
 
   nmethod* nm = CodeCache::alive_nmethod(CodeCache::first());
   jint disconnected = 0;
@@ -415,13 +381,9 @@
     nm = CodeCache::alive_nmethod(CodeCache::next(nm));
   }
 
-  if (LogCompilation && (xtty != NULL)) {
-    ttyLocker ttyl;
-    xtty->begin_elem("stop_cleaning_code_cache disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "' live_blobs='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
-                      disconnected, made_not_entrant, CodeCache::nof_blobs(), CodeCache::unallocated_capacity());
-    xtty->stamp();
-    xtty->end_elem();
-  }
+  log_sweep("stop_cleaning",
+                       "disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "'",
+                       disconnected, made_not_entrant);
 
   // Shut off compiler. Sweeper will start over with a new stack scan and
   // traversal cycle and turn it back on if it clears enough space.
@@ -439,3 +401,38 @@
   }
 #endif
 }
+
+
+// Print out some state information about the current sweep and the
+// state of the code cache if it's requested.
+void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
+  if (PrintMethodFlushing) {
+    ttyLocker ttyl;
+    tty->print("### sweeper: %s ", msg);
+    if (format != NULL) {
+      va_list ap;
+      va_start(ap, format);
+      tty->vprint(format, ap);
+      va_end(ap);
+    }
+    tty->print_cr(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+                  " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+                  CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+  }
+
+  if (LogCompilation && (xtty != NULL)) {
+    ttyLocker ttyl;
+    xtty->begin_elem("sweeper state='%s' traversals='" INTX_FORMAT "' ", msg, (intx)traversal_count());
+    if (format != NULL) {
+      va_list ap;
+      va_start(ap, format);
+      xtty->vprint(format, ap);
+      va_end(ap);
+    }
+    xtty->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
+                " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
+                CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+    xtty->stamp();
+    xtty->end_elem();
+  }
+}
--- a/hotspot/src/share/vm/runtime/sweeper.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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,14 +29,15 @@
 
 class NMethodSweeper : public AllStatic {
   static long      _traversals;   // Stack traversal count
-  static CodeBlob* _current;      // Current nmethod
+  static nmethod*  _current;      // Current nmethod
   static int       _seen;         // Nof. nmethod we have currently processed in current pass of CodeCache
-  static int       _invocations;  // No. of invocations left until we are completed with this pass
+
+  static volatile int      _invocations;   // No. of invocations left until we are completed with this pass
+  static volatile int      _sweep_started; // Flag to control conc sweeper
 
   static bool      _rescan;          // Indicates that we should do a full rescan of the
                                      // of the code cache looking for work to do.
   static bool      _do_sweep;        // Flag to skip the conc sweep if no stack scan happened
-  static jint      _sweep_started;   // Flag to control conc sweeper
   static int       _locked_seen;     // Number of locked nmethods encountered during the scan
   static int       _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack
 
@@ -47,6 +48,9 @@
   static long      _was_full_traversal;   // trav number at last emergency unloading
 
   static void process_nmethod(nmethod *nm);
+
+  static void log_sweep(const char* msg, const char* format = NULL, ...);
+
  public:
   static long traversal_count() { return _traversals; }
 
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -747,6 +747,8 @@
 
 ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
 ObjectMonitor * volatile ObjectSynchronizer::gFreeList  = NULL ;
+ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList  = NULL ;
+int ObjectSynchronizer::gOmInUseCount = 0;
 static volatile intptr_t ListLock = 0 ;      // protects global monitor free-list cache
 static volatile int MonitorFreeCount  = 0 ;      // # on gFreeList
 static volatile int MonitorPopulation = 0 ;      // # Extant -- in circulation
@@ -826,6 +828,22 @@
     }
   }
 }
+/* Too slow for general assert or debug
+void ObjectSynchronizer::verifyInUse (Thread *Self) {
+   ObjectMonitor* mid;
+   int inusetally = 0;
+   for (mid = Self->omInUseList; mid != NULL; mid = mid->FreeNext) {
+     inusetally ++;
+   }
+   assert(inusetally == Self->omInUseCount, "inuse count off");
+
+   int freetally = 0;
+   for (mid = Self->omFreeList; mid != NULL; mid = mid->FreeNext) {
+     freetally ++;
+   }
+   assert(freetally == Self->omFreeCount, "free count off");
+}
+*/
 
 ObjectMonitor * ATTR ObjectSynchronizer::omAlloc (Thread * Self) {
     // A large MAXPRIVATE value reduces both list lock contention
@@ -853,6 +871,9 @@
              m->FreeNext = Self->omInUseList;
              Self->omInUseList = m;
              Self->omInUseCount ++;
+             // verifyInUse(Self);
+           } else {
+             m->FreeNext = NULL;
            }
            return m ;
         }
@@ -874,13 +895,12 @@
                 guarantee (take->object() == NULL, "invariant") ;
                 guarantee (!take->is_busy(), "invariant") ;
                 take->Recycle() ;
-                omRelease (Self, take) ;
+                omRelease (Self, take, false) ;
             }
             Thread::muxRelease (&ListLock) ;
             Self->omFreeProvision += 1 + (Self->omFreeProvision/2) ;
             if (Self->omFreeProvision > MAXPRIVATE ) Self->omFreeProvision = MAXPRIVATE ;
             TEVENT (omFirst - reprovision) ;
-            continue ;
 
             const int mx = MonitorBound ;
             if (mx > 0 && (MonitorPopulation-MonitorFreeCount) > mx) {
@@ -961,11 +981,34 @@
 // That is, *not* one-at-a-time.
 
 
-void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m) {
+void ObjectSynchronizer::omRelease (Thread * Self, ObjectMonitor * m, bool fromPerThreadAlloc) {
     guarantee (m->object() == NULL, "invariant") ;
-    m->FreeNext = Self->omFreeList ;
-    Self->omFreeList = m ;
-    Self->omFreeCount ++ ;
+
+    // Remove from omInUseList
+    if (MonitorInUseLists && fromPerThreadAlloc) {
+      ObjectMonitor* curmidinuse = NULL;
+      for (ObjectMonitor* mid = Self->omInUseList; mid != NULL; ) {
+       if (m == mid) {
+         // extract from per-thread in-use-list
+         if (mid == Self->omInUseList) {
+           Self->omInUseList = mid->FreeNext;
+         } else if (curmidinuse != NULL) {
+           curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+         }
+         Self->omInUseCount --;
+         // verifyInUse(Self);
+         break;
+       } else {
+         curmidinuse = mid;
+         mid = mid->FreeNext;
+      }
+    }
+  }
+
+  // FreeNext is used for both onInUseList and omFreeList, so clear old before setting new
+  m->FreeNext = Self->omFreeList ;
+  Self->omFreeList = m ;
+  Self->omFreeCount ++ ;
 }
 
 // Return the monitors of a moribund thread's local free list to
@@ -975,6 +1018,10 @@
 // consecutive STW safepoints.  Relatedly, we might decay
 // omFreeProvision at STW safepoints.
 //
+// Also return the monitors of a moribund thread"s omInUseList to
+// a global gOmInUseList under the global list lock so these
+// will continue to be scanned.
+//
 // We currently call omFlush() from the Thread:: dtor _after the thread
 // has been excised from the thread list and is no longer a mutator.
 // That means that omFlush() can run concurrently with a safepoint and
@@ -987,24 +1034,50 @@
 void ObjectSynchronizer::omFlush (Thread * Self) {
     ObjectMonitor * List = Self->omFreeList ;  // Null-terminated SLL
     Self->omFreeList = NULL ;
-    if (List == NULL) return ;
     ObjectMonitor * Tail = NULL ;
-    ObjectMonitor * s ;
     int Tally = 0;
-    for (s = List ; s != NULL ; s = s->FreeNext) {
-        Tally ++ ;
-        Tail = s ;
-        guarantee (s->object() == NULL, "invariant") ;
-        guarantee (!s->is_busy(), "invariant") ;
-        s->set_owner (NULL) ;   // redundant but good hygiene
-        TEVENT (omFlush - Move one) ;
+    if (List != NULL) {
+      ObjectMonitor * s ;
+      for (s = List ; s != NULL ; s = s->FreeNext) {
+          Tally ++ ;
+          Tail = s ;
+          guarantee (s->object() == NULL, "invariant") ;
+          guarantee (!s->is_busy(), "invariant") ;
+          s->set_owner (NULL) ;   // redundant but good hygiene
+          TEVENT (omFlush - Move one) ;
+      }
+      guarantee (Tail != NULL && List != NULL, "invariant") ;
     }
 
-    guarantee (Tail != NULL && List != NULL, "invariant") ;
+    ObjectMonitor * InUseList = Self->omInUseList;
+    ObjectMonitor * InUseTail = NULL ;
+    int InUseTally = 0;
+    if (InUseList != NULL) {
+      Self->omInUseList = NULL;
+      ObjectMonitor *curom;
+      for (curom = InUseList; curom != NULL; curom = curom->FreeNext) {
+        InUseTail = curom;
+        InUseTally++;
+      }
+// TODO debug
+      assert(Self->omInUseCount == InUseTally, "inuse count off");
+      Self->omInUseCount = 0;
+      guarantee (InUseTail != NULL && InUseList != NULL, "invariant");
+    }
+
     Thread::muxAcquire (&ListLock, "omFlush") ;
-    Tail->FreeNext = gFreeList ;
-    gFreeList = List ;
-    MonitorFreeCount += Tally;
+    if (Tail != NULL) {
+      Tail->FreeNext = gFreeList ;
+      gFreeList = List ;
+      MonitorFreeCount += Tally;
+    }
+
+    if (InUseTail != NULL) {
+      InUseTail->FreeNext = gOmInUseList;
+      gOmInUseList = InUseList;
+      gOmInUseCount += InUseTally;
+    }
+
     Thread::muxRelease (&ListLock) ;
     TEVENT (omFlush) ;
 }
@@ -1166,7 +1239,6 @@
           // We do this before the CAS in order to minimize the length of time
           // in which INFLATING appears in the mark.
           m->Recycle();
-          m->FreeNext      = NULL ;
           m->_Responsible  = NULL ;
           m->OwnerIsThread = 0 ;
           m->_recursions   = 0 ;
@@ -1174,7 +1246,7 @@
 
           markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
           if (cmp != mark) {
-             omRelease (Self, m) ;
+             omRelease (Self, m, true) ;
              continue ;       // Interference -- just retry
           }
 
@@ -1262,7 +1334,6 @@
       m->set_object(object);
       m->OwnerIsThread = 1 ;
       m->_recursions   = 0 ;
-      m->FreeNext      = NULL ;
       m->_Responsible  = NULL ;
       m->_SpinDuration = Knob_SpinLimit ;       // consider: keep metastats by type/class
 
@@ -1271,7 +1342,7 @@
           m->set_owner  (NULL) ;
           m->OwnerIsThread = 0 ;
           m->Recycle() ;
-          omRelease (Self, m) ;
+          omRelease (Self, m, true) ;
           m = NULL ;
           continue ;
           // interference - the markword changed - just retry.
@@ -1852,6 +1923,10 @@
 // only scans the per-thread inuse lists. omAlloc() puts all
 // assigned monitors on the per-thread list. deflate_idle_monitors()
 // returns the non-busy monitors to the global free list.
+// When a thread dies, omFlush() adds the list of active monitors for
+// that thread to a global gOmInUseList acquiring the
+// global list lock. deflate_idle_monitors() acquires the global
+// list lock to scan for non-busy monitors to the global free list.
 // An alternative could have used a single global inuse list. The
 // downside would have been the additional cost of acquiring the global list lock
 // for every omAlloc().
@@ -1904,6 +1979,7 @@
      if (*FreeHeadp == NULL) *FreeHeadp = mid;
      if (*FreeTailp != NULL) {
        ObjectMonitor * prevtail = *FreeTailp;
+       assert(prevtail->FreeNext == NULL, "cleaned up deflated?"); // TODO KK
        prevtail->FreeNext = mid;
       }
      *FreeTailp = mid;
@@ -1912,6 +1988,39 @@
   return deflated;
 }
 
+// Caller acquires ListLock
+int ObjectSynchronizer::walk_monitor_list(ObjectMonitor** listheadp,
+                                          ObjectMonitor** FreeHeadp, ObjectMonitor** FreeTailp) {
+  ObjectMonitor* mid;
+  ObjectMonitor* next;
+  ObjectMonitor* curmidinuse = NULL;
+  int deflatedcount = 0;
+
+  for (mid = *listheadp; mid != NULL; ) {
+     oop obj = (oop) mid->object();
+     bool deflated = false;
+     if (obj != NULL) {
+       deflated = deflate_monitor(mid, obj, FreeHeadp, FreeTailp);
+     }
+     if (deflated) {
+       // extract from per-thread in-use-list
+       if (mid == *listheadp) {
+         *listheadp = mid->FreeNext;
+       } else if (curmidinuse != NULL) {
+         curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+       }
+       next = mid->FreeNext;
+       mid->FreeNext = NULL;  // This mid is current tail in the FreeHead list
+       mid = next;
+       deflatedcount++;
+     } else {
+       curmidinuse = mid;
+       mid = mid->FreeNext;
+    }
+  }
+  return deflatedcount;
+}
+
 void ObjectSynchronizer::deflate_idle_monitors() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   int nInuse = 0 ;              // currently associated with objects
@@ -1929,36 +2038,25 @@
   Thread::muxAcquire (&ListLock, "scavenge - return") ;
 
   if (MonitorInUseLists) {
-    ObjectMonitor* mid;
-    ObjectMonitor* next;
-    ObjectMonitor* curmidinuse;
+    int inUse = 0;
     for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
-      curmidinuse = NULL;
-      for (mid = cur->omInUseList; mid != NULL; ) {
-        oop obj = (oop) mid->object();
-        deflated = false;
-        if (obj != NULL) {
-          deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);
-        }
-        if (deflated) {
-          // extract from per-thread in-use-list
-          if (mid == cur->omInUseList) {
-            cur->omInUseList = mid->FreeNext;
-          } else if (curmidinuse != NULL) {
-            curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
-          }
-          next = mid->FreeNext;
-          mid->FreeNext = NULL;  // This mid is current tail in the FreeHead list
-          mid = next;
-          cur->omInUseCount--;
-          nScavenged ++ ;
-        } else {
-          curmidinuse = mid;
-          mid = mid->FreeNext;
-          nInuse ++;
-        }
+      nInCirculation+= cur->omInUseCount;
+      int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);
+      cur->omInUseCount-= deflatedcount;
+      // verifyInUse(cur);
+      nScavenged += deflatedcount;
+      nInuse += cur->omInUseCount;
      }
-   }
+
+   // For moribund threads, scan gOmInUseList
+   if (gOmInUseList) {
+     nInCirculation += gOmInUseCount;
+     int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);
+     gOmInUseCount-= deflatedcount;
+     nScavenged += deflatedcount;
+     nInuse += gOmInUseCount;
+    }
+
   } else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
   // Iterate over all extant monitors - Scavenge all idle monitors.
     assert(block->object() == CHAINMARKER, "must be a block header");
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -122,8 +122,9 @@
   static void reenter            (Handle obj, intptr_t recursion, TRAPS);
 
   // thread-specific and global objectMonitor free list accessors
+//  static void verifyInUse (Thread * Self) ; too slow for general assert/debug
   static ObjectMonitor * omAlloc (Thread * Self) ;
-  static void omRelease (Thread * Self, ObjectMonitor * m) ;
+  static void omRelease (Thread * Self, ObjectMonitor * m, bool FromPerThreadAlloc) ;
   static void omFlush   (Thread * Self) ;
 
   // Inflate light weight monitor to heavy weight monitor
@@ -150,6 +151,9 @@
   // Basically we deflate all monitors that are not busy.
   // An adaptive profile-based deflation policy could be used if needed
   static void deflate_idle_monitors();
+  static int walk_monitor_list(ObjectMonitor** listheadp,
+                               ObjectMonitor** FreeHeadp,
+                               ObjectMonitor** FreeTailp);
   static bool deflate_monitor(ObjectMonitor* mid, oop obj, ObjectMonitor** FreeHeadp,
                               ObjectMonitor** FreeTailp);
   static void oops_do(OopClosure* f);
@@ -163,6 +167,8 @@
   enum { _BLOCKSIZE = 128 };
   static ObjectMonitor* gBlockList;
   static ObjectMonitor * volatile gFreeList;
+  static ObjectMonitor * volatile gOmInUseList; // for moribund thread, so monitors they inflated still get scanned
+  static int gOmInUseCount;
 
  public:
   static void Initialize () ;
--- a/hotspot/src/share/vm/runtime/thread.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -2700,7 +2700,7 @@
   if (in_bytes(size_in_bytes) != 0) {
     _popframe_preserved_args = NEW_C_HEAP_ARRAY(char, in_bytes(size_in_bytes));
     _popframe_preserved_args_size = in_bytes(size_in_bytes);
-    Copy::conjoint_bytes(start, _popframe_preserved_args, _popframe_preserved_args_size);
+    Copy::conjoint_jbytes(start, _popframe_preserved_args, _popframe_preserved_args_size);
   }
 }
 
--- a/hotspot/src/share/vm/runtime/thread.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -270,6 +270,7 @@
   static void interrupt(Thread* thr);
   static bool is_interrupted(Thread* thr, bool clear_interrupted);
 
+  ObjectMonitor** omInUseList_addr()             { return (ObjectMonitor **)&omInUseList; }
   Monitor* SR_lock() const                       { return _SR_lock; }
 
   bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -355,9 +355,9 @@
       } else {
         base = iframe()->interpreter_frame_expression_stack();
       }
-      Copy::conjoint_bytes(saved_args,
-                           base,
-                           popframe_preserved_args_size_in_bytes);
+      Copy::conjoint_jbytes(saved_args,
+                            base,
+                            popframe_preserved_args_size_in_bytes);
       thread->popframe_free_preserved_args();
     }
   }
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -111,6 +111,35 @@
   return result;
 }
 
+// Helper method.
+static bool failed_to_reserve_as_requested(char* base, char* requested_address,
+                                           const size_t size, bool special)
+{
+  if (base == requested_address || requested_address == NULL)
+    return false; // did not fail
+
+  if (base != NULL) {
+    // Different reserve address may be acceptable in other cases
+    // but for compressed oops heap should be at requested address.
+    assert(UseCompressedOops, "currently requested address used only for compressed oops");
+    if (PrintCompressedOopsMode) {
+      tty->cr();
+      tty->print_cr("Reserved memory at not requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
+    }
+    // OS ignored requested address. Try different address.
+    if (special) {
+      if (!os::release_memory_special(base, size)) {
+        fatal("os::release_memory_special failed");
+      }
+    } else {
+      if (!os::release_memory(base, size)) {
+        fatal("os::release_memory failed");
+      }
+    }
+  }
+  return true;
+}
+
 ReservedSpace::ReservedSpace(const size_t prefix_size,
                              const size_t prefix_align,
                              const size_t suffix_size,
@@ -129,6 +158,10 @@
   assert((suffix_align & prefix_align - 1) == 0,
     "suffix_align not divisible by prefix_align");
 
+  // Assert that if noaccess_prefix is used, it is the same as prefix_align.
+  assert(noaccess_prefix == 0 ||
+         noaccess_prefix == prefix_align, "noaccess prefix wrong");
+
   // Add in noaccess_prefix to prefix_size;
   const size_t adjusted_prefix_size = prefix_size + noaccess_prefix;
   const size_t size = adjusted_prefix_size + suffix_size;
@@ -150,15 +183,16 @@
   _noaccess_prefix = 0;
   _executable = false;
 
-  // Assert that if noaccess_prefix is used, it is the same as prefix_align.
-  assert(noaccess_prefix == 0 ||
-         noaccess_prefix == prefix_align, "noaccess prefix wrong");
-
   // Optimistically try to reserve the exact size needed.
   char* addr;
   if (requested_address != 0) {
-    addr = os::attempt_reserve_memory_at(size,
-                                         requested_address-noaccess_prefix);
+    requested_address -= noaccess_prefix; // adjust address
+    assert(requested_address != NULL, "huge noaccess prefix?");
+    addr = os::attempt_reserve_memory_at(size, requested_address);
+    if (failed_to_reserve_as_requested(addr, requested_address, size, false)) {
+      // OS ignored requested address. Try different address.
+      addr = NULL;
+    }
   } else {
     addr = os::reserve_memory(size, NULL, prefix_align);
   }
@@ -222,11 +256,20 @@
   bool special = large && !os::can_commit_large_page_memory();
   char* base = NULL;
 
+  if (requested_address != 0) {
+    requested_address -= noaccess_prefix; // adjust requested address
+    assert(requested_address != NULL, "huge noaccess prefix?");
+  }
+
   if (special) {
 
     base = os::reserve_memory_special(size, requested_address, executable);
 
     if (base != NULL) {
+      if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
+        // OS ignored requested address. Try different address.
+        return;
+      }
       // Check alignment constraints
       if (alignment > 0) {
         assert((uintptr_t) base % alignment == 0,
@@ -235,6 +278,13 @@
       _special = true;
     } else {
       // failed; try to reserve regular memory below
+      if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
+                            !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
+        if (PrintCompressedOopsMode) {
+          tty->cr();
+          tty->print_cr("Reserve regular memory without large pages.");
+        }
+      }
     }
   }
 
@@ -248,8 +298,11 @@
     // important.  If available space is not detected, return NULL.
 
     if (requested_address != 0) {
-      base = os::attempt_reserve_memory_at(size,
-                                           requested_address-noaccess_prefix);
+      base = os::attempt_reserve_memory_at(size, requested_address);
+      if (failed_to_reserve_as_requested(base, requested_address, size, false)) {
+        // OS ignored requested address. Try different address.
+        base = NULL;
+      }
     } else {
       base = os::reserve_memory(size, NULL, alignment);
     }
@@ -365,7 +418,12 @@
 }
 
 void ReservedSpace::protect_noaccess_prefix(const size_t size) {
-  // If there is noaccess prefix, return.
+  assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL &&
+                                      (size_t(_base + _size) > OopEncodingHeapMax) &&
+                                      Universe::narrow_oop_use_implicit_null_checks()),
+         "noaccess_prefix should be used only with non zero based compressed oops");
+
+  // If there is no noaccess prefix, return.
   if (_noaccess_prefix == 0) return;
 
   assert(_noaccess_prefix >= (size_t)os::vm_page_size(),
@@ -377,6 +435,10 @@
                           _special)) {
     fatal("cannot protect protection page");
   }
+  if (PrintCompressedOopsMode) {
+    tty->cr();
+    tty->print_cr("Protected page at the reserved heap base: " PTR_FORMAT " / " INTX_FORMAT " bytes", _base, _noaccess_prefix);
+  }
 
   _base += _noaccess_prefix;
   _size -= _noaccess_prefix;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -614,7 +614,6 @@
   /* NMethods (NOTE: incomplete, but only a little) */                                                                               \
   /**************************************************/                                                                               \
                                                                                                                                      \
-     static_field(nmethod,             _zombie_instruction_size,                      int)                                   \
   nonstatic_field(nmethod,             _method,                                       methodOop)                             \
   nonstatic_field(nmethod,             _entry_bci,                                    int)                                   \
   nonstatic_field(nmethod,             _osr_link,                                     nmethod*)                              \
--- a/hotspot/src/share/vm/runtime/vtune.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.
- *
- */
-
-// Interface to Intel's VTune profiler.
-
-class VTune : AllStatic {
- public:
-   static void create_nmethod(nmethod* nm);      // register newly created nmethod
-   static void delete_nmethod(nmethod* nm);      // unregister nmethod before discarding it
-
-   static void register_stub(const char* name, address start, address end);
-                                                 // register internal VM stub
-   static void start_GC();                       // start/end of GC or scavenge
-   static void end_GC();
-
-   static void start_class_load();               // start/end of class loading
-   static void end_class_load();
-
-   static void exit();                           // VM exit
-};
-
-
-// helper objects
-class VTuneGCMarker : StackObj {
- public:
-   VTuneGCMarker() { VTune::start_GC(); }
-  ~VTuneGCMarker() { VTune::end_GC(); }
-};
-
-class VTuneClassLoadMarker : StackObj {
- public:
-   VTuneClassLoadMarker() { VTune::start_class_load(); }
-  ~VTuneClassLoadMarker() { VTune::end_class_load(); }
-};
--- a/hotspot/src/share/vm/utilities/constantTag.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/utilities/constantTag.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -28,56 +28,85 @@
 #ifndef PRODUCT
 
 void constantTag::print_on(outputStream* st) const {
+  st->print(internal_name());
+}
+
+#endif // PRODUCT
+
+BasicType constantTag::basic_type() const {
   switch (_tag) {
-    case JVM_CONSTANT_Class :
-      st->print("Class");
-      break;
-    case JVM_CONSTANT_Fieldref :
-      st->print("Field");
-      break;
-    case JVM_CONSTANT_Methodref :
-      st->print("Method");
-      break;
-    case JVM_CONSTANT_InterfaceMethodref :
-      st->print("InterfaceMethod");
-      break;
-    case JVM_CONSTANT_String :
-      st->print("String");
-      break;
     case JVM_CONSTANT_Integer :
-      st->print("Integer");
-      break;
+      return T_INT;
     case JVM_CONSTANT_Float :
-      st->print("Float");
-      break;
+      return T_FLOAT;
     case JVM_CONSTANT_Long :
-      st->print("Long");
-      break;
+      return T_LONG;
     case JVM_CONSTANT_Double :
-      st->print("Double");
-      break;
-    case JVM_CONSTANT_NameAndType :
-      st->print("NameAndType");
-      break;
-    case JVM_CONSTANT_Utf8 :
-      st->print("Utf8");
-      break;
+      return T_DOUBLE;
+
+    case JVM_CONSTANT_Class :
+    case JVM_CONSTANT_String :
     case JVM_CONSTANT_UnresolvedClass :
-      st->print("Unresolved class");
-      break;
+    case JVM_CONSTANT_UnresolvedClassInError :
     case JVM_CONSTANT_ClassIndex :
-      st->print("Unresolved class index");
-      break;
     case JVM_CONSTANT_UnresolvedString :
-      st->print("Unresolved string");
-      break;
     case JVM_CONSTANT_StringIndex :
-      st->print("Unresolved string index");
-      break;
+    case JVM_CONSTANT_MethodHandle :
+    case JVM_CONSTANT_MethodType :
+    case JVM_CONSTANT_Object :
+      return T_OBJECT;
     default:
       ShouldNotReachHere();
-      break;
+      return T_ILLEGAL;
   }
 }
 
-#endif // PRODUCT
+
+
+const char* constantTag::internal_name() const {
+  switch (_tag) {
+    case JVM_CONSTANT_Invalid :
+      return "Invalid index";
+    case JVM_CONSTANT_Class :
+      return "Class";
+    case JVM_CONSTANT_Fieldref :
+      return "Field";
+    case JVM_CONSTANT_Methodref :
+      return "Method";
+    case JVM_CONSTANT_InterfaceMethodref :
+      return "InterfaceMethod";
+    case JVM_CONSTANT_String :
+      return "String";
+    case JVM_CONSTANT_Integer :
+      return "Integer";
+    case JVM_CONSTANT_Float :
+      return "Float";
+    case JVM_CONSTANT_Long :
+      return "Long";
+    case JVM_CONSTANT_Double :
+      return "Double";
+    case JVM_CONSTANT_NameAndType :
+      return "NameAndType";
+    case JVM_CONSTANT_MethodHandle :
+      return "MethodHandle";
+    case JVM_CONSTANT_MethodType :
+      return "MethodType";
+    case JVM_CONSTANT_Object :
+      return "Object";
+    case JVM_CONSTANT_Utf8 :
+      return "Utf8";
+    case JVM_CONSTANT_UnresolvedClass :
+      return "Unresolved Class";
+    case JVM_CONSTANT_UnresolvedClassInError :
+      return "Unresolved Class Error";
+    case JVM_CONSTANT_ClassIndex :
+      return "Unresolved Class Index";
+    case JVM_CONSTANT_UnresolvedString :
+      return "Unresolved String";
+    case JVM_CONSTANT_StringIndex :
+      return "Unresolved String Index";
+    default:
+      ShouldNotReachHere();
+      return "Illegal";
+  }
+}
--- a/hotspot/src/share/vm/utilities/constantTag.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/utilities/constantTag.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -78,13 +78,24 @@
   bool is_field_or_method() const   { return is_field() || is_method() || is_interface_method(); }
   bool is_symbol() const            { return is_utf8(); }
 
+  bool is_method_type() const              { return _tag == JVM_CONSTANT_MethodType; }
+  bool is_method_handle() const            { return _tag == JVM_CONSTANT_MethodHandle; }
+
+  constantTag() {
+    _tag = JVM_CONSTANT_Invalid;
+  }
   constantTag(jbyte tag) {
     assert((tag >= 0 && tag <= JVM_CONSTANT_NameAndType) ||
+           (tag >= JVM_CONSTANT_MethodHandle && tag <= JVM_CONSTANT_MethodType) ||
            (tag >= JVM_CONSTANT_InternalMin && tag <= JVM_CONSTANT_InternalMax), "Invalid constant tag");
     _tag = tag;
   }
 
   jbyte value()                      { return _tag; }
 
+  BasicType basic_type() const;        // if used with ldc, what kind of value gets pushed?
+
+  const char* internal_name() const;  // for error reporting
+
   void print_on(outputStream* st) const PRODUCT_RETURN;
 };
--- a/hotspot/src/share/vm/utilities/copy.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/utilities/copy.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -48,7 +48,7 @@
     Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));
   } else {
     // Not aligned, so no need to be atomic.
-    Copy::conjoint_bytes((void*) src, (void*) dst, size);
+    Copy::conjoint_jbytes((void*) src, (void*) dst, size);
   }
 }
 
--- a/hotspot/src/share/vm/utilities/copy.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/utilities/copy.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -73,6 +73,9 @@
   // whole alignment units.  E.g., if BytesPerLong is 2x word alignment, an odd
   // count may copy an extra word.  In the arrayof case, we are allowed to copy
   // only the number of copy units specified.
+  //
+  // All callees check count for 0.
+  //
 
   // HeapWords
 
@@ -99,7 +102,6 @@
   // Object-aligned words,  conjoint, not atomic on each word
   static void aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
     assert_params_aligned(from, to);
-    assert_non_zero(count);
     pd_aligned_conjoint_words(from, to, count);
   }
 
@@ -107,49 +109,42 @@
   static void aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
     assert_params_aligned(from, to);
     assert_disjoint(from, to, count);
-    assert_non_zero(count);
     pd_aligned_disjoint_words(from, to, count);
   }
 
   // bytes, jshorts, jints, jlongs, oops
 
   // bytes,                 conjoint, not atomic on each byte (not that it matters)
-  static void conjoint_bytes(void* from, void* to, size_t count) {
-    assert_non_zero(count);
+  static void conjoint_jbytes(void* from, void* to, size_t count) {
     pd_conjoint_bytes(from, to, count);
   }
 
   // bytes,                 conjoint, atomic on each byte (not that it matters)
-  static void conjoint_bytes_atomic(void* from, void* to, size_t count) {
-    assert_non_zero(count);
+  static void conjoint_jbytes_atomic(void* from, void* to, size_t count) {
     pd_conjoint_bytes(from, to, count);
   }
 
   // jshorts,               conjoint, atomic on each jshort
   static void conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerShort);
-    assert_non_zero(count);
     pd_conjoint_jshorts_atomic(from, to, count);
   }
 
   // jints,                 conjoint, atomic on each jint
   static void conjoint_jints_atomic(jint* from, jint* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerInt);
-    assert_non_zero(count);
     pd_conjoint_jints_atomic(from, to, count);
   }
 
   // jlongs,                conjoint, atomic on each jlong
   static void conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerLong);
-    assert_non_zero(count);
     pd_conjoint_jlongs_atomic(from, to, count);
   }
 
   // oops,                  conjoint, atomic on each oop
   static void conjoint_oops_atomic(oop* from, oop* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerHeapOop);
-    assert_non_zero(count);
     pd_conjoint_oops_atomic(from, to, count);
   }
 
@@ -157,7 +152,6 @@
   static void conjoint_oops_atomic(narrowOop* from, narrowOop* to, size_t count) {
     assert(sizeof(narrowOop) == sizeof(jint), "this cast is wrong");
     assert_params_ok(from, to, LogBytesPerInt);
-    assert_non_zero(count);
     pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
   }
 
@@ -168,36 +162,31 @@
   static void conjoint_memory_atomic(void* from, void* to, size_t size);
 
   // bytes,                 conjoint array, atomic on each byte (not that it matters)
-  static void arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
-    assert_non_zero(count);
+  static void arrayof_conjoint_jbytes(HeapWord* from, HeapWord* to, size_t count) {
     pd_arrayof_conjoint_bytes(from, to, count);
   }
 
   // jshorts,               conjoint array, atomic on each jshort
   static void arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerShort);
-    assert_non_zero(count);
     pd_arrayof_conjoint_jshorts(from, to, count);
   }
 
   // jints,                 conjoint array, atomic on each jint
   static void arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerInt);
-    assert_non_zero(count);
     pd_arrayof_conjoint_jints(from, to, count);
   }
 
   // jlongs,                conjoint array, atomic on each jlong
   static void arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerLong);
-    assert_non_zero(count);
     pd_arrayof_conjoint_jlongs(from, to, count);
   }
 
   // oops,                  conjoint array, atomic on each oop
   static void arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
     assert_params_ok(from, to, LogBytesPerHeapOop);
-    assert_non_zero(count);
     pd_arrayof_conjoint_oops(from, to, count);
   }
 
@@ -319,14 +308,6 @@
 #endif
   }
 
-  static void assert_non_zero(size_t count) {
-#ifdef ASSERT
-    if (count == 0) {
-      basic_fatal("count must be non-zero");
-    }
-#endif
-  }
-
   static void assert_byte_count_ok(size_t byte_count, size_t unit_size) {
 #ifdef ASSERT
     if ((size_t)round_to(byte_count, unit_size) != byte_count) {
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -182,73 +182,3 @@
     _index < objArrayOop(_obj)->length();
 }
 #endif // ASSERT
-
-bool RegionTaskQueueWithOverflow::is_empty() {
-  return (_region_queue.size() == 0) &&
-         (_overflow_stack->length() == 0);
-}
-
-bool RegionTaskQueueWithOverflow::stealable_is_empty() {
-  return _region_queue.size() == 0;
-}
-
-bool RegionTaskQueueWithOverflow::overflow_is_empty() {
-  return _overflow_stack->length() == 0;
-}
-
-void RegionTaskQueueWithOverflow::initialize() {
-  _region_queue.initialize();
-  assert(_overflow_stack == 0, "Creating memory leak");
-  _overflow_stack =
-    new (ResourceObj::C_HEAP) GrowableArray<RegionTask>(10, true);
-}
-
-void RegionTaskQueueWithOverflow::save(RegionTask t) {
-  if (TraceRegionTasksQueuing && Verbose) {
-    gclog_or_tty->print_cr("CTQ: save " PTR_FORMAT, t);
-  }
-  if(!_region_queue.push(t)) {
-    _overflow_stack->push(t);
-  }
-}
-
-// Note that using this method will retrieve all regions
-// that have been saved but that it will always check
-// the overflow stack.  It may be more efficient to
-// check the stealable queue and the overflow stack
-// separately.
-bool RegionTaskQueueWithOverflow::retrieve(RegionTask& region_task) {
-  bool result = retrieve_from_overflow(region_task);
-  if (!result) {
-    result = retrieve_from_stealable_queue(region_task);
-  }
-  if (TraceRegionTasksQueuing && Verbose && result) {
-    gclog_or_tty->print_cr("  CTQ: retrieve " PTR_FORMAT, result);
-  }
-  return result;
-}
-
-bool RegionTaskQueueWithOverflow::retrieve_from_stealable_queue(
-                                   RegionTask& region_task) {
-  bool result = _region_queue.pop_local(region_task);
-  if (TraceRegionTasksQueuing && Verbose) {
-    gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
-  }
-  return result;
-}
-
-bool
-RegionTaskQueueWithOverflow::retrieve_from_overflow(RegionTask& region_task) {
-  bool result;
-  if (!_overflow_stack->is_empty()) {
-    region_task = _overflow_stack->pop();
-    result = true;
-  } else {
-    region_task = (RegionTask) NULL;
-    result = false;
-  }
-  if (TraceRegionTasksQueuing && Verbose) {
-    gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task);
-  }
-  return result;
-}
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, 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
@@ -109,8 +109,9 @@
 public:
   TaskQueueSuper() : _bottom(0), _age() {}
 
-  // Return true if the TaskQueue contains any tasks.
-  bool peek() { return _bottom != _age.top(); }
+  // Return true if the TaskQueue contains/does not contain any tasks.
+  bool peek()     const { return _bottom != _age.top(); }
+  bool is_empty() const { return size() == 0; }
 
   // Return an estimate of the number of elements in the queue.
   // The "careful" version admits the possibility of pop_local/pop_global
@@ -165,18 +166,16 @@
 
   void initialize();
 
-  // Push the task "t" on the queue.  Returns "false" iff the queue is
-  // full.
+  // Push the task "t" on the queue.  Returns "false" iff the queue is full.
   inline bool push(E t);
 
-  // If succeeds in claiming a task (from the 'local' end, that is, the
-  // most recently pushed task), returns "true" and sets "t" to that task.
-  // Otherwise, the queue is empty and returns false.
+  // Attempts to claim a task from the "local" end of the queue (the most
+  // recently pushed).  If successful, returns true and sets t to the task;
+  // otherwise, returns false (the queue is empty).
   inline bool pop_local(E& t);
 
-  // If succeeds in claiming a task (from the 'global' end, that is, the
-  // least recently pushed task), returns "true" and sets "t" to that task.
-  // Otherwise, the queue is empty and returns false.
+  // Like pop_local(), but uses the "global" end of the queue (the least
+  // recently pushed).
   bool pop_global(E& t);
 
   // Delete any resource associated with the queue.
@@ -198,7 +197,6 @@
 template<class E, unsigned int N>
 void GenericTaskQueue<E, N>::initialize() {
   _elems = NEW_C_HEAP_ARRAY(E, N);
-  guarantee(_elems != NULL, "Allocation failed.");
 }
 
 template<class E, unsigned int N>
@@ -289,7 +287,87 @@
   FREE_C_HEAP_ARRAY(E, _elems);
 }
 
-// Inherits the typedef of "Task" from above.
+// OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
+// elements that do not fit in the TaskQueue.
+//
+// Three methods from super classes are overridden:
+//
+// initialize() - initialize the super classes and create the overflow stack
+// push() - push onto the task queue or, if that fails, onto the overflow stack
+// is_empty() - return true if both the TaskQueue and overflow stack are empty
+//
+// Note that size() is not overridden--it returns the number of elements in the
+// TaskQueue, and does not include the size of the overflow stack.  This
+// simplifies replacement of GenericTaskQueues with OverflowTaskQueues.
+template<class E, unsigned int N = TASKQUEUE_SIZE>
+class OverflowTaskQueue: public GenericTaskQueue<E, N>
+{
+public:
+  typedef GrowableArray<E>       overflow_t;
+  typedef GenericTaskQueue<E, N> taskqueue_t;
+
+  OverflowTaskQueue();
+  ~OverflowTaskQueue();
+  void initialize();
+
+  inline overflow_t* overflow_stack() const { return _overflow_stack; }
+
+  // Push task t onto the queue or onto the overflow stack.  Return true.
+  inline bool push(E t);
+
+  // Attempt to pop from the overflow stack; return true if anything was popped.
+  inline bool pop_overflow(E& t);
+
+  inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
+  inline bool overflow_empty()  const { return overflow_stack()->is_empty(); }
+  inline bool is_empty()        const {
+    return taskqueue_empty() && overflow_empty();
+  }
+
+private:
+  overflow_t* _overflow_stack;
+};
+
+template <class E, unsigned int N>
+OverflowTaskQueue<E, N>::OverflowTaskQueue()
+{
+  _overflow_stack = NULL;
+}
+
+template <class E, unsigned int N>
+OverflowTaskQueue<E, N>::~OverflowTaskQueue()
+{
+  if (_overflow_stack != NULL) {
+    delete _overflow_stack;
+    _overflow_stack = NULL;
+  }
+}
+
+template <class E, unsigned int N>
+void OverflowTaskQueue<E, N>::initialize()
+{
+  taskqueue_t::initialize();
+  assert(_overflow_stack == NULL, "memory leak");
+  _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<E>(10, true);
+}
+
+template <class E, unsigned int N>
+bool OverflowTaskQueue<E, N>::push(E t)
+{
+  if (!taskqueue_t::push(t)) {
+    overflow_stack()->push(t);
+  }
+  return true;
+}
+
+template <class E, unsigned int N>
+bool OverflowTaskQueue<E, N>::pop_overflow(E& t)
+{
+  if (overflow_empty()) return false;
+  t = overflow_stack()->pop();
+  return true;
+}
+
 class TaskQueueSetSuper: public CHeapObj {
 protected:
   static int randomParkAndMiller(int* seed0);
@@ -323,11 +401,11 @@
 
   T* queue(uint n);
 
-  // The thread with queue number "queue_num" (and whose random number seed
-  // is at "seed") is trying to steal a task from some other queue.  (It
-  // may try several queues, according to some configuration parameter.)
-  // If some steal succeeds, returns "true" and sets "t" the stolen task,
-  // otherwise returns false.
+  // The thread with queue number "queue_num" (and whose random number seed is
+  // at "seed") is trying to steal a task from some other queue.  (It may try
+  // several queues, according to some configuration parameter.)  If some steal
+  // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
+  // false.
   bool steal(uint queue_num, int* seed, E& t);
 
   bool peek();
@@ -507,7 +585,7 @@
   uint localBot = _bottom;
   // This value cannot be N-1.  That can only occur as a result of
   // the assignment to bottom in this method.  If it does, this method
-  // resets the size( to 0 before the next call (which is sequential,
+  // resets the size to 0 before the next call (which is sequential,
   // since this is pop_local.)
   uint dirty_n_elems = dirty_size(localBot, _age.top());
   assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
@@ -533,8 +611,7 @@
   }
 }
 
-typedef oop Task;
-typedef GenericTaskQueue<Task>            OopTaskQueue;
+typedef GenericTaskQueue<oop>             OopTaskQueue;
 typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet;
 
 #ifdef _MSC_VER
@@ -615,35 +692,8 @@
 #pragma warning(pop)
 #endif
 
-typedef GenericTaskQueue<StarTask>            OopStarTaskQueue;
+typedef OverflowTaskQueue<StarTask>           OopStarTaskQueue;
 typedef GenericTaskQueueSet<OopStarTaskQueue> OopStarTaskQueueSet;
 
-typedef size_t RegionTask;  // index for region
-typedef GenericTaskQueue<RegionTask>         RegionTaskQueue;
-typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet;
-
-class RegionTaskQueueWithOverflow: public CHeapObj {
- protected:
-  RegionTaskQueue              _region_queue;
-  GrowableArray<RegionTask>*   _overflow_stack;
-
- public:
-  RegionTaskQueueWithOverflow() : _overflow_stack(NULL) {}
-  // Initialize both stealable queue and overflow
-  void initialize();
-  // Save first to stealable queue and then to overflow
-  void save(RegionTask t);
-  // Retrieve first from overflow and then from stealable queue
-  bool retrieve(RegionTask& region_index);
-  // Retrieve from stealable queue
-  bool retrieve_from_stealable_queue(RegionTask& region_index);
-  // Retrieve from overflow
-  bool retrieve_from_overflow(RegionTask& region_index);
-  bool is_empty();
-  bool stealable_is_empty();
-  bool overflow_is_empty();
-  uint stealable_size() { return _region_queue.size(); }
-  RegionTaskQueue* task_queue() { return &_region_queue; }
-};
-
-#define USE_RegionTaskQueueWithOverflow
+typedef OverflowTaskQueue<size_t>             RegionTaskQueue;
+typedef GenericTaskQueueSet<RegionTaskQueue>  RegionTaskQueueSet;
--- a/jdk/.hgtags	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/.hgtags	Wed Jul 05 17:17:57 2017 +0200
@@ -75,3 +75,4 @@
 82593186fa54ab12f17af31f86a7bf364efaf4df jdk7-b98
 2587c9f0b60dc3146b4247b8674ada456a643d6f jdk7-b99
 820b4e843d5168370a3bf166d19751a3271d8575 jdk7-b100
+d58354a69011f3d3354765fa3167567c4c4a9612 jdk7-b101
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/common/shared/Defs-javadoc.gmk	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 1997, 2010, 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.
+#
+
+# Copyright year for beginning of Java and some of the apis
+#   (Needed when creating the javadocs)
+FIRST_COPYRIGHT_YEAR                = 1993
+DOMAPI_FIRST_COPYRIGHT_YEAR         = 2005
+MIRROR_FIRST_COPYRIGHT_YEAR         = 2004
+DOCLETAPI_FIRST_COPYRIGHT_YEAR      = 1993
+TAGLETAPI_FIRST_COPYRIGHT_YEAR      = 1993
+JDI_FIRST_COPYRIGHT_YEAR            = 1999
+JAAS_FIRST_COPYRIGHT_YEAR           = 1998
+JGSS_FIRST_COPYRIGHT_YEAR           = 2000
+SMARTCARDIO_FIRST_COPYRIGHT_YEAR    = 2005
+HTTPSERVER_FIRST_COPYRIGHT_YEAR     = 2005
+MGMT_FIRST_COPYRIGHT_YEAR           = 2003
+ATTACH_FIRST_COPYRIGHT_YEAR         = 2005
+JCONSOLE_FIRST_COPYRIGHT_YEAR       = 2006
+SCTPAPI_FIRST_COPYRIGHT_YEAR        = 2009
+TRACING_FIRST_COPYRIGHT_YEAR        = 2008
+TREEAPI_FIRST_COPYRIGHT_YEAR        = 2005
+JNLP_FIRST_COPYRIGHT_YEAR           = 1998
+PLUGIN2_FIRST_COPYRIGHT_YEAR        = 2007
+
+# Oracle name
+COMPANY_NAME = Oracle and/or its affiliates
+
+# Copyright address
+COMPANY_ADDRESS = 500 Oracle Parkway<br>Redwood Shores, CA 94065 USA.
+
+# The trademark symbol
+TRADEMARK = &trade;
+
+# Common copyright lines used
+#   The word "Copyright" might optionally be a link to the file cpyr.html.
+#   The first year of copyright may vary or not be available.
+#   The address to the company might be optional.
+COMMA:= ,
+EMPTY:=
+SPACE:=$(EMPTY) $(EMPTY)
+COPYRIGHT_SYMBOL = &\#x00a9;
+# Macros to handle the optional empty args.
+#   (The GNU make 3.78.1 "if" conditional is broken, fixed in GNU make 3.81)
+define OptionalCopyrightUrl # url
+$(shell \
+  if [ "$1" != "" ] ; then \
+    printf "<a href=\"%s\">Copyright</a>" "$1"; \
+  else \
+    printf "Copyright"; \
+  fi)
+endef
+define OptionalCopyrightFirstYear # year
+$(shell \
+  if [ "$1" != "" ] ; then \
+    printf "%s," "$1";\
+  fi)
+endef
+define OptionalCompanyAddress # address
+$(shell \
+  if [ "$1" != "" ] ; then \
+    printf "%s" "$1";\
+  fi)
+endef
+define CopyrightLine # optionalurl optionalfirstyear optionaladdress
+$(call OptionalCopyrightUrl,$1) $(COPYRIGHT_SYMBOL)\
+$(call OptionalCopyrightFirstYear,$2) $(COPYRIGHT_YEAR),\
+$(COMPANY_NAME).\
+$(call OptionalCompanyAddress,$3)\
+All rights reserved.
+endef
+
--- a/jdk/make/common/shared/Defs-windows.gmk	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/make/common/shared/Defs-windows.gmk	Wed Jul 05 17:17:57 2017 +0200
@@ -230,7 +230,8 @@
 
 # Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit]
 ifeq ($(ARCH_DATA_MODEL), 32)
-  # Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
+  # Try looking in MSVCDIR or MSVCDir area first 
+  # (set by vcvars32.bat for VC .NET, not defined in the VC 2008/2010)
   ifdef MSVCDIR
     xMSVCDIR  :="$(subst \,/,$(MSVCDIR))"
     _msvc_dir :=$(call FullPath,$(xMSVCDIR))
@@ -238,11 +239,6 @@
     ifdef MSVCDir
       xMSVCDIR  :="$(subst \,/,$(MSVCDir))"
       _msvc_dir :=$(call FullPath,$(xMSVCDIR))
-    else
-      ifneq ($(_program_files),)
-        xMSVCDIR  :="$(_program_files)/Microsoft Visual Studio .NET 2003/Vc7"
-        _msvc_dir :=$(call FullPath,$(xMSVCDIR))
-      endif
     endif
   endif
   # If we still don't have it, look for VSnnCOMNTOOLS (newest first),
--- a/jdk/make/docs/Makefile	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/make/docs/Makefile	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,4 @@
-#
-# Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2010, 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
@@ -30,6 +29,41 @@
 PRODUCT=docs
 include $(BUILDDIR)/common/Defs.gmk
 
+# Get CopyrightLine macro and other shared variables
+include $(BUILDDIR)/common/shared/Defs-javadoc.gmk
+
+# Url to root of documents
+DOCSDIR_URL = {@docroot}/$(GET2DOCSDIR)
+
+# Url to copyright html file
+COPYRIGHT_URL-7 = $(DOCSDIR_URL)/legal/cpyr.html
+COPYRIGHT_URL = $(COPYRIGHT_URL-$(JDK_MINOR_VERSION))
+
+# Url to bug filing site
+BUG_SUBMIT_URL = http://bugs.sun.com/services/bugreport/index.jsp
+
+# Common line for how to submit a bug or rfe
+BUG_SUBMIT_LINE = <a href=\"$(BUG_SUBMIT_URL)\">Submit a bug or feature</a>
+
+# Url to devdocs page
+#   Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html
+DEV_DOCS_URL-5 = http://java.sun.com/j2se/1.5.0/docs
+DEV_DOCS_URL-6 = http://download.oracle.com/docs/cd/E17409_01/javase/6/docs
+DEV_DOCS_URL-7 = http://download.oracle.com/docs/cd/E17409_01/javase/7/docs
+DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
+
+# Url to Java Language Spec
+JLS3_URL = http://java.sun.com/docs/books/jls/
+
+# Common Java trademark line
+JAVA_TRADEMARK_LINE = Java is a trademark or registered trademark of \
+$(COMPANY_NAME) in the US and other countries.
+
+#
+# Definitions for imported components
+#
+include $(BUILDDIR)/common/internal/ImportComponents.gmk
+
 # We override whatever the max VM memory setting is here.
 #    NOTE: javadoc will not complete without these larger settings.
 #    WARNING: This could cause thrashing on low memory machines.
@@ -39,418 +73,155 @@
   MAX_VM_MEMORY = 512
 endif
 
-#
-# Variables used by docs target
+# List of all possible directories for javadoc to look for sources
+#    NOTE: Quotes are required around sourcepath argument only on Windows.
+#          Otherwise, you get "No packages or classes specified." due 
+#          to $(CLASSPATH_SEPARATOR) being interpreted as an end of 
+#          command (newline or shell ; character)
+ALL_SOURCE_DIRS = $(SHARE_SRC)/classes \
+                  $(IMPORTSRCDIR) \
+                  $(GENSRCDIR) \
+                  $(SHARE_SRC)/../solaris/classes \
+	          $(SHARE_SRC)/../windows/classes \
+		  $(SHARE_SRC)/doc/stub
+EMPTY:=
+SPACE:= $(EMPTY) $(EMPTY)
+RELEASEDOCS_SOURCEPATH = \
+    $(subst $(SPACE),$(CLASSPATH_SEPARATOR),$(strip $(ALL_SOURCE_DIRS)))
+
+# Prep for javadoc creation, assumes $@ is an index.html file
+define prep-javadoc
+@if [ -f "$@" -a "$?" != "" ] ; then \
+  $(ECHO) "# Dependencies have changed: $?"; \
+fi
+$(RM) -r $(@D)
+$(MKDIR) -p $(@D)
+endef
+
+# A cache of the directories in ALL_SOURCE_DIRS
+DIRECTORY_CACHE = $(DOCSTMPDIR)/directory.cache
+
+# Given a list of packages, return a list of files or dirs to be dependent on
+#   (Currently only returning a list of directories)
+define PackageDependencies # packages
+$(shell							\
+  if [ "$1" != "" -a -f $(DIRECTORY_CACHE) ] ; then	\
+    for p in $1 ; do 					\
+      pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`;	\
+      $(CAT) $(DIRECTORY_CACHE) | $(GREP) "/$${pd}/" ; 	\
+    done; 						\
+  fi							\
+)
+endef
+
+# Given a list of packages, add packages that exist to $@, print summary
+define PackageFilter # packages
+@if [ "$1" != "" ] ; then 				\
+  for p in $1 ; do 					\
+    pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`; 	\
+    found="false"; 					\
+    for cp in $(ALL_SOURCE_DIRS) ; do 			\
+      if [ -d $${cp}/$${pd} ] ; then 			\
+        $(ECHO) "$${p}" >> $@; 				\
+	found="true";					\
+	break; 						\
+      fi; 						\
+    done; 						\
+    if [ "$${found}" = "false" ] ; then 		\
+      $(ECHO) "WARNING: Package not found: $${p}"; 	\
+    fi; 						\
+  done; 						\
+fi
+endef
+
+# Print out a summary of the javadoc command about to be run
+define JavadocSummary # optionsfile packagesfile
+@$(ECHO) "# Summary for $@";\
+ $(ECHO) "# Options (`$(BASENAME) $1`):"; $(SED) -e 's@^@#   @' $1; \
+ $(ECHO) "# Packages (`$(BASENAME) $2`):";$(SED) -e 's@^@#   @' $2
+endef
+
 #
-DOCSTMPDIR          = $(TEMPDIR)/doctmp
+# Temporary directory for javadoc creation
+#
+DOCSTMPDIR = $(TEMPDIR)/doctmp
+
+#
+# Different api directories created from root directory
+#
+COREAPI_DOCSDIR   = $(DOCSDIR)/api
+JDK_API_DOCSDIR   = $(DOCSDIR)/jdk/api
+JRE_API_DOCSDIR   = $(DOCSDIR)/jre/api
+PLATFORM_DOCSDIR  = $(DOCSDIR)/platform
+
+# The non-core api javadocs need to be able to access the root of the core
+#   api directory, so for jdk/api or jre/api to get to the core api/
+#   directory we would use this:
+JDKJRE2COREAPI    = ../../api
+
+# Common bottom argument
+define CommonBottom # year
+<font size=\"-1\"><p> $(call CopyrightLine,,$1,)</font>
+endef
 
+# Common trademark bottom argument (Not sure why this is used sometimes)
+define CommonTrademarkBottom # year
+<font size=\"-1\">\
+$(BUG_SUBMIT_LINE)<br>$(JAVA_TRADEMARK_LINE)<br>\
+$(call CopyrightLine,,$1,$(COMPANY_ADDRESS))\
+</font>
+endef
+
+# Core api bottom argument (with special sauce)
+COREAPI_BOTTOM = <font size=\"-1\"> $(BUG_SUBMIT_LINE)\
+<br>For further API reference and developer documentation, \
+see <a href=\"$(DEV_DOCS_URL)\" target=\"_blank\">Java SE Documentation</a>. \
+That documentation contains more detailed, developer-targeted descriptions, \
+with conceptual overviews, definitions of terms, workarounds, \
+and working code examples.<p>\
+$(call CopyrightLine,$(COPYRIGHT_URL),$(FIRST_COPYRIGHT_YEAR),)\
+</font>
+
+# Common javadoc options used by all
 COMMON_JAVADOCFLAGS =					\
-		$(NO_PROPRIETARY_API_WARNINGS)		\
+                $(NO_PROPRIETARY_API_WARNINGS)          \
 		-source 1.5				\
 		-quiet					\
                 -use					\
                 -keywords				\
-		$(JAVADOC_VM_MEMORY_FLAGS)		\
 		$(ADDITIONAL_JAVADOCFLAGS)
 ADDITIONAL_JAVADOCFLAGS =
 
-CORE_JAVADOCFLAGS  = $(COMMON_JAVADOCFLAGS)		\
-		$(TAGS)					\
-		-encoding ISO-8859-1			\
-		-splitIndex				\
-		-doctitle $(DOCTITLE_SWITCH)		\
-		-windowtitle $(WINDOWTITLE_SWITCH)	\
-		-header $(HEADER_SWITCH)		\
-		$(TOPOPTION) 				\
-		-bottom $(JAVADOCBOTTOM_SWITCH)		\
-		$(OVERVIEW_OPTION)
-
-DRAFT = '<br><strong>DRAFT&nbsp;'$(MILESTONE)-$(BUILD_NUMBER)'</strong>'
-THIS_YEAR := $(shell $(DATE) | $(SED) -e 's/  / /g' | $(CUT) -d' ' -f6)
-TRADEMARK = &\#x2122;
-
-IGNORED_TAGS =	beaninfo revised since.unbundled spec specdefault Note ToDo
-
-JLS3_URL = http://java.sun.com/docs/books/jls/
-JLS3_CITE = <a href="$(JLS3_URL)"> \
-		The Java Language Specification, Third Edition</a>
-TAG_JLS3 = -tag 'jls3:a:See <cite>$(JLS3_CITE)</cite>:'
-
-TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3)
-
-ifeq ($(MILESTONE), fcs)
-    DOCTITLE_SWITCH = $(JAVADOCTITLE)
-    WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)
-    HEADER_SWITCH = $(JAVADOCHEADER)
-    TOPOPTION=
-    JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM)
-    OVERVIEW_OPTION = -overview $(JAVADOCOVERVIEW)
-else
-    DOCTITLE_SWITCH = $(JAVADOCTITLE_EARLYACCESS)$(DRAFT)
-    WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)" $(BUILD_NUMBER)"
-    HEADER_SWITCH = $(JAVADOCHEADER)$(DRAFT)
-    JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM_EARLYACCESS)
-    TOPOPTION= -top $(JAVADOCTOP_EARLYACCESS)
-    OVERVIEW_OPTION =
+# Draft used for non-fcs documents
+JDK_IS_FCS = false
+DRAFT_HEADER =
+ifeq ($(JDK_MINOR_VERSION),5)
+  JDK_IS_FCS = true
+endif
+ifeq ($(JDK_MINOR_VERSION),6)
+  JDK_IS_FCS = true
+endif
+ifeq ($(JDK_IS_FCS),false)
+  ifneq ($(MILESTONE), fcs)
+    DRAFT_HEADER = <br><strong>DRAFT&nbsp;$(MILESTONE)-$(BUILD_NUMBER)</strong>
+    DRAFT_BOTTOM = <br><strong>DRAFT&nbsp;$(MILESTONE)-$(BUILD_NUMBER)</strong>
+    DRAFT_WINTITLE = $(BUILD_NUMBER)
+    # Early access top text (not used in FCS releases)
+    COREAPI_TOP_EARLYACCESS = \
+<div style=\"background-color: \#EEEEEE\"> \
+<div style=\"padding: 6px; margin-top: 2px; margin-bottom: 6px; \
+margin-left: 6px; margin-right: 6px; text-align: justify; \
+font-size: 80%; font-family: Helvetica, Arial, sans-serif; \
+font-weight: normal;\"> \
+Please note that the specifications and other information \
+contained herein are not final and are subject to change. \
+The information is being made available to you solely for purpose of \
+evaluation. \
+</div> </div>
+  endif
 endif
 
-JAVADOCTITLE  = 'Java$(TRADEMARK) Platform, Standard Edition $(JDK_MINOR_VERSION)<br>API Specification'
-JAVADOCWINDOWTITLE  = 'Java Platform SE $(JDK_MINOR_VERSION)'
-JAVADOCHEADER = '<strong>Java$(TRADEMARK)&nbsp;Platform<br>Standard&nbsp;Ed.&nbsp;$(JDK_MINOR_VERSION)</strong>'
-JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>For further API reference and developer documentation, see <a href="{@docroot}/../../webnotes/devdocs-vs-specs.html">Java SE Developer Documentation</a>. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>. Also see the <a href="http://java.sun.com/docs/redist.html">documentation redistribution policy</a>.</font>'
-JAVADOCOVERVIEW = $(SHARE_SRC)/classes/overview-core.html
-
-#
-# Early access top and bottom text (for snapshots, beta and rc)
-#
-JAVADOCTOP_EARLYACCESS = '<div style="background-color: \#EEEEEE"> <div style="padding: 6px; margin-top: 2px; margin-bottom: 6px; margin-left: 6px; margin-right: 6px; text-align: justify; font-size: 80%; font-family: Helvetica, Arial, sans-serif; font-weight: normal;"> Please note that this documentation is not final and is subject to change. </div> </div>'
-JAVADOCBOTTOM_EARLYACCESS = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a> <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>.</font>'
-JAVADOCTITLE_EARLYACCESS = $(subst Specification,Documentation,$(JAVADOCTITLE))
-
-#
-# Variables used by domapidocs target
-#
-
-DOMAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)		      \
-		    -encoding ascii			      \
-                    -splitIndex                               \
-                    -doctitle $(DOMAPI_JAVADOCTITLE)          \
-                    -windowtitle $(DOMAPI_JAVADOCWINDOWTITLE) \
-                    -header $(DOMAPI_JAVADOCHEADER)           \
-                    -bottom $(DOMAPI_JAVADOCBOTTOM)           \
-                    -group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP)
-DOMAPI_JAVADOCTITLE  = 'Common DOM API'
-DOMAPI_JAVADOCWINDOWTITLE  = 'Common DOM API'
-DOMAPI_JAVADOCHEADER = '<strong>Common DOM API</strong>'
-DOMAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A.  All Rights Reserved.</font>'
-DOMAPI_GROUPNAME = "Packages"
-DOMAPI_REGEXP = "com.sun.java.browser.dom:org.w3c.dom*"
-# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by mirrordocs target
-#
-
-MIRROR_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)		        \
-                    -encoding ascii			        \
-                    -doctitle $(MIRROR_JAVADOCTITLE)            \
-                    -windowtitle $(MIRROR_JAVADOCWINDOWTITLE)   \
-                    -header $(MIRROR_JAVADOCHEADER)             \
-                    -bottom $(MIRROR_JAVADOCBOTTOM)             \
-                    -group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP) \
-                    -overview $(MIRROR_OVERVIEW)
-MIRROR_JAVADOCTITLE = 'Mirror API'
-MIRROR_JAVADOCWINDOWTITLE = 'Mirror API'
-MIRROR_JAVADOCHEADER = '<strong>Mirror API</strong>'
-MIRROR_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-MIRROR_GROUPNAME = "Packages"
-MIRROR_OVERVIEW = $(IMPORTSRCDIR)/com/sun/mirror/overview.html
-MIRROR_REGEXP = "com.sun.mirror.*"
-MIRROR_DESTDIR = $(DOCSDIR)/jdk/api/apt/mirror
-MIRROR_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
-# MIRROR_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by docletapidocs target
-#
-
-DOCLETAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			 \
-		    -breakiterator				 \
-		    -encoding ascii			         \
-                    -doctitle $(DOCLETAPI_JAVADOCTITLE)          \
-                    -windowtitle $(DOCLETAPI_JAVADOCWINDOWTITLE) \
-                    -header $(DOCLETAPI_JAVADOCHEADER)           \
-                    -bottom $(DOCLETAPI_JAVADOCBOTTOM)           \
-                    -group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP)
-DOCLETAPI_JAVADOCTITLE  = 'Doclet API'
-DOCLETAPI_JAVADOCWINDOWTITLE  = 'Doclet API'
-DOCLETAPI_JAVADOCHEADER = '<strong>Doclet API</strong>'
-DOCLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A.  All Rights Reserved.</font>'
-DOCLETAPI_GROUPNAME = "Packages"
-DOCLETAPI_REGEXP = "com.sun.javadoc"
-DOCLETAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
-# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by tagletapidocs target
-#
-
-TAGLETAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			\
-		    -encoding ascii			        \
-                    -nonavbar                                   \
-                    -noindex                                    \
-                    -bottom $(TAGLETAPI_JAVADOCBOTTOM)
-TAGLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A.  All Rights Reserved.</font>'
-# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by jdi target
-#
-
-JPDA_SOURCEPATH  = $(TOPDIR)/src/share/classes
-
-JDI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			 \
-		   -encoding ascii			         \
-                   -nodeprecatedlist                             \
-                   -d $(DOCSDIR)/jdk/api/jpda/jdi                  \
-                   -sourcepath $(JPDA_SOURCEPATH)                \
-                   -windowtitle $(JDI_WINDOWTITLE)               \
-                   -doctitle $(JDI_DOCTITLE)                     \
-                   -header $(JDI_HEADER)                         \
-                   -linkoffline ../../../../api $(DOCSDIR)/api/     \
-                   -overview $(JPDA_SOURCEPATH)/jdi-overview.html
-JDI_WINDOWTITLE = "Java Debug Interface"
-JDI_DOCTITLE    = "Java$(TRADEMARK) Debug Interface"
-JDI_HEADER      = "Java Debug Interface"
-# JDI_PKGS is located in NON_CORE_PKGS.gmk
-
-# Variables used by security components
-SECURITYAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-
-#
-# Variables used by JAAS target
-#
-# NOTE: Quotes are required around sourcepath argument only on Windows.  Otherwise,
-#       you get "No packages or classes specified." due to $(CLASSPATH_SEPARATOR)
-#       being interpreted as an end of command (newline)
-
-JAAS_SOURCEPATH  = "$(TOPDIR)/src/share/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/solaris/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/windows/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/linux/classes"
-JAAS_DOCDIR	 = $(DOCSDIR)/jre/api/security/jaas/spec
-JAAS_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			 \
-		   -encoding ascii			         \
-                   -nodeprecatedlist                             \
-                   -d $(JAAS_DOCDIR)				 \
-                   -sourcepath $(JAAS_SOURCEPATH)                \
-                   -windowtitle $(JAAS_WINDOWTITLE)              \
-                   -doctitle $(JAAS_DOCTITLE)                    \
-                   -header $(JAAS_JAVADOCHEADER)                 \
-                   -bottom $(SECURITYAPI_JAVADOCBOTTOM)                      \
-                   -linkoffline ../../../../../api $(DOCSDIR)/api/	 \
-                   -overview $(TOPDIR)/src/share/classes/com/sun/security/auth/jaas-overview.html
-JAAS_WINDOWTITLE = "Java Authentication and Authorization Service "
-JAAS_DOCTITLE    = "Java$(TRADEMARK) Authentication and Authorization Service"
-JAAS_JAVADOCHEADER      = "JAAS"
-# JAAS_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by JGSS target
-#
-
-JGSS_SOURCEPATH  = $(TOPDIR)/src/share/classes
-JGSS_DOCDIR	 = $(DOCSDIR)/jre/api/security/jgss/spec
-
-JGSS_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			\
-		   -encoding ascii			        \
-                   -nodeprecatedlist                            \
-                   -d $(JGSS_DOCDIR)				\
-                   -sourcepath $(JGSS_SOURCEPATH)               \
-                   -windowtitle $(JGSS_WINDOWTITLE)             \
-                   -doctitle $(JGSS_DOCTITLE)                   \
-                   -header $(JGSS_JAVADOCHEADER)                \
-                   -bottom $(SECURITYAPI_JAVADOCBOTTOM)                      \
-                   -linkoffline ../../../../../api $(DOCSDIR)/api/ \
-                   -overview $(JGSS_SOURCEPATH)/com/sun/security/jgss/jgss-overview.html
-
-JGSS_WINDOWTITLE = "Java GSS-API Utilities "
-JGSS_DOCTITLE    = "Java$(TRADEMARK) GSS-API Utilities"
-JGSS_JAVADOCHEADER      = "Java GSS-API Utilities"
-# JGSS_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by SMARTCARDIO target
-#
-
-SMARTCARDIO_SOURCEPATH  = $(TOPDIR)/src/share/classes
-SMARTCARDIO_DOCDIR	 = $(DOCSDIR)/jre/api/security/smartcardio/spec
-
-SMARTCARDIO_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			\
-		   -encoding ascii			        \
-                   -nodeprecatedlist                            \
-                   -d $(SMARTCARDIO_DOCDIR)				\
-                   -sourcepath $(SMARTCARDIO_SOURCEPATH)               \
-                   -windowtitle $(SMARTCARDIO_WINDOWTITLE)             \
-                   -doctitle $(SMARTCARDIO_DOCTITLE)                   \
-                   -header $(SMARTCARDIO_JAVADOCHEADER)                \
-                   -bottom $(SECURITYAPI_JAVADOCBOTTOM)                      \
-                   -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-SMARTCARDIO_WINDOWTITLE = "Java Smart Card I/O"
-SMARTCARDIO_DOCTITLE    = "Java$(TRADEMARK) Smart Card I/O"
-SMARTCARDIO_JAVADOCHEADER      = "Java Smart Card I/O"
-# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by TRACING target
-#
-
-TRACING_SOURCEPATH  = $(TOPDIR)/src/share/classes
-TRACING_DOCDIR	 = $(DOCSDIR)/jre/api/tracing
-
-TRACING_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			    \
-		   -encoding ascii			            \
-                   -nodeprecatedlist                                \
-                   -d $(TRACING_DOCDIR)				    \
-                   -sourcepath $(TRACING_SOURCEPATH)                \
-                   -windowtitle $(TRACING_WINDOWTITLE)              \
-                   -doctitle $(TRACING_DOCTITLE)                    \
-                   -header $(TRACING_JAVADOCHEADER)                 \
-                   -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-TRACING_WINDOWTITLE = "Tracing"
-TRACING_DOCTITLE    = "Java$(TRADEMARK) Platform Tracing"
-TRACING_JAVADOCHEADER      = "Platform Tracing"
-# TRACING_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by HTTPSERVER target
-#
-
-HTTPSERVER_SOURCEPATH  = $(TOPDIR)/src/share/classes
-HTTPSERVER_DOCDIR	 = $(DOCSDIR)/jre/api/net/httpserver/spec
-
-HTTPSERVER_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)			\
-		   -encoding ascii			        \
-                   -nodeprecatedlist                            \
-                   -d $(HTTPSERVER_DOCDIR)				\
-                   -sourcepath $(HTTPSERVER_SOURCEPATH)               \
-                   -windowtitle $(HTTPSERVER_WINDOWTITLE)             \
-                   -doctitle $(HTTPSERVER_DOCTITLE)                   \
-                   -header $(HTTPSERVER_JAVADOCHEADER)                \
-                   -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-HTTPSERVER_WINDOWTITLE = "Java HTTP Server"
-HTTPSERVER_DOCTITLE    = "Java$(TRADEMARK) HTTP Server"
-HTTPSERVER_JAVADOCHEADER      = "Java HTTP Server"
-# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by sctp target
-#
-
-SCTPAPI_SOURCEPATH  = $(TOPDIR)/src/share/classes
-SCTPAPI_DOCDIR   = $(DOCSDIR)/jre/api/nio/sctp/spec
-
-SCTPAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)                           \
-                   -encoding ascii                                      \
-                   -nodeprecatedlist                                    \
-                   -d $(SCTPAPI_DOCDIR)                                 \
-                   -sourcepath $(SCTPAPI_SOURCEPATH)                    \
-                   -windowtitle $(SCTPAPI_WINDOWTITLE)                  \
-                   -doctitle $(SCTPAPI_DOCTITLE)                        \
-                   -header $(SCTPAPI_JAVADOCHEADER)                     \
-                   -bottom $(SCTPAPI_JAVADOCBOTTOM)			\
-                   -linkoffline ../../../../../api $(DOCSDIR)/api/
-
-SCTPAPI_WINDOWTITLE = "SCTP API"
-SCTPAPI_DOCTITLE    = "SCTP API"
-SCTPAPI_JAVADOCHEADER      = "SCTP API"
-SCTPAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by jvmti target
-#
-JVMTI_DOCS_SUBDIR = platform/jvmti
-JVMTI_HTML        = $(HOTSPOT_DOCS_IMPORT_PATH)/$(JVMTI_DOCS_SUBDIR)/jvmti.html
-
-#
-# Variables used by mgmt target
-#
-MGMT_DOCDIR	   = $(DOCSDIR)/jre/api/management/
-MGMT_EXT_DIR	   = $(MGMT_DOCDIR)/extension
-MGMT_SOURCEPATH    = $(TOPDIR)/src/share/classes
-JVM_MIB_NAME       = JVM-MANAGEMENT-MIB.mib
-JVM_MIB_SRC        = $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME)
-
-ifdef OPENJDK
-   COPY-MIB-TARGET =
-else
-   COPY-MIB-TARGET = copy-mib
-endif
-MGMT_JAVADOCFLAGS  = $(COMMON_JAVADOCFLAGS)			   \
-		     -encoding ascii			           \
-                     -nodeprecatedlist                             \
-                     -d $(MGMT_EXT_DIR) 		  	   \
-                     -sourcepath $(MGMT_SOURCEPATH)                \
-                     -windowtitle $(MGMT_WINDOWTITLE)              \
-                     -doctitle $(MGMT_DOCTITLE)                    \
-                     -header $(MGMT_HEADER)                        \
-		     -linkoffline ../../../../api $(DOCSDIR)/api/  \
-                     -overview $(MGMT_SOURCEPATH)/com/sun/management/mgmt-overview.html
-MGMT_WINDOWTITLE = "Monitoring and Management Interface for the Java Platform"
-MGMT_DOCTITLE    = "Monitoring and Management Interface for the Java$(TRADEMARK) Platform"
-MGMT_HEADER      = "Monitoring and Management Interface for the Java Platform"
-# MGMT_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by attach target
-#
-
-ATTACH_SOURCEPATH  = $(TOPDIR)/src/share/classes
-ATTACH_DOCDIR      = $(DOCSDIR)/jdk/api/attach/spec
-ATTACH_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)                        	\
-		   -encoding ascii                               	\
-                   -nodeprecatedlist                             	\
-		   -d $(ATTACH_DOCDIR)					\
-                   -sourcepath $(ATTACH_SOURCEPATH)                	\
-                   -windowtitle $(ATTACH_WINDOWTITLE)               	\
-                   -doctitle $(ATTACH_DOCTITLE)                     	\
-                   -header $(ATTACH_HEADER)                         	\
-		   -linkoffline ../../../../api $(DOCSDIR)/api/
-ATTACH_WINDOWTITLE = "Attach API"
-ATTACH_DOCTITLE    = "Attach API"
-ATTACH_HEADER      = "Attach API"
-# ATTACH_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by jconsole target
-#
-
-JCONSOLE_SOURCEPATH  = $(TOPDIR)/src/share/classes
-JCONSOLE_DOCDIR      = $(DOCSDIR)/jdk/api/jconsole/spec
-JCONSOLE_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)                        	\
-		   -encoding ascii                               	\
-                   -nodeprecatedlist                             	\
-		   -d $(JCONSOLE_DOCDIR)				\
-                   -sourcepath $(JCONSOLE_SOURCEPATH)                	\
-                   -windowtitle $(JCONSOLE_WINDOWTITLE)               	\
-                   -doctitle $(JCONSOLE_DOCTITLE)                     	\
-                   -header $(JCONSOLE_HEADER)                         	\
-		   -linkoffline ../../../../api $(DOCSDIR)/api/
-JCONSOLE_WINDOWTITLE = "JConsole API"
-JCONSOLE_DOCTITLE    = "JConsole API"
-JCONSOLE_HEADER      = "JConsole API"
-# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Variables used by treeapidocs target
-#
-
-TREEAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS)		        \
-                    -encoding ascii			        \
-                    -doctitle $(TREEAPI_JAVADOCTITLE)            \
-                    -windowtitle $(TREEAPI_JAVADOCWINDOWTITLE)   \
-                    -header $(TREEAPI_JAVADOCHEADER)             \
-                    -bottom $(TREEAPI_JAVADOCBOTTOM)             \
-                    -group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP) 
-#
-#	            -overview $(TREEAPI_OVERVIEW)
-#
-TREEAPI_JAVADOCTITLE = 'Compiler Tree API'
-TREEAPI_JAVADOCWINDOWTITLE = 'Compiler Tree API'
-TREEAPI_JAVADOCHEADER = '<strong>Compiler Tree API</strong>'
-TREEAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>'
-TREEAPI_GROUPNAME = "Packages"
-TREEAPI_OVERVIEW = $(SHARE_SRC)/classes/com/sun/source/overview.html
-TREEAPI_REGEXP = "com.sun.source.*"
-TREEAPI_DESTDIR = $(DOCSDIR)/jdk/api/javac/tree
-TREEAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/
-# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-#
-# Path where javadoc should find source files for release docs
-#
-RELEASEDOCS_SRCPATH = "$(SHARE_SRC)/classes$(CLASSPATH_SEPARATOR)$(PLATFORM_SRC)/classes$(CLASSPATH_SEPARATOR)$(GENSRCDIR)$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/doc/stub$(CLASSPATH_SEPARATOR)$(CLOSED_SRC)/share/classes$(CLASSPATH_SEPARATOR)$(IMPORTSRCDIR)"
+#################################################################
 
 #
 # CORE_PKGS environment variable has been moved to the following file
@@ -463,30 +234,13 @@
 #
 include NON_CORE_PKGS.gmk
 
-# Targets for all APIs other than the core platform APIs
-ALL_OTHER_TARGETS = \
-    mirrordocs \
-    docletapidocs \
-    tagletapidocs \
-    domapidocs \
-    jpdadocs \
-    jaasdocs \
-    jgssdocs \
-    smartcardiodocs \
-    tracingdocs \
-    httpserverdocs  \
-    sctpdocs \
-    mgmtdocs \
-    attachdocs \
-    jconsoledocs \
-    treeapidocs
+#################################################################
 
-.PHONY: all docs
-all docs: coredocs otherdocs
+#
+# Default target is same as docs target, create core api and all others it can
+#
 
-.PHONY: otherdocs
-otherdocs: ${ALL_OTHER_TARGETS}
-
+all docs: coredocs otherdocs
 
 #################################################################
 # Production Targets -- USE THESE TARGETS WHEN:
@@ -496,9 +250,9 @@
 #       the downloaded doc bundle.
 #
 # See:  Notes.html#releaseTargets
-# Note: Spaces preceed ifdef/ifndef indents. Tabs preceed target commands (!)
+# Note: Spaces precede ifdef/ifndef indents. Tabs precede target commands (!)
 #
-.PHONY: sanitycheckcoredocs
+
 sanitycheckcoredocs:
 	@$(ECHO) ""
 	@$(ECHO) "Building core api docs with these values:"
@@ -512,199 +266,942 @@
 	exit 1
   endif
 
-# Maximize performance and ensure that build number & milestone are set.
-.PHONY: rel-coredocs
-rel-coredocs: sanitycheckcoredocs
-	@# ######## release version of core packages ########
-	$(MAKE) coredocs
+#############################################################
+#
+# coredocs
+#
+COREAPI_DOCTITLE  = Java$(TRADEMARK) Platform, Standard Edition \
+$(JDK_MINOR_VERSION)<br>API Specification
+COREAPI_WINDOWTITLE  = Java Platform SE $(JDK_MINOR_VERSION)
+COREAPI_HEADER = \
+<strong>Java$(TRADEMARK)&nbsp;Platform<br>Standard&nbsp;Ed.&nbsp;$(JDK_MINOR_VERSION)</strong>
+
+# Ignored tags
+IGNORED_TAGS =	beaninfo revised since.unbundled spec specdefault Note ToDo
+
+# Java language specification cite
+JLS3_CITE = <a href=\"$(JLS3_URL)\"> \
+		The Java Language Specification, Third Edition</a>
+TAG_JLS3 = -tag 'jls3:a:See <cite>$(JLS3_CITE)</cite>:'
+
+TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3)
+
+# Overview file for core apis
+COREAPI_OVERVIEW = $(SHARE_SRC)/classes/overview-core.html
+
+# The index.html, options, and packages files
+COREAPI_INDEX_FILE    = $(COREAPI_DOCSDIR)/index.html
+COREAPI_OPTIONS_FILE  = $(DOCSTMPDIR)/coredocs.options
+COREAPI_PACKAGES_FILE = $(DOCSTMPDIR)/coredocs.packages
+
+coredocs: $(COREAPI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(COREAPI_INDEX_FILE): GET2DOCSDIR=..
 
-.PHONY: rel-docs
-rel-docs: rel-coredocs ${ALL_OTHER_TARGETS}
+# Run javadoc if the index file is out of date or missing
+$(COREAPI_INDEX_FILE): $(COREAPI_OPTIONS_FILE) $(COREAPI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(COREAPI_OPTIONS_FILE),$(COREAPI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(COREAPI_OPTIONS_FILE) @$(COREAPI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(COREAPI_OPTIONS_FILE): $(COREAPI_OVERVIEW)
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "$(TAGS)"						; \
+	  $(ECHO) "-encoding ISO-8859-1"				; \
+	  $(ECHO) "-splitIndex"						; \
+	  $(ECHO) "-overview $(COREAPI_OVERVIEW)" 			; \
+	  $(ECHO) "-doctitle '$(COREAPI_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(COREAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(COREAPI_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(COREAPI_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+        ) >> $@
+ifdef COREAPI_TOP_EARLYACCESS
+	@$(ECHO) "-top '$(COREAPI_TOP_EARLYACCESS)'" >> $@
+endif
+
+# Create a file with the package names in it
+$(COREAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(CORE_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(CORE_PKGS))
+
+#############################################################
 #
-# end of production targets
-#############################################################
+# mirrordocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+  ALL_OTHER_TARGETS += mirrordocs
+endif
 
-.PHONY: coredocs
-coredocs:
-	@# ######## core packages #######################
-	$(RM) -r $(DOCSDIR)/api
-	$(MKDIR) -p $(DOCSDIR)/api
-	$(JAVADOC_CMD) $(CORE_JAVADOCFLAGS)            \
-                   -d $(DOCSDIR)/api                   \
-                   -sourcepath $(RELEASEDOCS_SRCPATH)  \
-                   $(CORE_PKGS)
+MIRROR_DOCDIR      := $(JDK_API_DOCSDIR)/apt/mirror
+MIRROR2COREAPI     := ../../$(JDKJRE2COREAPI)
+MIRROR_DOCTITLE    := Mirror API
+MIRROR_WINDOWTITLE := Mirror API
+MIRROR_HEADER      := <strong>Mirror API</strong>
+MIRROR_BOTTOM      := $(call CommonBottom,$(MIRROR_FIRST_COPYRIGHT_YEAR))
+MIRROR_GROUPNAME   := Packages
+MIRROR_OVERVIEW    := $(IMPORTSRCDIR)/com/sun/mirror/overview.html
+MIRROR_REGEXP      := com.sun.mirror.*
+# MIRROR_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+MIRROR_INDEX_FILE    = $(MIRROR_DOCDIR)/index.html
+MIRROR_OPTIONS_FILE  = $(DOCSTMPDIR)/mirror.options
+MIRROR_PACKAGES_FILE = $(DOCSTMPDIR)/mirror.packages
+
+mirrordocs: $(MIRROR_INDEX_FILE)
+
+# Set relative location to core api document root
+$(MIRROR_INDEX_FILE): GET2DOCSDIR=$(MIRROR2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(MIRROR_INDEX_FILE): $(MIRROR_OPTIONS_FILE) $(MIRROR_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(MIRROR_OPTIONS_FILE),$(MIRROR_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(MIRROR_OPTIONS_FILE) @$(MIRROR_PACKAGES_FILE)
 
-.PHONY: mirrordocs
-mirrordocs:
-	@# ######## mirror api for apt ##################
-	$(RM) -r $(MIRROR_DESTDIR)
-	$(MKDIR) -p $(MIRROR_DESTDIR)
-	$(JAVADOC_CMD) $(MIRROR_JAVADOCFLAGS)             \
-		   -d $(MIRROR_DESTDIR)               \
-		   -sourcepath $(RELEASEDOCS_SRCPATH) \
-		   $(MIRROR_LINKOPT)                  \
-		   $(MIRROR_PKGS)
+# Create file with javadoc options in it
+$(MIRROR_OPTIONS_FILE): $(MIRROR_OVERVIEW)
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-overview $(MIRROR_OVERVIEW)" 			; \
+	  $(ECHO) "-doctitle '$(MIRROR_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(MIRROR_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(MIRROR_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(MIRROR_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP)"		; \
+	  $(ECHO) "-linkoffline $(MIRROR2COREAPI) $(COREAPI_DOCSDIR)/"; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(MIRROR_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(MIRROR_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(MIRROR_PKGS))
+
+#############################################################
+#
+# docletapidocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+  ALL_OTHER_TARGETS += docletapidocs
+endif
+
+DOCLETAPI_DOCDIR       := $(JDK_API_DOCSDIR)/javadoc/doclet
+DOCLETAPI2COREAPI      := ../../$(JDKJRE2COREAPI)
+DOCLETAPI_DOCTITLE     := Doclet API
+DOCLETAPI_WINDOWTITLE  := Doclet API
+DOCLETAPI_HEADER       := <strong>Doclet API</strong>
+DOCLETAPI_BOTTOM       := $(call CommonTrademarkBottom,$(DOCLETAPI_FIRST_COPYRIGHT_YEAR))
+DOCLETAPI_GROUPNAME    := Packages
+DOCLETAPI_REGEXP       := com.sun.javadoc
+# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+DOCLETAPI_INDEX_FILE    = $(DOCLETAPI_DOCDIR)/index.html
+DOCLETAPI_OPTIONS_FILE  = $(DOCSTMPDIR)/docletapi.options
+DOCLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/docletapi.packages
+
+docletapidocs: $(DOCLETAPI_INDEX_FILE)
 
-.PHONY: docletapidocs
-docletapidocs:
-	@# ######## doclet api ############################
-	$(RM) -r $(DOCSDIR)/jdk/api/javadoc/doclet
-	$(MKDIR) -p $(DOCSDIR)/jdk/api/javadoc/doclet
-	$(JAVADOC_CMD) $(DOCLETAPI_JAVADOCFLAGS)                 \
-                   -d $(DOCSDIR)/jdk/api/javadoc/doclet      \
-                   -sourcepath $(RELEASEDOCS_SRCPATH)        \
-                   $(DOCLETAPI_LINKOPT)                      \
-                   $(DOCLETAPI_PKGS)
+# Set relative location to core api document root
+$(DOCLETAPI_INDEX_FILE): GET2DOCSDIR=$(DOCLETAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(DOCLETAPI_INDEX_FILE): $(DOCLETAPI_OPTIONS_FILE) $(DOCLETAPI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(DOCLETAPI_OPTIONS_FILE),$(DOCLETAPI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(DOCLETAPI_OPTIONS_FILE) @$(DOCLETAPI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(DOCLETAPI_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-breakiterator"					; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-doctitle '$(DOCLETAPI_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(DOCLETAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(DOCLETAPI_HEADER)$(DRAFT_HEADER)'"	; \
+	  $(ECHO) "-bottom '$(DOCLETAPI_BOTTOM)$(DRAFT_BOTTOM)'"	; \
+	  $(ECHO) "-group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP)"	; \
+	  $(ECHO) "-linkoffline $(DOCLETAPI2COREAPI) $(COREAPI_DOCSDIR)/"; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(DOCLETAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(DOCLETAPI_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(DOCLETAPI_PKGS))
+
+#############################################################
+#
+# tagletapidocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+  ALL_OTHER_TARGETS += tagletapidocs
+endif
+
+TAGLETAPI_DOCDIR   := $(JDK_API_DOCSDIR)/javadoc/taglet
+TAGLETAPI2COREAPI  := ../../$(JDKJRE2COREAPI)
+TAGLETAPI_BOTTOM   := $(call CommonTrademarkBottom,$(TAGLETAPI_FIRST_COPYRIGHT_YEAR))
+# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk
+
+# Temporary directory (special generation rules)
+TAGLETAPI_TEMPDIR       = $(DOCSTMPDIR)/taglets_temp
+
+# The index.html, options, and packages files
+TAGLETAPI_INDEX_FILE    = $(TAGLETAPI_DOCDIR)/index.html
+TAGLETAPI_OPTIONS_FILE  = $(DOCSTMPDIR)/tagletapi.options
+TAGLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/tagletapi.packages
+
+tagletapidocs: $(TAGLETAPI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(TAGLETAPI_INDEX_FILE): GET2DOCSDIR=$(TAGLETAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(TAGLETAPI_INDEX_FILE): $(TAGLETAPI_OPTIONS_FILE) $(TAGLETAPI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(RM) -r $(TAGLETAPI_TEMPDIR)
+	$(MKDIR) -p $(TAGLETAPI_TEMPDIR)
+	$(call JavadocSummary,$(TAGLETAPI_OPTIONS_FILE),$(TAGLETAPI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(TAGLETAPI_TEMPDIR) \
+	  @$(TAGLETAPI_OPTIONS_FILE) @$(TAGLETAPI_PACKAGES_FILE)
+	cp -r $(TAGLETAPI_TEMPDIR)/com $(@D)
+	cp $(TAGLETAPI_TEMPDIR)/stylesheet.css $(@D)
+	$(RM) -r $(TAGLETAPI_TEMPDIR)
 
-.PHONY: tagletapidocs
-tagletapidocs:
-	@# ######## taglet api ############################
-	$(RM) -r $(DOCSDIR)/jdk/api/javadoc/taglet
-	$(MKDIR) -p $(DOCSDIR)/jdk/api/javadoc/taglet
-	$(RM) -r $(DOCSTMPDIR)
-	$(MKDIR) -p $(DOCSTMPDIR)
-	$(JAVADOC_CMD) $(TAGLETAPI_JAVADOCFLAGS)                 \
-                   -d $(DOCSTMPDIR)                          \
-                   -linkoffline ../../../../api $(DOCSDIR)/api/ \
-                   $(IMPORTSRCDIR)/$(TAGLETAPI_FILE)
-	cp -r $(DOCSTMPDIR)/com $(DOCSDIR)/jdk/api/javadoc/taglet
-	cp $(DOCSTMPDIR)/stylesheet.css $(DOCSDIR)/jdk/api/javadoc/taglet
-	$(RM) -r $(DOCSTMPDIR)
+# Create file with javadoc options in it
+$(TAGLETAPI_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nonavbar"						; \
+	  $(ECHO) "-noindex"						; \
+	  $(ECHO) "-bottom '$(TAGLETAPI_BOTTOM)$(DRAFT_BOTTOM)'"			; \
+	  $(ECHO) "-linkoffline $(TAGLETAPI2COREAPI) $(COREAPI_DOCSDIR)/"; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(TAGLETAPI_PACKAGES_FILE): $(IMPORTSRCDIR)/$(TAGLETAPI_FILE)
+	$(prep-target)
+	@($(ECHO) "$(IMPORTSRCDIR)/$(TAGLETAPI_FILE)" ) > $@
+
+#############################################################
+#
+# domapidocs
+#
+
+ALL_OTHER_TARGETS += domapidocs
+
+DOMAPI_DOCDIR       := $(JRE_API_DOCSDIR)/plugin/dom
+DOMAPI2COREAPI      := ../../$(JDKJRE2COREAPI)
+DOMAPI_DOCTITLE     := Common DOM API
+DOMAPI_WINDOWTITLE  := Common DOM API
+DOMAPI_HEADER       := <strong>Common DOM API</strong>
+DOMAPI_BOTTOM       := $(call CommonTrademarkBottom,$(DOMAPI_FIRST_COPYRIGHT_YEAR))
+DOMAPI_GROUPNAME    := Packages
+DOMAPI_REGEXP       := com.sun.java.browser.dom:org.w3c.dom*
+# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+DOMAPI_INDEX_FILE    = $(DOMAPI_DOCDIR)/index.html
+DOMAPI_OPTIONS_FILE  = $(DOCSTMPDIR)/domapi.options
+DOMAPI_PACKAGES_FILE = $(DOCSTMPDIR)/domapi.packages
 
-.PHONY: domapidocs
-domapidocs:
-	@# ######## dom api ############################
-	$(RM) -r $(DOCSDIR)/jre/api/plugin/dom
-	$(MKDIR) -p $(DOCSDIR)/jre/api/plugin/dom
-	$(JAVADOC_CMD) $(DOMAPI_JAVADOCFLAGS)		     \
-                   -d $(DOCSDIR)/jre/api/plugin/dom            \
-                   -sourcepath $(RELEASEDOCS_SRCPATH)        \
-                   -linkoffline ../../../../api $(DOCSDIR)/api/ \
-                   $(DOMAPI_PKGS)
+domapidocs: $(DOMAPI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(DOMAPI_INDEX_FILE): GET2DOCSDIR=$(DOMAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(DOMAPI_INDEX_FILE): $(DOMAPI_OPTIONS_FILE) $(DOMAPI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(DOMAPI_OPTIONS_FILE),$(DOMAPI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(DOMAPI_OPTIONS_FILE) @$(DOMAPI_PACKAGES_FILE)
 
-.PHONY: jpdadocs
+# Create file with javadoc options in it
+$(DOMAPI_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-splitIndex"						; \
+	  $(ECHO) "-doctitle '$(DOMAPI_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(DOMAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(DOMAPI_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(DOMAPI_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP)"		; \
+	  $(ECHO) "-linkoffline $(DOMAPI2COREAPI) $(COREAPI_DOCSDIR)/" 	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(DOMAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(DOMAPI_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(DOMAPI_PKGS))
+
+#############################################################
+#
+# jpdadocs
+#
+
+ALL_OTHER_TARGETS += jpdadocs
+
 jpdadocs: jdidocs jdwpdocs jvmtidocs
 
-.PHONY: jdidocs
-jdidocs:
-	@# ######## jdi #################################
-	$(RM) -r $(DOCSDIR)/jdk/api/jpda/jdi
-	$(MKDIR) -p $(DOCSDIR)/jdk/api/jpda/jdi
-	$(JAVADOC_CMD) $(JDI_JAVADOCFLAGS)                       \
-                   $(JDI_PKGS)
+#############################################################
+#
+# jdidocs
+#
+
+ALL_OTHER_TARGETS += jdidocs
+
+JDI_DOCDIR      := $(JDK_API_DOCSDIR)/jpda/jdi
+JDI2COREAPI     := ../../$(JDKJRE2COREAPI)
+JDI_DOCTITLE    := Java$(TRADEMARK) Debug Interface
+JDI_WINDOWTITLE := Java Debug Interface
+JDI_HEADER      := <strong>Java Debug Interface</strong>
+JDI_BOTTOM      := $(call CommonBottom,$(JDI_FIRST_COPYRIGHT_YEAR))
+JDI_OVERVIEW    := $(SHARE_SRC)/classes/jdi-overview.html
+# JDI_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+JDI_INDEX_FILE    = $(JDI_DOCDIR)/index.html
+JDI_OPTIONS_FILE  = $(DOCSTMPDIR)/jdi.options
+JDI_PACKAGES_FILE = $(DOCSTMPDIR)/jdi.packages
+
+jdidocs: $(JDI_INDEX_FILE)
+
+# Set relative location to core api document root
+$(JDI_INDEX_FILE): GET2DOCSDIR=$(JDI2COREAPI)/..
 
+# Run javadoc if the index file is out of date or missing
+$(JDI_INDEX_FILE): $(JDI_OPTIONS_FILE) $(JDI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(JDI_OPTIONS_FILE),$(JDI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(JDI_OPTIONS_FILE) @$(JDI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JDI_OPTIONS_FILE): $(JDI_OVERVIEW)
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-overview $(JDI_OVERVIEW)" 				; \
+	  $(ECHO) "-doctitle '$(JDI_DOCTITLE)'"				; \
+	  $(ECHO) "-windowtitle '$(JDI_WINDOWTITLE) $(DRAFT_WINTITLE)'"	; \
+	  $(ECHO) "-header '$(JDI_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(JDI_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(JDI2COREAPI) $(COREAPI_DOCSDIR)/" 	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(JDI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JDI_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(JDI_PKGS))
+
+#############################################################
+#
+# jdwpdocs
+#
+
+ALL_OTHER_TARGETS += jdwpdocs
+
+JDWP_DOCDIR     = $(PLATFORM_DOCSDIR)/jpda/jdwp
 JDWP_SPEC       = $(BUILDDIR)/jpda/jdwp/jdwp.spec
-JDWP_DOC        = $(DOCSDIR)/platform/jpda/jdwp/jdwp-protocol.html
 JDWPGEN_JARFILE = $(BUILDTOOLJARDIR)/jdwpgen.jar
 
-.PHONY: jdwpdocs
-jdwpdocs: $(JDWP_DOC)
+jdwpdocs: $(JDWP_DOCDIR)/jdwp-protocol.html
+$(JDWP_DOCDIR)/jdwp-protocol.html: $(JDWPGEN_JARFILE) $(JDWP_SPEC)
+	$(prep-javadoc)
+	$(BOOT_JAVA_CMD) -jar $(JDWPGEN_JARFILE) $(JDWP_SPEC) -doc $@
 
-$(JDWP_DOC): $(JDWPGEN_JARFILE) $(JDWP_SPEC)
-	$(prep-target)
-	$(BOOT_JAVA_CMD) -jar $(JDWPGEN_JARFILE) $(JDWP_SPEC) -doc $(JDWP_DOC)
+#############################################################
+#
+# jvmtidocs
+#
+
+ALL_OTHER_TARGETS += jvmtidocs
 
-.PHONY: jvmtidocs
-jvmtidocs:
-	@# ######## jvmti #################################
-	@if [ -f $(JVMTI_HTML) ] ; then \
-	  $(RM) -r $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
-	  $(MKDIR) -p $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
-	  $(ECHO) $(CP) $(JVMTI_HTML) $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
-	  $(CP) $(JVMTI_HTML) $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \
-	else \
-	  $(ECHO) "WARNING: Generated jvmti file does not exist: $(JVMTI_HTML)"; \
+JVMTI_DOCDIR      = $(PLATFORM_DOCSDIR)/jvmti
+JVMTI_HTML        = $(HOTSPOT_DOCS_IMPORT_PATH)/platform/jvmti/jvmti.html
+
+jvmtidocs:  $(JVMTI_DOCDIR)/jvmti.html
+$(JVMTI_DOCDIR)/jvmti.html:
+	@$(prep-javadoc)
+	@if [ -f $(JVMTI_HTML) ] ; then		                           \
+	  $(ECHO) "$(CP) $(JVMTI_HTML) $@";                 	           \
+	  $(CP) $(JVMTI_HTML) $@; 	                 	           \
+	else 						                   \
+	  $(ECHO) "WARNING: Generated file does not exist: $(JVMTI_HTML)"; \
 	fi
 
-.PHONY: jaasdocs
-jaasdocs:
-	@# ######## api-jaas ############################
-	$(RM) -r $(JAAS_DOCDIR)
-	$(MKDIR) -p $(JAAS_DOCDIR)
-	$(JAVADOC_CMD) $(JAAS_JAVADOCFLAGS)                     \
-		   $(JAAS_PKGS)
+#############################################################
+#
+# jaasdocs
+#
+
+ALL_OTHER_TARGETS += jaasdocs
+
+JAAS_DOCDIR	 := $(JRE_API_DOCSDIR)/security/jaas/spec
+JAAS2COREAPI     := ../../../$(JDKJRE2COREAPI)
+JAAS_DOCTITLE    := Java$(TRADEMARK) Authentication and Authorization Service
+JAAS_WINDOWTITLE := Java Authentication and Authorization Service
+JAAS_HEADER      := <strong>Java Authentication and Authorization Service</strong>
+JAAS_BOTTOM      := $(call CommonBottom,$(JAAS_FIRST_COPYRIGHT_YEAR))
+# JAAS_PKGS is located in NON_CORE_PKGS.gmk
+JAAS_OVERVIEW    := $(SHARE_SRC)/classes/com/sun/security/auth/jaas-overview.html
+
+# The index.html, options, and packages files
+JAAS_INDEX_FILE    = $(JAAS_DOCDIR)/index.html
+JAAS_OPTIONS_FILE  = $(DOCSTMPDIR)/jaas.options
+JAAS_PACKAGES_FILE = $(DOCSTMPDIR)/jaas.packages
+
+jaasdocs: $(JAAS_INDEX_FILE)
+
+# Set relative location to core api document root
+$(JAAS_INDEX_FILE): GET2DOCSDIR=$(JAAS2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JAAS_INDEX_FILE): $(JAAS_OPTIONS_FILE) $(JAAS_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(JAAS_OPTIONS_FILE),$(JAAS_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(JAAS_OPTIONS_FILE) @$(JAAS_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JAAS_OPTIONS_FILE): $(JAAS_OVERVIEW)
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-overview $(JAAS_OVERVIEW)" 				; \
+	  $(ECHO) "-doctitle '$(JAAS_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(JAAS_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \
+	  $(ECHO) "-header '$(JAAS_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(JAAS_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(JAAS2COREAPI) $(COREAPI_DOCSDIR)/" 	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(JAAS_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JAAS_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(JAAS_PKGS))
+
+#############################################################
+#
+# jgssdocs
+#
+
+ALL_OTHER_TARGETS += jgssdocs
+
+JGSS_DOCDIR	 := $(JRE_API_DOCSDIR)/security/jgss/spec
+JGSS2COREAPI     := ../../../$(JDKJRE2COREAPI)
+JGSS_DOCTITLE    := Java$(TRADEMARK) GSS-API Utilities
+JGSS_WINDOWTITLE := Java GSS-API Utilities
+JGSS_HEADER      := <strong>Java GSS-API Utilities</strong>
+JGSS_BOTTOM      := $(call CommonBottom,$(JGSS_FIRST_COPYRIGHT_YEAR))
+JGSS_OVERVIEW    := $(SHARE_SRC)/classes/com/sun/security/jgss/jgss-overview.html
+# JGSS_PKGS is located in NON_CORE_PKGS.gmk
 
-.PHONY: jgssdocs
-jgssdocs:
-	@# ######## api-jgss ############################
-	$(RM) -r $(JGSS_DOCDIR)
-	$(MKDIR) -p $(JGSS_DOCDIR)
-	$(JAVADOC_CMD) $(JGSS_JAVADOCFLAGS)                     \
-		   $(JGSS_PKGS)
+# The index.html, options, and packages files
+JGSS_INDEX_FILE    = $(JGSS_DOCDIR)/index.html
+JGSS_OPTIONS_FILE  = $(DOCSTMPDIR)/jgss.options
+JGSS_PACKAGES_FILE = $(DOCSTMPDIR)/jgss.packages
+
+jgssdocs: $(JGSS_INDEX_FILE)
+
+# Set relative location to core api document root
+$(JGSS_INDEX_FILE): GET2DOCSDIR=$(JGSS2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JGSS_INDEX_FILE): $(JGSS_OPTIONS_FILE) $(JGSS_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(JGSS_OPTIONS_FILE),$(JGSS_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(JGSS_OPTIONS_FILE) @$(JGSS_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JGSS_OPTIONS_FILE): $(JGSS_OVERVIEW)
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-overview $(JGSS_OVERVIEW)" 				; \
+	  $(ECHO) "-doctitle '$(JGSS_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(JGSS_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \
+	  $(ECHO) "-header '$(JGSS_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(JGSS_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(JGSS2COREAPI) $(COREAPI_DOCSDIR)/" 	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(JGSS_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JGSS_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(JGSS_PKGS))
+
+#############################################################
+#
+# smartcardiodocs
+#
+
+ALL_OTHER_TARGETS += smartcardiodocs
+
+SMARTCARDIO_DOCDIR	:= $(JRE_API_DOCSDIR)/security/smartcardio/spec
+SMARTCARDIO2COREAPI     := ../../../$(JDKJRE2COREAPI)
+SMARTCARDIO_DOCTITLE    := Java$(TRADEMARK) Smart Card I/O
+SMARTCARDIO_WINDOWTITLE := Java Smart Card I/O
+SMARTCARDIO_HEADER      := <strong>Java Smart Card I/O</strong>
+SMARTCARDIO_BOTTOM      := $(call CommonBottom,$(SMARTCARDIO_FIRST_COPYRIGHT_YEAR))
+# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+SMARTCARDIO_INDEX_FILE    = $(SMARTCARDIO_DOCDIR)/index.html
+SMARTCARDIO_OPTIONS_FILE  = $(DOCSTMPDIR)/smartcardio.options
+SMARTCARDIO_PACKAGES_FILE = $(DOCSTMPDIR)/smartcardio.packages
+
+smartcardiodocs: $(SMARTCARDIO_INDEX_FILE)
+
+# Set relative location to core api document root
+$(SMARTCARDIO_INDEX_FILE): GET2DOCSDIR=$(SMARTCARDIO2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(SMARTCARDIO_INDEX_FILE): $(SMARTCARDIO_OPTIONS_FILE) $(SMARTCARDIO_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(SMARTCARDIO_OPTIONS_FILE),$(SMARTCARDIO_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(SMARTCARDIO_OPTIONS_FILE) @$(SMARTCARDIO_PACKAGES_FILE)
 
-.PHONY: smartcardiodocs
-smartcardiodocs:
-	@# ######## api-smartcardio ############################
-	$(RM) -r $(SMARTCARDIO_DOCDIR)
-	$(MKDIR) -p $(SMARTCARDIO_DOCDIR)
-	$(JAVADOC_CMD) $(SMARTCARDIO_JAVADOCFLAGS)                     \
-		   $(SMARTCARDIO_PKGS)
+# Create file with javadoc options in it
+$(SMARTCARDIO_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-doctitle '$(SMARTCARDIO_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(SMARTCARDIO_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(SMARTCARDIO_HEADER)$(DRAFT_HEADER)'"	; \
+	  $(ECHO) "-bottom '$(SMARTCARDIO_BOTTOM)$(DRAFT_BOTTOM)'"	; \
+	  $(ECHO) "-linkoffline $(SMARTCARDIO2COREAPI) $(COREAPI_DOCSDIR)/"; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(SMARTCARDIO_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(SMARTCARDIO_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(SMARTCARDIO_PKGS))
+
+#############################################################
+#
+# httpserverdocs
+#
+
+ALL_OTHER_TARGETS += httpserverdocs
+
+HTTPSERVER_DOCDIR      := $(JRE_API_DOCSDIR)/net/httpserver/spec
+HTTPSERVER2COREAPI     := ../../../$(JDKJRE2COREAPI)
+HTTPSERVER_DOCTITLE    := Java$(TRADEMARK) HTTP Server
+HTTPSERVER_WINDOWTITLE := Java HTTP Server
+HTTPSERVER_HEADER      := <strong>Java HTTP Server</strong>
+HTTPSERVER_BOTTOM      := $(call CommonBottom,$(HTTPSERVER_FIRST_COPYRIGHT_YEAR))
+# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk
+
+HTTPSERVER_INDEX_HTML    = $(HTTPSERVER_DOCDIR)/index.html
+HTTPSERVER_OPTIONS_FILE  = $(DOCSTMPDIR)/httpserver.options
+HTTPSERVER_PACKAGES_FILE = $(DOCSTMPDIR)/httpserver.packages
+
+httpserverdocs: $(HTTPSERVER_INDEX_HTML)
+
+# Set relative location to core api document root
+$(HTTPSERVER_INDEX_HTML): GET2DOCSDIR=$(HTTPSERVER2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(HTTPSERVER_INDEX_HTML): $(HTTPSERVER_OPTIONS_FILE) $(HTTPSERVER_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(HTTPSERVER_OPTIONS_FILE),$(HTTPSERVER_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(HTTPSERVER_OPTIONS_FILE) @$(HTTPSERVER_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(HTTPSERVER_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-doctitle '$(HTTPSERVER_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(HTTPSERVER_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(HTTPSERVER_HEADER)$(DRAFT_HEADER)'"	; \
+	  $(ECHO) "-bottom '$(HTTPSERVER_BOTTOM)$(DRAFT_BOTTOM)'"	; \
+	  $(ECHO) "-linkoffline $(HTTPSERVER2COREAPI) $(COREAPI_DOCSDIR)/"; \
+        ) >> $@
 
-.PHONY: tracingdocs
-tracingdocs:
-	@# ######## api-tracing ############################
-	$(RM) -r $(TRACING_DOCDIR)
-	$(MKDIR) -p $(TRACING_DOCDIR)
-	$(JAVADOC_CMD) $(TRACING_JAVADOCFLAGS)                     \
-		   $(TRACING_PKGS)
+# Create a file with the package names in it
+$(HTTPSERVER_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(HTTPSERVER_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(HTTPSERVER_PKGS))
+
+#############################################################
+#
+# mgmtdocs
+#
+
+ALL_OTHER_TARGETS += mgmtdocs
+
+MGMT_DOCDIR	 := $(JRE_API_DOCSDIR)/management/extension
+MGMT2COREAPI     := ../../$(JDKJRE2COREAPI)
+JVM_MIB_NAME     := JVM-MANAGEMENT-MIB.mib
+JVM_MIB_SRC      := $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME)
+MGMT_DOCTITLE    := Monitoring and Management Interface for the Java$(TRADEMARK) Platform
+MGMT_WINDOWTITLE := Monitoring and Management Interface for the Java Platform
+MGMT_HEADER      := <strong>Monitoring and Management Interface for the Java Platform</strong>
+MGMT_BOTTOM      := $(call CommonBottom,$(MGMT_FIRST_COPYRIGHT_YEAR))
+MGMT_OVERVIEW    := $(SHARE_SRC)/classes/com/sun/management/mgmt-overview.html
+# MGMT_PKGS is located in NON_CORE_PKGS.gmk
+
+# The index.html, options, and packages files
+MGMT_INDEX_FILE    = $(MGMT_DOCDIR)/index.html
+MGMT_OPTIONS_FILE  = $(DOCSTMPDIR)/mgmt.options
+MGMT_PACKAGES_FILE = $(DOCSTMPDIR)/mgmt.packages
+
+mgmtdocs: $(MGMT_INDEX_FILE)
+
+# Set relative location to core api document root
+$(MGMT_INDEX_FILE): GET2DOCSDIR=$(MGMT2COREAPI)/..
 
-.PHONY: httpserverdocs
-httpserverdocs:
-	@# ######## api-httpserver #######################
-	$(RM) -r $(HTTPSERVER_DOCDIR)
-	$(MKDIR) -p $(HTTPSERVER_DOCDIR)
-	$(JAVADOC_CMD) $(HTTPSERVER_JAVADOCFLAGS)                     \
-		   $(HTTPSERVER_PKGS)
+# Run javadoc if the index file is out of date or missing
+$(MGMT_INDEX_FILE): $(MGMT_OPTIONS_FILE) $(MGMT_PACKAGES_FILE)
+	$(prep-javadoc)
+	@if [ -f $(JVM_MIB_SRC) ] ; then 				\
+	  $(ECHO) "$(CP) $(JVM_MIB_SRC) $(@D)/.."; 			\
+	  $(CP) $(JVM_MIB_SRC) $(@D)/.. ; 				\
+	else 								\
+	  $(ECHO) "WARNING: File $(JVM_MIB_NAME) not available."; 	\
+	fi
+	$(call JavadocSummary,$(MGMT_OPTIONS_FILE),$(MGMT_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(MGMT_OPTIONS_FILE) @$(MGMT_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(MGMT_OPTIONS_FILE): $(MGMT_OVERVIEW)
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-overview $(MGMT_OVERVIEW)" 				; \
+	  $(ECHO) "-doctitle '$(MGMT_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(MGMT_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \
+	  $(ECHO) "-header '$(MGMT_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(MGMT_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(MGMT2COREAPI) $(COREAPI_DOCSDIR)/" 	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(MGMT_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(MGMT_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(MGMT_PKGS))
+
+#############################################################
+#
+# attachdocs
+#
+
+ALL_OTHER_TARGETS += attachdocs
 
-.PHONY: sctpdocs
-sctpdocs:
-	@# ######## api-sctp #######################
-	$(RM) -r $(SCTPAPI_DOCDIR)
-	$(MKDIR) -p $(SCTPAPI_DOCDIR)
-	$(JAVADOC_CMD) $(SCTPAPI_JAVADOCFLAGS)                     \
-		$(SCTPAPI_PKGS)
+ATTACH_DOCDIR      := $(JDK_API_DOCSDIR)/attach/spec
+ATTACH2COREAPI     := ../../$(JDKJRE2COREAPI)
+ATTACH_DOCTITLE    := Attach API
+ATTACH_WINDOWTITLE := Attach API
+ATTACH_HEADER      := <strong>Attach API</strong>
+ATTACH_BOTTOM      := $(call CommonBottom,$(ATTACH_FIRST_COPYRIGHT_YEAR))
+# ATTACH_PKGS is located in NON_CORE_PKGS.gmk
+
+ATTACH_INDEX_HTML    = $(ATTACH_DOCDIR)/index.html
+ATTACH_OPTIONS_FILE  = $(DOCSTMPDIR)/attach.options
+ATTACH_PACKAGES_FILE = $(DOCSTMPDIR)/attach.packages
+
+attachdocs: $(ATTACH_INDEX_HTML)
+
+# Set relative location to core api document root
+$(ATTACH_INDEX_HTML): GET2DOCSDIR=$(ATTACH2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(ATTACH_INDEX_HTML): $(ATTACH_OPTIONS_FILE) $(ATTACH_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(ATTACH_OPTIONS_FILE),$(ATTACH_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(ATTACH_OPTIONS_FILE) @$(ATTACH_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(ATTACH_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-doctitle '$(ATTACH_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(ATTACH_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(ATTACH_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(ATTACH_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(ATTACH2COREAPI) $(COREAPI_DOCSDIR)/"	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(ATTACH_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(ATTACH_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(ATTACH_PKGS))
+
+#############################################################
+#
+# jconsoledocs
+#
+
+ALL_OTHER_TARGETS += jconsoledocs
+
+JCONSOLE_DOCDIR      := $(JDK_API_DOCSDIR)/jconsole/spec
+JCONSOLE2COREAPI     := ../../$(JDKJRE2COREAPI)
+JCONSOLE_DOCTITLE    := JConsole API
+JCONSOLE_WINDOWTITLE := JConsole API
+JCONSOLE_HEADER      := <strong>JConsole API</strong>
+JCONSOLE_BOTTOM      := $(call CommonBottom,$(JCONSOLE_FIRST_COPYRIGHT_YEAR))
+# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk
+
+JCONSOLE_INDEX_HTML    = $(JCONSOLE_DOCDIR)/index.html
+JCONSOLE_OPTIONS_FILE  = $(DOCSTMPDIR)/jconsole.options
+JCONSOLE_PACKAGES_FILE = $(DOCSTMPDIR)/jconsole.packages
+
+jconsoledocs: $(JCONSOLE_INDEX_HTML)
 
-.PHONY: mgmtdocs
-mgmtdocs: $(COPY-MIB-TARGET)
-	@# ######## api-management ############################
-	$(RM) -r $(MGMT_EXT_DIR)
-	$(MKDIR) -p $(MGMT_EXT_DIR)
-	$(JAVADOC_CMD) $(MGMT_JAVADOCFLAGS)                     \
-		   $(MGMT_PKGS)
+# Set relative location to core api document root
+$(JCONSOLE_INDEX_HTML): GET2DOCSDIR=$(JCONSOLE2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JCONSOLE_INDEX_HTML): $(JCONSOLE_OPTIONS_FILE) $(JCONSOLE_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(JCONSOLE_OPTIONS_FILE),$(JCONSOLE_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(JCONSOLE_OPTIONS_FILE) @$(JCONSOLE_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JCONSOLE_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-doctitle '$(JCONSOLE_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(JCONSOLE_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(JCONSOLE_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(JCONSOLE_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(JCONSOLE2COREAPI) $(COREAPI_DOCSDIR)/"; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(JCONSOLE_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JCONSOLE_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(JCONSOLE_PKGS))
 
-copy-mib:
-	@# ######## copy-snmp-mib ############################
-	$(RM) $(MGMT_DOCDIR)/$(JVM_MIB_NAME)
-	$(MKDIR) -p $(MGMT_DOCDIR)
-	$(CP) $(JVM_MIB_SRC) $(MGMT_DOCDIR)
+#############################################################
+#
+# treeapidocs
+#
+
+# Part of langtools
+ifdef LANGTOOLS_DIST
+  ALL_OTHER_TARGETS += treeapidocs
+endif
+
+TREEAPI_DOCDIR       := $(JDK_API_DOCSDIR)/javac/tree
+TREEAPI2COREAPI      := ../../$(JDKJRE2COREAPI)
+TREEAPI_DOCTITLE     := Compiler Tree API
+TREEAPI_WINDOWTITLE  := Compiler Tree API
+TREEAPI_HEADER       := <strong>Compiler Tree API</strong>
+TREEAPI_BOTTOM       := $(call CommonBottom,$(TREEAPI_FIRST_COPYRIGHT_YEAR))
+TREEAPI_GROUPNAME    := Packages
+TREEAPI_REGEXP       := com.sun.source.*
+# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+TREEAPI_INDEX_HTML    = $(TREEAPI_DOCDIR)/index.html
+TREEAPI_OPTIONS_FILE  = $(DOCSTMPDIR)/treeapi.options
+TREEAPI_PACKAGES_FILE = $(DOCSTMPDIR)/treeapi.packages
+
+treeapidocs: $(TREEAPI_INDEX_HTML)
+
+# Set relative location to core api document root
+$(TREEAPI_INDEX_HTML): GET2DOCSDIR=$(TREEAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(TREEAPI_INDEX_HTML): $(TREEAPI_OPTIONS_FILE) $(TREEAPI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(TREEAPI_OPTIONS_FILE),$(TREEAPI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(TREEAPI_OPTIONS_FILE) @$(TREEAPI_PACKAGES_FILE)
 
-.PHONY: attachdocs
-attachdocs:
-	@# ######## api-attach ############################
-	$(RM) -r $(ATTACH_DOCDIR)
-	$(MKDIR) -p $(ATTACH_DOCDIR)
-	$(JAVADOC_CMD) $(ATTACH_JAVADOCFLAGS)                     \
-		   $(ATTACH_PKGS)
+# Create file with javadoc options in it
+$(TREEAPI_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-doctitle '$(TREEAPI_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(TREEAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(TREEAPI_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(TREEAPI_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP)"	; \
+	  $(ECHO) "-linkoffline $(TREEAPI2COREAPI) $(COREAPI_DOCSDIR)/"	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(TREEAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TREEAPI_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(TREEAPI_PKGS))
+
+#############################################################
+#
+# sctpdocs
+#
+
+ALL_OTHER_TARGETS += sctpdocs
+
+SCTPAPI_DOCDIR      := $(JRE_API_DOCSDIR)/nio/sctp/spec
+SCTPAPI2COREAPI     := ../../../$(JDKJRE2COREAPI)
+SCTPAPI_DOCTITLE    := SCTP API
+SCTPAPI_WINDOWTITLE := SCTP API
+SCTPAPI_HEADER      := <strong>SCTP API</strong>
+SCTPAPI_BOTTOM      := $(call CommonBottom,$(SCTPAPI_FIRST_COPYRIGHT_YEAR))
+# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk
+
+SCTPAPI_INDEX_HTML    = $(SCTPAPI_DOCDIR)/index.html
+SCTPAPI_OPTIONS_FILE  = $(DOCSTMPDIR)/sctp.options
+SCTPAPI_PACKAGES_FILE = $(DOCSTMPDIR)/sctp.packages
+
+sctpdocs: $(SCTPAPI_INDEX_HTML)
+
+# Set relative location to core api document root
+$(SCTSCTSCTP: GET2DOCSDIR=$(SCTPAPI2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(SCTPAPI_INDEX_HTML): $(SCTPAPI_OPTIONS_FILE) $(SCTPAPI_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(SCTPAPI_OPTIONS_FILE),$(SCTPAPI_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(SCTPAPI_OPTIONS_FILE) @$(SCTPAPI_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(SCTPAPI_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-doctitle '$(SCTPAPI_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(SCTPAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(SCTPAPI_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(SCTPAPI_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(SCTPAPI2COREAPI) $(COREAPI_DOCSDIR)/"	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(SCTPAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(SCTPAPI_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(SCTPAPI_PKGS))
+
+#############################################################
+#
+# tracingdocs
+#
 
-.PHONY: jconsoledocs
-jconsoledocs:
-	@# ######## api-jconsole ############################
-	$(RM) -r $(JCONSOLE_DOCDIR)
-	$(MKDIR) -p $(JCONSOLE_DOCDIR)
-	$(JAVADOC_CMD) $(JCONSOLE_JAVADOCFLAGS)                     \
-		   $(JCONSOLE_PKGS)
+ALL_OTHER_TARGETS += tracingdocs
+
+TRACING_DOCDIR      := $(JRE_API_DOCSDIR)/tracing
+TRACING2COREAPI     := ../$(JDKJRE2COREAPI)
+TRACING_DOCTITLE    := Java$(TRADEMARK) Platform Tracing
+TRACING_WINDOWTITLE := Platform Tracing
+TRACING_HEADER      := <strong>Platform Tracing</strong>
+TRACING_BOTTOM      := $(call CommonBottom,$(TRACING_FIRST_COPYRIGHT_YEAR))
+# TRACING_PKGS is located in NON_CORE_PKGS.gmk
+
+TRACING_INDEX_HTML    = $(TRACING_DOCDIR)/index.html
+TRACING_OPTIONS_FILE  = $(DOCSTMPDIR)/tracing.options
+TRACING_PACKAGES_FILE = $(DOCSTMPDIR)/tracing.packages
+
+tracingdocs: $(TRACING_INDEX_HTML)
+
+# Set relative location to core api document root
+$(TRACING_INDEX_HTML): GET2DOCSDIR=$(TRACING2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(TRACING_INDEX_HTML): $(TRACING_OPTIONS_FILE) $(TRACING_PACKAGES_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(TRACING_OPTIONS_FILE),$(TRACING_PACKAGES_FILE))
+	$(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \
+	  @$(TRACING_OPTIONS_FILE) @$(TRACING_PACKAGES_FILE)
 
-.PHONY: treeapidocs
-treeapidocs:
-	@# ######## tree api for javac ##################
-	$(RM) -r $(TREEAPI_DESTDIR)
-	$(MKDIR) -p $(TREEAPI_DESTDIR)
-	$(JAVADOC_CMD) $(TREEAPI_JAVADOCFLAGS)             \
-		   -d $(TREEAPI_DESTDIR)               \
-		   -sourcepath $(RELEASEDOCS_SRCPATH) \
-		   $(TREEAPI_LINKOPT)                  \
-		   $(TREEAPI_PKGS)
+# Create file with javadoc options in it
+$(TRACING_OPTIONS_FILE):
+	$(prep-target)
+	@($(ECHO) "$(COMMON_JAVADOCFLAGS)"				; \
+	  $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\""		; \
+	  $(ECHO) "-encoding ascii"					; \
+	  $(ECHO) "-nodeprecatedlist"					; \
+	  $(ECHO) "-doctitle '$(TRACING_DOCTITLE)'"			; \
+	  $(ECHO) "-windowtitle '$(TRACING_WINDOWTITLE) $(DRAFT_WINTITLE)'";\
+	  $(ECHO) "-header '$(TRACING_HEADER)$(DRAFT_HEADER)'"		; \
+	  $(ECHO) "-bottom '$(TRACING_BOTTOM)$(DRAFT_BOTTOM)'"		; \
+	  $(ECHO) "-linkoffline $(TRACING2COREAPI) $(COREAPI_DOCSDIR)/"	; \
+        ) >> $@
+
+# Create a file with the package names in it
+$(TRACING_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TRACING_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(TRACING_PKGS))
+
+#############################################################
+#
+# Get a cache of all the directories
 
+$(DIRECTORY_CACHE): $(ALL_SOURCE_DIRS)
+	$(prep-target)
+	@for cp in $(ALL_SOURCE_DIRS) ; do 		\
+	  $(ECHO) "$(FIND) $${cp} -type f >> $@"; 	\
+	  $(FIND) $${cp} -type f >> $@; 		\
+	done
+
+#############################################################
+#release version of core packages ########
+# Maximize performance and ensure that build number & milestone are set.
+
+rel-coredocs: sanitycheckcoredocs
+	$(MAKE) coredocs
+
+rel-docs: rel-coredocs $(ALL_OTHER_TARGETS)
+#
+# end of production targets
+
+otherdocs: $(ALL_OTHER_TARGETS)
+
+clean:
+	$(RM) -r $(DOCSDIR) $(DOCSTMPDIR)
+
+#############################################################
 # DEBUG TARGET
 # List the values defined in the makefile hierarchy, to make sure everything
 # is set properly, and to help identify values we can use instead of making new ones.
@@ -714,9 +1211,14 @@
 #    * BUILD_NUMBER defaults to b00 if not set on command line with BUILD_NUMBER=<value>
 #    * MILESTONE defaults to internal unless set to beta, rc, or fcs on command line
 #
-.PHONY: echovalues
+
 echovalues:
 	@$(ECHO) ""
+	@$(ECHO) --------------Imports---------------------------
+	@$(ECHO) "IMPORT_PACKAGES = $(IMPORT_PACKAGES)"
+	@$(ECHO) "IMPORT_PACKAGE_FILTER = $(IMPORT_PACKAGE_FILTER)"
+	@$(ECHO) --------------Imports---------------------------
+	@$(ECHO) ""
 	@$(ECHO) --------------Shared---------------------------
 	@$(ECHO) BUILD_NUMBER = $(BUILD_NUMBER)
 	@$(ECHO) FULL_VERSION = $(FULL_VERSION)
@@ -736,11 +1238,16 @@
 	@$(ECHO) --------------Shared---------------------------
 	@$(ECHO) ""
 	@$(ECHO) --------------common/Defs---------------------------
-	@$(ECHO) "RELEASEDOCS_SRCPATH"
+	@$(ECHO) "RELEASEDOCS_SOURCEPATH"
 	@$(ECHO) "   SHARE_SRC/classes: $(SHARE_SRC)/classes"
 	@$(ECHO) "   PLATFORM_SRC/classes: $(PLATFORM_SRC)/classes"
 	@$(ECHO) "   GENSRCDIR: $(GENSRCDIR)"
+	@$(ECHO) "   SHARE_SRC/doc/stub: $(SHARE_SRC)/doc/stub"
 	@$(ECHO) "   IMPORTSRCDIR: $(IMPORTSRCDIR)"
-	@$(ECHO) "   SHARE_SRC/doc/stub: $(SHARE_SRC)/doc/stub"
 	@$(ECHO) --------------common/Defs---------------------------
 	@$(ECHO) ""
+
+#############################################################
+.PHONY: all docs coredocs rel-docs echovalues otherdocs rel-coredocs \
+        sanitycheckcoredocs $(ALL_OTHER_TARGETS)
+
--- a/jdk/make/java/java/FILES_java.gmk	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/make/java/java/FILES_java.gmk	Wed Jul 05 17:17:57 2017 +0200
@@ -30,6 +30,7 @@
 #
 JAVA_JAVA_java = \
     java/lang/Object.java \
+    java/lang/AutoCloseable.java \
     java/lang/Class.java \
     java/lang/Thread.java \
     java/lang/Character.java \
--- a/jdk/make/java/security/Makefile	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/make/java/security/Makefile	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 2010 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
@@ -62,6 +62,11 @@
 CACERTS_SRC =	$(CACERTS_FILE)
 CACERTS_BUILD = $(LIBDIR)/security/cacerts
 
+ifndef OPENJDK
+  BLACKLIST_SRC =	$(CLOSED_SHARE_SRC)/lib/security/blacklist
+  BLACKLIST_BUILD = $(LIBDIR)/security/blacklist
+endif
+
 FILES_class = $(FILES_java:%.java=$(CLASSBINDIR)/%.class)
 
 #
@@ -69,7 +74,11 @@
 #
 include $(BUILDDIR)/common/Rules.gmk
 
+ifdef OPENJDK
 build: properties policy cacerts
+else
+build: properties policy cacerts blacklist
+endif
 
 install: all
 
@@ -79,6 +88,8 @@
 
 cacerts: classes $(CACERTS_BUILD)
 
+blacklist: classes $(BLACKLIST_BUILD)
+
 $(PROPS_BUILD): $(PROPS_SRC)
 	$(install-file)
 
@@ -88,9 +99,12 @@
 $(CACERTS_BUILD): $(CACERTS_SRC)
 	$(install-file)
 
+$(BLACKLIST_BUILD): $(BLACKLIST_SRC)
+	$(install-file)
+
 clean clobber:: .delete.classlist
 	$(RM) -r $(CLASSBINDIR)/java/security
-	$(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD)
+	$(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD)
 
 # Additional Rule for building sun.security.util
 $(CLASSBINDIR)/%.class: $(SHARE_SRC)/sun/%.java
--- a/jdk/make/mkdemo/Makefile	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/make/mkdemo/Makefile	Wed Jul 05 17:17:57 2017 +0200
@@ -46,11 +46,11 @@
 	$(RM) -r $(DEMODIR)/nbproject
 	$(MKDIR) -p $(DEMODIR)
 	( $(CD) $(SHARE_SRC)/demo && $(TAR) -cf - \
-	  `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
+	  `$(FIND) nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
 	  ( $(CD) $(DEMODIR) && $(TAR) -xf - )
 ifndef OPENJDK
 	( $(CD) $(CLOSED_SHARE_SRC)/demo && $(TAR) -cf - \
-	  `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
+	  `$(FIND) nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \
 	  ( $(CD) $(DEMODIR) && $(TAR) -xf - )
 endif
 
--- a/jdk/make/tools/src/build/tools/jarreorder/JarReorder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/make/tools/src/build/tools/jarreorder/JarReorder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -28,7 +28,6 @@
  * combine with an argument list of files and directories, and
  * write a list of items to be included in a jar file.
  */
-
 package build.tools.jarreorder;
 
 import java.io.BufferedReader;
@@ -36,74 +35,68 @@
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.Vector;
 import java.io.PrintStream;
 import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
 
 public class JarReorder {
 
     // To deal with output
-    private static PrintStream out;
+    private PrintStream out;
 
-    private final static boolean useTopDir = false;
-
-    private static void usage() {
+    private void usage() {
         String help;
         help =
-            "Usage:  jar JarReorder [-o <outputfile>] <order_list> <exclude_list> <file> ...\n"
-          + "   order_list    is a file containing names of files to load\n"
-          + "                 in order at the end of a jar file.\n"
-          + "   exclude_list  is a file containing names of files/directories\n"
-          + "                 NOT to be included in a jar file.\n";
-        if (useTopDir)
-            help +=
-                "   top_dir       is the top of the directory structure to be searched;\n"
-              + "                 the contents of the lists and remaining arguments are\n"
-              + "                 relative to this.\n";
-        help +=
-            "\n"
-          + "The order_list or exclude_list may be replaced by a \"_\" if no\n"
-          + "data is to be provided.\n"
-          + "\n"
-          + "   The remaining arguments are files or directories to be included\n"
-          + "   in a jar file, from which will be excluded thse entries which\n"
-          + "   appear in the exclude list.\n";
+                "Usage:  jar JarReorder [-o <outputfile>] <order_list> <exclude_list> <file> ...\n"
+                + "   order_list    is a file containing names of files to load\n"
+                + "                 in order at the end of a jar file unless\n"
+                + "                 excluded in the exclude list.\n"
+                + "   exclude_list  is a file containing names of files/directories\n"
+                + "                 NOT to be included in a jar file.\n"
+                + "\n"
+                + "The order_list or exclude_list may be replaced by a \"-\" if no\n"
+                + "data is to be provided.\n"
+                + "\n"
+                + "   The remaining arguments are files or directories to be included\n"
+                + "   in a jar file, from which will be excluded those entries which\n"
+                + "   appear in the exclude list.\n";
         System.err.println(help);
-        System.exit(1);
     }
 
 
     /*
-     * Create a list of files to be included in a jar file, such that the
-     * some the files will appear in a specific order, and allowing certain
+     * Create the file list to be included in a jar file, such that the
+     * list will appear in a specific order, and allowing certain
      * files and directories to be excluded.
      *
-     * Command line arguments are
+     * Command path arguments are
      *    - optional -o outputfile
-     *    - name of a file containing a list of files to be included in a jar file.
-     *    - name of a file containing a list of files (or directories) to be
+     *    - name of a file containing a set of files to be included in a jar file.
+     *    - name of a file containing a set of files (or directories) to be
      *      excluded from the jar file.
      *    - names of files or directories to be searched for files to include
      *      in the jar file.
      */
     public static void main(String[] args) {
+        JarReorder jr = new JarReorder();
+        jr.run(args);
+    }
 
-        HashMap filesExcluded = new HashMap();
-        Vector filesIncluded = new Vector();
-        int fileArgs;
-        String topDirName = "";
+    private void run(String args[]) {
+
         int arglen = args.length;
         int argpos = 0;
 
         // Look for "-o outputfilename" option
-        if ( arglen > 0 ) {
-            if ( arglen >= 2 && args[0].equals("-o") ) {
+        if (arglen > 0) {
+            if (arglen >= 2 && args[0].equals("-o")) {
                 try {
                     out = new PrintStream(new FileOutputStream(args[1]));
-                } catch ( FileNotFoundException e ) {
+                } catch (FileNotFoundException e) {
                     System.err.println("Error: " + e.getMessage());
                     e.printStackTrace(System.err);
                     System.exit(1);
@@ -118,128 +111,111 @@
             out = System.out;
         }
 
-        fileArgs = useTopDir ? 3 : 2;
-
-        if (arglen <= fileArgs) {
+        // Should be 2 or more args left
+        if (arglen <= 2) {
             usage();
+            System.exit(1);
         }
 
-        // Read the ordered list of files to be included in rt.jar.
-        // Read the list of files/directories to be excluded from rt.jar.
-
-        Vector orderList = readListFromFile(args[argpos], true);
-        Vector excludeList = readListFromFile(args[argpos+1], false);
-        if (useTopDir) {
-            topDirName = args[argpos+2];
-            if (!topDirName.endsWith(File.separator))
-                topDirName = topDirName + File.separator;
-        }
+        // Read the ordered set of files to be included in rt.jar.
+        // Read the set of files/directories to be excluded from rt.jar.
+        String classListFile = args[argpos];
+        String excludeListFile = args[argpos + 1];
+        argpos += 2;
+        arglen -= 2;
 
-        // Copy these lists into filesExcluded so that these files will be excluded
-        // from the file list. (The orderList files will be appended later.)
+        // Create 2 lists and a set of processed files
+        List<String> orderList = readListFromFile(classListFile, true);
+        List<String> excludeList = readListFromFile(excludeListFile, false);
+        Set<String> processed = new HashSet<String>();
 
-        for (int i = 0; i < orderList.size(); ++i) {
-            String s = (String) orderList.elementAt(i);
-            filesExcluded.put(s, s);
-        }
-        for (int i = 0; i < excludeList.size(); ++i) {
-            String s = (String) excludeList.elementAt(i);
-            filesExcluded.put(s, s);
-        }
+        // Create set of all files and directories excluded, then expand
+        //   that list completely
+        Set<String> excludeSet = new HashSet<String>(excludeList);
+        Set<String> allFilesExcluded = expand(null, excludeSet, processed);
+
+        // Indicate all these have been processed, orderList too, kept to end.
+        processed.addAll(orderList);
 
         // The remaining arguments are names of files/directories to be included
         // in the jar file.
-
-        String[] files = new String[arglen - fileArgs];
-        for (int i = fileArgs; i < arglen; ++i) {
-            files[i-fileArgs] = args[argpos+i];
-            filesExcluded.put(args[argpos+i], args[argpos+i]);
+        Set<String> inputSet = new HashSet<String>();
+        for (int i = 0; i < arglen; ++i) {
+            String name = args[argpos + i];
+            name = cleanPath(new File(name));
+            if ( name != null && name.length() > 0 && !inputSet.contains(name) ) {
+                inputSet.add(name);
+            }
         }
 
-        // Expand file/directory list to file list excluding those
-        // read from the class list.
+        // Expand file/directory input so we get a complete set (except ordered)
+        //   Should be everything not excluded and not in order list.
+        Set<String> allFilesIncluded = expand(null, inputSet, processed);
 
-        if (useTopDir)
-            expand(new File(topDirName), files, filesIncluded, filesExcluded, topDirName);
-        else
-            expand(null, files, filesIncluded, filesExcluded, null);
+        // Create simple sorted list so we can add ordered items at end.
+        List<String> allFiles = new ArrayList<String>(allFilesIncluded);
+        Collections.sort(allFiles);
 
-        // Now add the ordered list to the end of the expanded list.
+        // Now add the ordered set to the end of the list.
         // Add in REVERSE ORDER, so that the first element is closest to
         // the end (and the index).
-
-        HashSet excludeSet = new HashSet(excludeList);
         for (int i = orderList.size() - 1; i >= 0; --i) {
-            String s = (String) orderList.elementAt(i);
-            if (excludeSet.contains(s)) {
-                System.err.println("Included file " + s + " is also excluded, skipping.");
-                continue;
+            String s = orderList.get(i);
+            if (allFilesExcluded.contains(s)) {
+                System.err.println("Included order file " + s
+                    + " is also excluded, skipping.");
+            } else if (new File(s).exists()) {
+                allFiles.add(s);
+            } else {
+                System.err.println("Included order file " + s
+                    + " missing, skipping.");
             }
-            if (new File(topDirName + s).exists())
-                filesIncluded.addElement(s);
-            else
-                System.err.println("Included file "+s+" missing, skipping.");
         }
 
-        // Print results.
-
-        for (int i = 0; i < filesIncluded.size(); ++i) {
-            if (useTopDir) {
-                out.print("-C ");
-                out.print(topDirName);
-                out.print(" ");
-            }
-            out.println((String)filesIncluded.elementAt(i));
+        // Print final results.
+        for (String str : allFiles) {
+            out.println(str);
         }
-
         out.flush();
         out.close();
     }
 
-
     /*
-     * Read a file containing a list of files into a Vector.
+     * Read a file containing a list of files and directories into a List.
      */
-    private static Vector readListFromFile(String fileName,
-                                           boolean addClassSuffix) {
+    private List<String> readListFromFile(String fileName,
+            boolean addClassSuffix) {
 
         BufferedReader br = null;
-        Vector v = new Vector(2000);
-
-        if ("-".equals(fileName))
-            return v;
-
+        List<String> list = new ArrayList<String>();
+        // If you see "-" for the name, just assume nothing was provided.
+        if ("-".equals(fileName)) {
+            return list;
+        }
         try {
             br = new BufferedReader(new FileReader(fileName));
-
-        // Read the input file a line at a time. # in column 1 is a comment.
-
+            // Read the input file a path at a time. # in column 1 is a comment.
             while (true) {
-                String line = null;
-                line = br.readLine();
-
-                if (line == null)
+                String path = br.readLine();
+                if (path == null) {
                     break;
-
-                if (line.length() == 0    ||
-                    line.charAt(0) == '#')
+                }
+                // Look for comments
+                path = path.trim();
+                if (path.length() == 0
+                        || path.charAt(0) == '#') {
                     continue;
-
-                // Convert forward or back slashes to the type expected for
-                // the current platform.
-
-                if (File.separatorChar == '/')
-                    line = line.replace('\\', '/');
-                else
-                    line = line.replace('/', '\\');
-
-                line = line.trim();
-                if (addClassSuffix) {
-                    if (!line.endsWith(".class")) {
-                        line = line + ".class";
-                    }
+                }
+                // Add trailing .class if necessary
+                if (addClassSuffix && !path.endsWith(".class")) {
+                    path = path + ".class";
                 }
-                v.addElement(line);
+                // Normalize the path
+                path = cleanPath(new File(path));
+                // Add to list
+                if (path != null && path.length() > 0 && !list.contains(path)) {
+                    list.add(path);
+                }
             }
             br.close();
         } catch (FileNotFoundException e) {
@@ -249,68 +225,89 @@
             e.printStackTrace();
             System.exit(2);
         }
-        return v;
+        return list;
     }
 
-
     /*
-     * Expands list of files to process into full list of all files that
+     * Expands inputSet (files or dirs) into full set of all files that
      * can be found by recursively descending directories.
+     * @param dir root directory
+     * @param inputSet set of files or dirs to look into
+     * @param processed files or dirs already processed
+     * @return set of files
      */
-    private static void expand(File dir, String[] files,
-                               Vector includedFiles, HashMap excludedFiles,
-                               String topDirName) {
-        if (files == null) {
-            return;
+    private Set<String> expand(File dir,
+            Set<String> inputSet,
+            Set<String> processed) {
+        Set<String> includedFiles = new HashSet<String>();
+        if (inputSet.isEmpty()) {
+            return includedFiles;
         }
-        for (int i = 0; i < files.length; i++) {
-            File f = (dir == null) ? new File(files[i])
-                                   : new File(dir, files[i]);
-            if (f.isFile()) {
-                String filePath = f.getPath();
-
-                if (useTopDir) {
-                    if (filePath.startsWith(topDirName))
-                        filePath = filePath.substring(topDirName.length());
+        for (String name : inputSet) {
+            // Depending on start location
+            File f = (dir == null) ? new File(name)
+                    : new File(dir, name);
+            // Normalized path to use
+            String path = cleanPath(f);
+            if (path != null && path.length() > 0
+                    && !processed.contains(path)) {
+                if (f.isFile()) {
+                    // Not in the excludeList, add it to both lists
+                    includedFiles.add(path);
+                    processed.add(path);
+                } else if (f.isDirectory()) {
+                    // Add the directory entries
+                    String[] dirList = f.list();
+                    Set<String> dirInputSet = new HashSet<String>();
+                    for (String x : dirList) {
+                        dirInputSet.add(x);
+                    }
+                    // Process all entries in this directory
+                    Set<String> subList = expand(f, dirInputSet, processed);
+                    includedFiles.addAll(subList);
+                    processed.add(path);
                 }
-
-                if (filePath.length() >= 2 &&
-                    filePath.charAt(0) == '.' &&
-                    filePath.charAt(1) == File.separatorChar)
-                    filePath = filePath.substring(2);
-
-                if (!excludedFiles.containsKey(filePath)) {
-                    excludedFiles.put(filePath, filePath);
-                    includedFiles.addElement(filePath);
-                }
-            } else if (f.isDirectory()) {
-                String dirPath = f.getPath();
-                dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
-                    (dirPath + File.separator);
-
-                if (useTopDir) {
-                    if (dirPath.startsWith(topDirName))
-                        dirPath = dirPath.substring(topDirName.length());
-                }
-
-                if (dirPath.length() >= 2 &&
-                    dirPath.charAt(0) == '.' &&
-                    dirPath.charAt(1) == File.separatorChar)
-                    dirPath = dirPath.substring(2);
-
-                if (!excludedFiles.containsKey(dirPath)) {
-
-                    // Sort the directory list so that entries in the jar file
-                    // are in a repeatable order.  The order itself is not particularly
-                    // important.  [File.list() is unpredictable.]
-
-                    String[] dirList = f.list();
-                    Arrays.sort(dirList);
-                    expand(f, dirList, includedFiles, excludedFiles, topDirName);
-                }
-            } else {
-                System.err.println("Error accessing: " + f.getPath());
             }
         }
+        return includedFiles;
     }
+
+    private String cleanPath(File f) {
+        String path = f.getPath();
+        if (f.isFile()) {
+            path = cleanFilePath(path);
+        } else if (f.isDirectory()) {
+            path = cleanDirPath(path);
+        } else {
+            System.err.println("WARNING: Path does not exist as file or directory: " + path);
+            path = null;
+        }
+        return path;
+    }
+
+    private String cleanFilePath(String path) {
+        // Remove leading and trailing whitespace
+        path = path.trim();
+        // Make all / and \ chars one
+        if (File.separatorChar == '/') {
+            path = path.replace('\\', '/');
+        } else {
+            path = path.replace('/', '\\');
+        }
+        // Remove leading ./
+        if (path.startsWith("." + File.separator)) {
+            path = path.substring(2);
+        }
+        return path;
+    }
+
+    private String cleanDirPath(String path) {
+        path = cleanFilePath(path);
+        // Make sure it ends with a file separator
+        if (!path.endsWith(File.separator)) {
+            path = path + File.separator;
+        }
+        return path;
+    }
+
 }
--- a/jdk/src/share/bin/emessages.h	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/bin/emessages.h	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -44,7 +44,7 @@
 
 #define JVM_ERROR1      "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
 #define JVM_ERROR2      "Error: Could not detach main thread.\n" JNI_ERROR
-#define JVM_ERROR3      "Error: SPARC V8 processor detected; Server compiler requires V9 or better.\nUse Client compiler on V8 processors.\nCould not create the Java virtual machine."
+#define JVM_ERROR3      "Error: SPARC V8 processor detected;  Required V9 processors or better.\nUse JDK5 client compiler for V8 processors.\n" JVM_ERROR1
 
 #define JAR_ERROR1      "Error: Failed to load Main-Class manifest attribute from\n%s\n%s"
 #define JAR_ERROR2      "Error: Unable to access jarfile %s"
@@ -69,7 +69,8 @@
 #define CFG_ERROR5      "Error: Could not determine application home."
 #define CFG_ERROR6      "Error: could not open `%s'"
 #define CFG_ERROR7      "Error: no known VMs. (check for corrupt jvm.cfg file)"
-#define CFG_ERROR8      "Error: no `%s' JVM at `%s'."
+#define CFG_ERROR8      "Error: missing `%s' JVM at `%s'.\nPlease install or use the JRE or JDK that contains these missing components."
+#define CFG_ERROR9      "Error: could not determine JVM type."
 
 
 #define SPC_ERROR1      "Error: Syntax error in version specification \"%s\""
--- a/jdk/src/share/bin/java.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/bin/java.c	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2010, 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
@@ -192,8 +192,8 @@
     int ret;
     InvocationFunctions ifn;
     jlong start, end;
-    char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
-    char ** original_argv = argv;
+    char jvmpath[MAXPATHLEN];
+    char jrepath[MAXPATHLEN];
 
     _fVersion = fullversion;
     _dVersion = dotversion;
@@ -225,14 +225,17 @@
      */
     SelectVersion(argc, argv, &main_class);
 
-    /* copy original argv */
-    JLI_TraceLauncher("Command line Args:\n");
-    original_argv = (JLI_CopyArgs(argc, (const char**)argv));
+    if (JLI_IsTraceLauncher()) {
+        int i;
+        printf("Command line args:\n");
+        for (i = 0; i < argc ; i++) {
+            printf("argv[%d] = %s\n", i, argv[i]);
+        }
+    }
 
     CreateExecutionEnvironment(&argc, &argv,
                                jrepath, sizeof(jrepath),
-                               jvmpath, sizeof(jvmpath),
-                               original_argv);
+                               jvmpath, sizeof(jvmpath));
 
     ifn.CreateJavaVM = 0;
     ifn.GetDefaultJavaVMInitArgs = 0;
@@ -301,22 +304,43 @@
     return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret);
 
 }
+/*
+ * Always detach the main thread so that it appears to have ended when
+ * the application's main method exits.  This will invoke the
+ * uncaught exception handler machinery if main threw an
+ * exception.  An uncaught exception handler cannot change the
+ * launcher's return code except by calling System.exit.
+ *
+ * Wait for all non-daemon threads to end, then destroy the VM.
+ * This will actually create a trivial new Java waiter thread
+ * named "DestroyJavaVM", but this will be seen as a different
+ * thread from the one that executed main, even though they are
+ * the same C thread.  This allows mainThread.join() and
+ * mainThread.isAlive() to work as expected.
+ */
+#define LEAVE() \
+    if ((*vm)->DetachCurrentThread(vm) != 0) { \
+        JLI_ReportErrorMessage(JVM_ERROR2); \
+        ret = 1; \
+    } \
+    (*vm)->DestroyJavaVM(vm); \
+    return ret \
 
 #define CHECK_EXCEPTION_NULL_LEAVE(e) \
     if ((*env)->ExceptionOccurred(env)) { \
         JLI_ReportExceptionDescription(env); \
-        goto leave; \
+        LEAVE(); \
     } \
     if ((e) == NULL) { \
         JLI_ReportErrorMessage(JNI_ERROR); \
-        goto leave; \
+        LEAVE(); \
     }
 
 #define CHECK_EXCEPTION_LEAVE(rv) \
     if ((*env)->ExceptionOccurred(env)) { \
         JLI_ReportExceptionDescription(env); \
         ret = (rv); \
-        goto leave; \
+        LEAVE(); \
     }
 
 int JNICALL
@@ -349,8 +373,7 @@
         PrintJavaVersion(env, showVersion);
         CHECK_EXCEPTION_LEAVE(0);
         if (printVersion) {
-            ret = 0;
-            goto leave;
+            LEAVE();
         }
     }
 
@@ -358,7 +381,7 @@
     if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
         PrintUsage(env, printXUsage);
         CHECK_EXCEPTION_LEAVE(1);
-        goto leave;
+        LEAVE();
     }
 
     FreeKnownVMs();  /* after last possible PrintUsage() */
@@ -430,30 +453,7 @@
      * System.exit) will be non-zero if main threw an exception.
      */
     ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
-
-leave:
-    /*
-     * Always detach the main thread so that it appears to have ended when
-     * the application's main method exits.  This will invoke the
-     * uncaught exception handler machinery if main threw an
-     * exception.  An uncaught exception handler cannot change the
-     * launcher's return code except by calling System.exit.
-     */
-    if ((*vm)->DetachCurrentThread(vm) != 0) {
-        JLI_ReportErrorMessage(JVM_ERROR2);
-        ret = 1;
-    }
-    /*
-     * Wait for all non-daemon threads to end, then destroy the VM.
-     * This will actually create a trivial new Java waiter thread
-     * named "DestroyJavaVM", but this will be seen as a different
-     * thread from the one that executed main, even though they are
-     * the same C thread.  This allows mainThread.join() and
-     * mainThread.isAlive() to work as expected.
-     */
-    (*vm)->DestroyJavaVM(vm);
-
-    return ret;
+    LEAVE();
 }
 
 /*
@@ -1076,15 +1076,17 @@
     if (--argc >= 0) {
         if (jarflag) {
             *pjarfile = *argv++;
-            *pclassname = 0;
+            *pclassname = NULL;
         } else {
-            *pjarfile = 0;
+            *pjarfile = NULL;
             *pclassname = *argv++;
         }
         *pargc = argc;
         *pargv = argv;
     }
-
+    if (*pjarfile == NULL && *pclassname == NULL) {
+        *pret = 1;
+    }
     return JNI_TRUE;
 }
 
--- a/jdk/src/share/bin/java.h	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/bin/java.h	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, 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
@@ -114,13 +114,19 @@
 
 #define GetArch() GetArchPath(CURRENT_DATA_MODEL)
 
-void CreateExecutionEnvironment(int *_argc,
-                                       char ***_argv,
-                                       char jrepath[],
-                                       jint so_jrepath,
-                                       char jvmpath[],
-                                       jint so_jvmpath,
-                                       char **original_argv);
+/*
+ * Different platforms will implement this, here
+ * pargc is a pointer to the original argc,
+ * pargv is a pointer to the original argv,
+ * jrepath is an accessible path to the jre as determined by the call
+ * so_jrepath is the length of the buffer jrepath
+ * jvmpath is an accessible path to the jvm as determined by the call
+ * so_jvmpath is the length of the buffer jvmpath
+ */
+void CreateExecutionEnvironment(int *argc, char ***argv,
+                                char *jrepath, jint so_jrepath,
+                                char *jvmpath, jint so_jvmpath);
+
 /* Reports an error message to stderr or a window as appropriate. */
 void JLI_ReportErrorMessage(const char * message, ...);
 
--- a/jdk/src/share/bin/jli_util.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/bin/jli_util.c	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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,23 +85,6 @@
 }
 
 /*
- * Makes a copy of arguments
- */
-char**
-JLI_CopyArgs(int argc, const char **iargv)
-{
-    int i;
-    char** oargv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));
-    for (i = 0 ; i < argc+1 ; i++) {
-        oargv[i] = (iargv[i] == NULL) ? NULL : JLI_StringDup(iargv[i]);
-        if (iargv[i] != NULL && JLI_IsTraceLauncher() == JNI_TRUE) {
-            printf("\targv[%d] = '%s'\n",i,iargv[i]);
-        }
-    }
-    return oargv;
-}
-
-/*
  * debug helpers we use
  */
 static jboolean _launcher_debug = JNI_FALSE;
--- a/jdk/src/share/bin/jli_util.h	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/bin/jli_util.h	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, 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
@@ -33,7 +33,6 @@
 void *JLI_MemRealloc(void *ptr, size_t size);
 char *JLI_StringDup(const char *s1);
 void  JLI_MemFree(void *ptr);
-char **JLI_CopyArgs(int argc, const char **iargv);
 int   JLI_StrCCmp(const char *s1, const char* s2);
 
 
@@ -56,10 +55,12 @@
 #include <io.h>
 #define JLI_StrCaseCmp(p1, p2)          stricmp((p1), (p2))
 #define JLI_StrNCaseCmp(p1, p2, p3)     strnicmp((p1), (p2), (p3))
+#define JLI_Snprintf                    _snprintf
 #else
 #include <unistd.h>
 #define JLI_StrCaseCmp(p1, p2)          strcasecmp((p1), (p2))
 #define JLI_StrNCaseCmp(p1, p2, p3)     strncasecmp((p1), (p2), (p3))
+#define JLI_Snprintf                    snprintf
 #endif /* _WIN32 */
 
 /*
--- a/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/InstanceFinder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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,7 +39,7 @@
     private final Class<? extends T> type;
     private final boolean allow;
     private final String suffix;
-    private String[] packages;
+    private volatile String[] packages;
 
     InstanceFinder(Class<? extends T> type, boolean allow, String suffix, String... packages) {
         this.type = type;
@@ -49,9 +49,7 @@
     }
 
     public String[] getPackages() {
-        return (this.packages.length > 0)
-                ? this.packages.clone()
-                : this.packages;
+        return this.packages.clone();
     }
 
     public void setPackages(String... packages) {
--- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, 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
@@ -118,7 +118,7 @@
      * @throws NoSuchMethodException if method is not accessible or is not found
      *                               in specified superclass or interface
      */
-    private static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
+    public static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
         Class<?> type = method.getDeclaringClass();
         if (Modifier.isPublic(type.getModifiers())) {
             return method;
--- a/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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
@@ -47,17 +47,22 @@
     }
 
     public void register(Class<?> type, PersistenceDelegate delegate) {
-        if (delegate != null) {
-            this.registry.put(type, delegate);
-        }
-        else {
-            this.registry.remove(type);
+        synchronized (this.registry) {
+            if (delegate != null) {
+                this.registry.put(type, delegate);
+            }
+            else {
+                this.registry.remove(type);
+            }
         }
     }
 
     @Override
     public PersistenceDelegate find(Class<?> type) {
-        PersistenceDelegate delegate = this.registry.get(type);
+        PersistenceDelegate delegate;
+        synchronized (this.registry) {
+            delegate = this.registry.get(type);
+        }
         return (delegate != null) ? delegate : super.find(type);
     }
 }
--- a/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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
@@ -64,12 +64,18 @@
     }
 
     public void register(Class<?> type, Class<?> editor) {
-        this.registry.put(type, editor);
+        synchronized (this.registry) {
+            this.registry.put(type, editor);
+        }
     }
 
     @Override
     public PropertyEditor find(Class<?> type) {
-        PropertyEditor editor = instantiate(this.registry.get(type), null);
+        Class<?> predefined;
+        synchronized (this.registry) {
+            predefined = this.registry.get(type);
+        }
+        PropertyEditor editor = instantiate(predefined, null);
         if (editor == null) {
             editor = super.find(type);
             if ((editor == null) && (null != type.getEnumConstants())) {
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1440,10 +1440,6 @@
             }
         }
 
-        public Insets getBorderInsets(Component c) {
-            return getBorderInsets(c, null);
-        }
-
         public Insets getBorderInsets(Component c, Insets i) {
             SynthContext context = getContext(c);
 
--- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -271,7 +271,9 @@
     }
 
     public void uninstallUI(JComponent c) {
-        getFileChooser().removeAll();
+        c.removePropertyChangeListener(filterComboBoxModel);
+        approveButton.removeActionListener(getApproveSelectionAction());
+        filenameTextField.removeActionListener(getApproveSelectionAction());
         super.uninstallUI(c);
     }
 
@@ -515,6 +517,7 @@
 
     public void uninstallComponents(JFileChooser fc) {
         fc.removeAll();
+        bottomPanel = null;
         if (filterComboBoxModel != null) {
             fc.removePropertyChangeListener(filterComboBoxModel);
         }
--- a/jdk/src/share/classes/java/awt/EventDispatchThread.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java	Wed Jul 05 17:17:57 2017 +0200
@@ -61,85 +61,43 @@
  * @since 1.1
  */
 class EventDispatchThread extends Thread {
+
     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
 
     private EventQueue theQueue;
     private boolean doDispatch = true;
+    private boolean threadDeathCaught = false;
+
     private static final int ANY_EVENT = -1;
 
     private Vector<EventFilter> eventFilters = new Vector<EventFilter>();
-    // used in handleException
-    private int modalFiltersCount = 0;
 
     EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
         super(group, name);
-        theQueue = queue;
+        setEventQueue(queue);
     }
 
-    void stopDispatchingImpl(boolean wait) {
-        // Note: We stop dispatching via a flag rather than using
-        // Thread.interrupt() because we can't guarantee that the wait()
-        // we interrupt will be EventQueue.getNextEvent()'s.  -fredx 8-11-98
-
-        StopDispatchEvent stopEvent = new StopDispatchEvent();
-
-        // wait for the dispatcher to complete
-        if (Thread.currentThread() != this) {
-
-            // fix 4122683, 4128923
-            // Post an empty event to ensure getNextEvent is unblocked
-            //
-            // We have to use postEventPrivate instead of postEvent because
-            // EventQueue.pop calls EventDispatchThread.stopDispatching.
-            // Calling SunToolkit.flushPendingEvents in this case could
-            // lead to deadlock.
-            theQueue.postEventPrivate(stopEvent);
-
-            if (wait) {
-                try {
-                    join();
-                } catch(InterruptedException e) {
-                }
-            }
-        } else {
-            stopEvent.dispatch();
-        }
-
-        theQueue.detachDispatchThread(this, false);
-    }
-
+    /*
+     * Must be called on EDT only, that's why no synchronization
+     */
     public void stopDispatching() {
-        stopDispatchingImpl(true);
-    }
-
-    public void stopDispatchingLater() {
-        stopDispatchingImpl(false);
-    }
-
-    class StopDispatchEvent extends AWTEvent implements ActiveEvent {
-        /*
-         * serialVersionUID
-         */
-        static final long serialVersionUID = -3692158172100730735L;
-
-        public StopDispatchEvent() {
-            super(EventDispatchThread.this,0);
-        }
-
-        public void dispatch() {
-            doDispatch = false;
-        }
+        doDispatch = false;
     }
 
     public void run() {
-        try {
-            pumpEvents(new Conditional() {
-                public boolean evaluate() {
-                    return true;
+        while (true) {
+            try {
+                pumpEvents(new Conditional() {
+                    public boolean evaluate() {
+                        return true;
+                    }
+                });
+            } finally {
+                EventQueue eq = getEventQueue();
+                if (eq.detachDispatchThread(this) || threadDeathCaught) {
+                    break;
                 }
-            });
-        } finally {
-            theQueue.detachDispatchThread(this, true);
+            }
         }
     }
 
@@ -190,7 +148,6 @@
                         }
                     }
                     eventFilters.add(k, filter);
-                    modalFiltersCount++;
                 } else {
                     eventFilters.add(filter);
                 }
@@ -200,28 +157,25 @@
 
     void removeEventFilter(EventFilter filter) {
         synchronized (eventFilters) {
-            if (eventFilters.contains(filter)) {
-                if (filter instanceof ModalEventFilter) {
-                    modalFiltersCount--;
-                }
-                eventFilters.remove(filter);
-            }
+            eventFilters.remove(filter);
         }
     }
 
     boolean pumpOneEventForFilters(int id) {
+        AWTEvent event = null;
+        boolean eventOK = false;
         try {
-            AWTEvent event;
-            boolean eventOK;
-            EventQueueDelegate.Delegate delegate =
-                EventQueueDelegate.getDelegate();
+            EventQueue eq = null;
+            EventQueueDelegate.Delegate delegate = null;
             do {
+                // EventQueue may change during the dispatching
+                eq = getEventQueue();
+                delegate = EventQueueDelegate.getDelegate();
+
                 if (delegate != null && id == ANY_EVENT) {
-                    event = delegate.getNextEvent(theQueue);
+                    event = delegate.getNextEvent(eq);
                 } else {
-                    event = (id == ANY_EVENT)
-                        ? theQueue.getNextEvent()
-                        : theQueue.getNextEvent(id);
+                    event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
                 }
 
                 eventOK = true;
@@ -252,13 +206,15 @@
             if (delegate != null) {
                 handle = delegate.beforeDispatch(event);
             }
-            theQueue.dispatchEvent(event);
+            eq.dispatchEvent(event);
             if (delegate != null) {
                 delegate.afterDispatch(event, handle);
             }
+
             return true;
         }
         catch (ThreadDeath death) {
+            threadDeathCaught = true;
             return false;
 
         }
@@ -267,12 +223,10 @@
                           // Threads in the AppContext
 
         }
-        // Can get and throw only unchecked exceptions
-        catch (RuntimeException e) {
-            processException(e);
-        } catch (Error e) {
+        catch (Throwable e) {
             processException(e);
         }
+
         return true;
     }
 
@@ -281,14 +235,14 @@
             eventLog.fine("Processing exception: " + e);
         }
         getUncaughtExceptionHandler().uncaughtException(this, e);
-        // don't rethrow the exception to avoid EDT recreation
     }
 
-    boolean isDispatching(EventQueue eq) {
-        return theQueue.equals(eq);
+    public synchronized EventQueue getEventQueue() {
+        return theQueue;
     }
-
-    EventQueue getEventQueue() { return theQueue; }
+    public synchronized void setEventQueue(EventQueue eq) {
+        theQueue = eq;
+    }
 
     private static class HierarchyEventFilter implements EventFilter {
         private Component modalComponent;
--- a/jdk/src/share/classes/java/awt/EventQueue.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/awt/EventQueue.java	Wed Jul 05 17:17:57 2017 +0200
@@ -138,6 +138,15 @@
     private final Lock pushPopLock;
     private final Condition pushPopCond;
 
+    /*
+     * Dummy runnable to wake up EDT from getNextEvent() after
+     push/pop is performed
+     */
+    private final static Runnable dummyRunnable = new Runnable() {
+        public void run() {
+        }
+    };
+
     private EventDispatchThread dispatchThread;
 
     private final ThreadGroup threadGroup =
@@ -219,22 +228,22 @@
      * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
      *          or a subclass of it
      */
-    final void postEventPrivate(AWTEvent theEvent) {
+    private final void postEventPrivate(AWTEvent theEvent) {
         theEvent.isPosted = true;
         pushPopLock.lock();
         try {
-            if (dispatchThread == null && nextQueue == null) {
+            if (nextQueue != null) {
+                // Forward the event to the top of EventQueue stack
+                nextQueue.postEventPrivate(theEvent);
+                return;
+            }
+            if (dispatchThread == null) {
                 if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
                     return;
                 } else {
                     initDispatchThread();
                 }
             }
-            if (nextQueue != null) {
-                // Forward event to top of EventQueue stack.
-                nextQueue.postEventPrivate(theEvent);
-                return;
-            }
             postEvent(theEvent, getPriority(theEvent));
         } finally {
             pushPopLock.unlock();
@@ -242,29 +251,20 @@
     }
 
     private static int getPriority(AWTEvent theEvent) {
-        if (theEvent instanceof PeerEvent &&
-            (((PeerEvent)theEvent).getFlags() &
-                PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0)
-        {
-            return ULTIMATE_PRIORITY;
+        if (theEvent instanceof PeerEvent) {
+            PeerEvent peerEvent = (PeerEvent)theEvent;
+            if ((peerEvent.getFlags() & PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) {
+                return ULTIMATE_PRIORITY;
+            }
+            if ((peerEvent.getFlags() & PeerEvent.PRIORITY_EVENT) != 0) {
+                return HIGH_PRIORITY;
+            }
+            if ((peerEvent.getFlags() & PeerEvent.LOW_PRIORITY_EVENT) != 0) {
+                return LOW_PRIORITY;
+            }
         }
-
-        if (theEvent instanceof PeerEvent &&
-            (((PeerEvent)theEvent).getFlags() &
-                PeerEvent.PRIORITY_EVENT) != 0)
-        {
-            return HIGH_PRIORITY;
-        }
-
-        if (theEvent instanceof PeerEvent &&
-            (((PeerEvent)theEvent).getFlags() &
-                PeerEvent.LOW_PRIORITY_EVENT) != 0)
-        {
-            return LOW_PRIORITY;
-        }
-
         int id = theEvent.getID();
-        if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) {
+        if ((id >= PaintEvent.PAINT_FIRST) && (id <= PaintEvent.PAINT_LAST)) {
             return LOW_PRIORITY;
         }
         return NORM_PRIORITY;
@@ -501,16 +501,9 @@
             SunToolkit.flushPendingEvents();
             pushPopLock.lock();
             try {
-                for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
-                    if (queues[i].head != null) {
-                        EventQueueItem entry = queues[i].head;
-                        queues[i].head = entry.next;
-                        if (entry.next == null) {
-                            queues[i].tail = null;
-                        }
-                        uncacheEQItem(entry);
-                        return entry.event;
-                    }
+                AWTEvent event = getNextEventPrivate();
+                if (event != null) {
+                    return event;
                 }
                 AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
                 pushPopCond.await();
@@ -520,6 +513,24 @@
         } while(true);
     }
 
+    /*
+     * Must be called under the lock. Doesn't call flushPendingEvents()
+     */
+    AWTEvent getNextEventPrivate() throws InterruptedException {
+        for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
+            if (queues[i].head != null) {
+                EventQueueItem entry = queues[i].head;
+                queues[i].head = entry.next;
+                if (entry.next == null) {
+                    queues[i].tail = null;
+                }
+                uncacheEQItem(entry);
+                return entry.event;
+            }
+        }
+        return null;
+    }
+
     AWTEvent getNextEvent(int id) throws InterruptedException {
         do {
             /*
@@ -659,7 +670,9 @@
                 dispatchThread.stopDispatching();
             }
         } else {
-            System.err.println("unable to dispatch event: " + event);
+            if (eventLog.isLoggable(PlatformLogger.FINE)) {
+                eventLog.fine("Unable to dispatch event: " + event);
+            }
         }
     }
 
@@ -761,15 +774,23 @@
 
         pushPopLock.lock();
         try {
-            EventQueue toPush = this;
-            while (toPush.nextQueue != null) {
-                toPush = toPush.nextQueue;
+            EventQueue topQueue = this;
+            while (topQueue.nextQueue != null) {
+                topQueue = topQueue.nextQueue;
+            }
+
+            if ((topQueue.dispatchThread != null) &&
+                (topQueue.dispatchThread.getEventQueue() == this))
+            {
+                newEventQueue.dispatchThread = topQueue.dispatchThread;
+                topQueue.dispatchThread.setEventQueue(newEventQueue);
             }
 
             // Transfer all events forward to new EventQueue.
-            while (toPush.peekEvent() != null) {
+            while (topQueue.peekEvent() != null) {
                 try {
-                    newEventQueue.postEventPrivate(toPush.getNextEvent());
+                    // Use getNextEventPrivate() as it doesn't call flushPendingEvents()
+                    newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
                 } catch (InterruptedException ie) {
                     if (eventLog.isLoggable(PlatformLogger.FINE)) {
                         eventLog.fine("Interrupted push", ie);
@@ -777,28 +798,21 @@
                 }
             }
 
-            newEventQueue.previousQueue = toPush;
+            // Wake up EDT waiting in getNextEvent(), so it can
+            // pick up a new EventQueue. Post the waking event before
+            // topQueue.nextQueue is assigned, otherwise the event would
+            // go newEventQueue
+            topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
 
-            /*
-             * Stop the event dispatch thread associated with the currently
-             * active event queue, so that after the new queue is pushed
-             * on the top this event dispatch thread won't prevent AWT from
-             * being automatically shut down.
-             * Use stopDispatchingLater() to avoid deadlock: stopDispatching()
-             * waits for the dispatch thread to exit, which in turn waits
-             * for the lock in EQ.detachDispatchThread(), which is hold by
-             * this method.
-             */
-            if (toPush.dispatchThread != null) {
-                toPush.dispatchThread.stopDispatchingLater();
+            newEventQueue.previousQueue = topQueue;
+            topQueue.nextQueue = newEventQueue;
+
+            AppContext appContext = AppContext.getAppContext();
+            if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) {
+                appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
             }
 
-            toPush.nextQueue = newEventQueue;
-
-            AppContext appContext = AppContext.getAppContext();
-            if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) {
-                appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
-            }
+            pushPopCond.signalAll();
         } finally {
             pushPopLock.unlock();
         }
@@ -822,44 +836,51 @@
             eventLog.fine("EventQueue.pop(" + this + ")");
         }
 
-        EventDispatchThread dt = null;
         pushPopLock.lock();
         try {
-            EventQueue toPop = this;
-            while (toPop.nextQueue != null) {
-                toPop = toPop.nextQueue;
+            EventQueue topQueue = this;
+            while (topQueue.nextQueue != null) {
+                topQueue = topQueue.nextQueue;
             }
-            EventQueue prev = toPop.previousQueue;
-            if (prev == null) {
+            EventQueue prevQueue = topQueue.previousQueue;
+            if (prevQueue == null) {
                 throw new EmptyStackException();
             }
-            toPop.previousQueue = null;
+
+            topQueue.previousQueue = null;
+            prevQueue.nextQueue = null;
 
             // Transfer all events back to previous EventQueue.
-            prev.nextQueue = null;
-            while (toPop.peekEvent() != null) {
+            while (topQueue.peekEvent() != null) {
                 try {
-                    prev.postEventPrivate(toPop.getNextEvent());
+                    prevQueue.postEventPrivate(topQueue.getNextEventPrivate());
                 } catch (InterruptedException ie) {
                     if (eventLog.isLoggable(PlatformLogger.FINE)) {
                         eventLog.fine("Interrupted pop", ie);
                     }
                 }
             }
-            AppContext appContext = AppContext.getAppContext();
-            if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
-                appContext.put(AppContext.EVENT_QUEUE_KEY, prev);
+
+            if ((topQueue.dispatchThread != null) &&
+                (topQueue.dispatchThread.getEventQueue() == this))
+            {
+                prevQueue.dispatchThread = topQueue.dispatchThread;
+                topQueue.dispatchThread.setEventQueue(prevQueue);
             }
 
-            dt = toPop.dispatchThread;
+            AppContext appContext = AppContext.getAppContext();
+            if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
+                appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue);
+            }
+
+            // Wake up EDT waiting in getNextEvent(), so it can
+            // pick up a new EventQueue
+            topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
+
+            pushPopCond.signalAll();
         } finally {
             pushPopLock.unlock();
         }
-
-        if (dt != null) {
-            dt.stopDispatching(); // Must be done outside synchronized
-                                  // block to avoid possible deadlock
-        }
     }
 
     /**
@@ -907,9 +928,9 @@
         try {
             AppContext appContext = AppContext.getAppContext();
             if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
-                dispatchThread = (EventDispatchThread)
-                    AccessController.doPrivileged(new PrivilegedAction() {
-                        public Object run() {
+                dispatchThread = AccessController.doPrivileged(
+                    new PrivilegedAction<EventDispatchThread>() {
+                        public EventDispatchThread run() {
                             EventDispatchThread t =
                                 new EventDispatchThread(threadGroup,
                                                         name,
@@ -919,7 +940,8 @@
                             t.setDaemon(false);
                             return t;
                         }
-                    });
+                    }
+                );
                 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
                 dispatchThread.start();
             }
@@ -928,7 +950,7 @@
         }
     }
 
-    final void detachDispatchThread(EventDispatchThread edt, boolean restart) {
+    final boolean detachDispatchThread(EventDispatchThread edt) {
         /*
          * This synchronized block is to secure that the event dispatch
          * thread won't die in the middle of posting a new event to the
@@ -939,26 +961,21 @@
          */
         pushPopLock.lock();
         try {
-            EventDispatchThread oldDispatchThread = dispatchThread;
-            if (dispatchThread == edt) {
-                dispatchThread = null;
-            }
-            if (restart) {
+            if (edt == dispatchThread) {
                 /*
-                 * Event dispatch thread dies in case of an uncaught exception.
-                 * A new event dispatch thread for this queue will be started
-                 * only if a new event is posted to it. In case if no more
-                 * events are posted after this thread died all events that
-                 * currently are in the queue will never be dispatched.
+                 * Don't detach the thread if any events are pending. Not
+                 * sure if it's a possible scenario, though.
                  *
                  * Fix for 4648733. Check both the associated java event
                  * queue and the PostEventQueue.
                  */
                 if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
-                    initDispatchThread();
+                    return false;
                 }
-                AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread);
+                dispatchThread = null;
             }
+            AWTAutoShutdown.getInstance().notifyThreadFree(edt);
+            return true;
         } finally {
             pushPopLock.unlock();
         }
--- a/jdk/src/share/classes/java/beans/Encoder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/Encoder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -194,13 +194,8 @@
      * @see java.beans.BeanInfo#getBeanDescriptor
      */
     public PersistenceDelegate getPersistenceDelegate(Class<?> type) {
-        synchronized (this.finder) {
-            PersistenceDelegate pd = this.finder.find(type);
-            if (pd != null) {
-                return pd;
-            }
-        }
-        return MetaData.getPersistenceDelegate(type);
+        PersistenceDelegate pd = this.finder.find(type);
+        return (pd != null) ? pd : MetaData.getPersistenceDelegate(type);
     }
 
     /**
@@ -214,9 +209,7 @@
      * @see java.beans.BeanInfo#getBeanDescriptor
      */
     public void setPersistenceDelegate(Class<?> type, PersistenceDelegate delegate) {
-        synchronized (this.finder) {
-            this.finder.register(type, delegate);
-        }
+        this.finder.register(type, delegate);
     }
 
     /**
--- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java	Wed Jul 05 17:17:57 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.lang.ref.Reference;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 
 /**
  * An EventSetDescriptor describes a group of events that a given Java
@@ -175,10 +176,8 @@
         setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
 
         // Be more forgiving of not finding the getListener method.
-        Method method = Introspector.findMethod(sourceClass,
-                                                getListenerMethodName, 0);
-        if (method != null) {
-            setGetListenerMethod(method);
+        if (getListenerMethodName != null) {
+            setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName));
         }
     }
 
@@ -188,7 +187,7 @@
             return null;
         }
         Method method = Introspector.findMethod(cls, name, args);
-        if (method == null) {
+        if ((method == null) || Modifier.isStatic(method.getModifiers())) {
             throw new IntrospectionException("Method not found: " + name +
                                              " on class " + cls.getName());
         }
--- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java	Wed Jul 05 17:17:57 2017 +0200
@@ -189,16 +189,11 @@
                     indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
                 }
             }
-
-            Class[] args = { int.class };
-
-            indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName,
-                                                        1, args);
+            indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
             if (indexedReadMethod == null) {
                 // no "is" method, so look for a "get" method.
                 indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
-                indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName,
-                                                            1, args);
+                indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
             }
             setIndexedReadMethod0(indexedReadMethod);
         }
@@ -270,8 +265,7 @@
             if (indexedWriteMethodName == null) {
                 indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();
             }
-            indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName,
-                         2, (type == null) ? null : new Class[] { int.class, type });
+            indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type);
             if (indexedWriteMethod != null) {
                 if (!indexedWriteMethod.getReturnType().equals(void.class)) {
                     indexedWriteMethod = null;
--- a/jdk/src/share/classes/java/beans/Introspector.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/Introspector.java	Wed Jul 05 17:17:57 2017 +0200
@@ -28,6 +28,7 @@
 import com.sun.beans.WeakCache;
 import com.sun.beans.finder.BeanInfoFinder;
 import com.sun.beans.finder.ClassFinder;
+import com.sun.beans.finder.MethodFinder;
 
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
@@ -157,21 +158,23 @@
         if (!ReflectUtil.isPackageAccessible(beanClass)) {
             return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
         }
+        Map<Class<?>, BeanInfo> beanInfoCache;
+        BeanInfo beanInfo;
         synchronized (BEANINFO_CACHE) {
-            Map<Class<?>, BeanInfo> beanInfoCache =
-                    (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE);
-
+            beanInfoCache = (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE);
             if (beanInfoCache == null) {
                 beanInfoCache = new WeakHashMap<Class<?>, BeanInfo>();
                 AppContext.getAppContext().put(BEANINFO_CACHE, beanInfoCache);
             }
-            BeanInfo beanInfo = beanInfoCache.get(beanClass);
-            if (beanInfo == null) {
-                beanInfo = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
+            beanInfo = beanInfoCache.get(beanClass);
+        }
+        if (beanInfo == null) {
+            beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
+            synchronized (BEANINFO_CACHE) {
                 beanInfoCache.put(beanClass, beanInfo);
             }
-            return beanInfo;
         }
+        return beanInfo;
     }
 
     /**
@@ -301,10 +304,7 @@
      */
 
     public static String[] getBeanInfoSearchPath() {
-        BeanInfoFinder finder = getFinder();
-        synchronized (finder) {
-            return finder.getPackages();
-        }
+        return getFinder().getPackages();
     }
 
     /**
@@ -328,10 +328,7 @@
         if (sm != null) {
             sm.checkPropertiesAccess();
         }
-        BeanInfoFinder finder = getFinder();
-        synchronized (finder) {
-            finder.setPackages(path);
-        }
+        getFinder().setPackages(path);
     }
 
 
@@ -453,10 +450,7 @@
      * @return Instance of an explicit BeanInfo class or null if one isn't found.
      */
     private static BeanInfo findExplicitBeanInfo(Class beanClass) {
-        BeanInfoFinder finder = getFinder();
-        synchronized (finder) {
-            return finder.find(beanClass);
-        }
+        return getFinder().find(beanClass);
     }
 
     /**
@@ -849,8 +843,8 @@
                 Method read = result.getReadMethod();
 
                 if (read == null && write != null) {
-                    read = findMethod(result.getClass0(),
-                                      GET_PREFIX + NameGenerator.capitalize(result.getName()), 0);
+                    read = findInstanceMethod(result.getClass0(),
+                                              GET_PREFIX + NameGenerator.capitalize(result.getName()));
                     if (read != null) {
                         try {
                             result.setReadMethod(read);
@@ -860,9 +854,9 @@
                     }
                 }
                 if (write == null && read != null) {
-                    write = findMethod(result.getClass0(),
-                                       SET_PREFIX + NameGenerator.capitalize(result.getName()), 1,
-                                       new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) });
+                    write = findInstanceMethod(result.getClass0(),
+                                               SET_PREFIX + NameGenerator.capitalize(result.getName()),
+                                               FeatureDescriptor.getReturnType(result.getClass0(), read));
                     if (write != null) {
                         try {
                             result.setWriteMethod(write);
@@ -1286,90 +1280,27 @@
     // Package private support methods.
     //======================================================================
 
-    /**
-     * Internal support for finding a target methodName with a given
-     * parameter list on a given class.
-     */
-    private static Method internalFindMethod(Class start, String methodName,
-                                                 int argCount, Class args[]) {
-        // For overriden methods we need to find the most derived version.
-        // So we start with the given class and walk up the superclass chain.
-
-        Method method = null;
-
-        for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
-            Method methods[] = getPublicDeclaredMethods(cl);
-            for (int i = 0; i < methods.length; i++) {
-                method = methods[i];
-                if (method == null) {
-                    continue;
+    static Method findMethod(Class<?> type, String name, int args) {
+        for (Method method : type.getMethods()) {
+            if (method.getName().equals(name) && (args == method.getParameterTypes().length)) {
+                try {
+                    return MethodFinder.findAccessibleMethod(method);
                 }
-
-                // make sure method signature matches.
-                Class params[] = FeatureDescriptor.getParameterTypes(start, method);
-                if (method.getName().equals(methodName) &&
-                    params.length == argCount) {
-                    if (args != null) {
-                        boolean different = false;
-                        if (argCount > 0) {
-                            for (int j = 0; j < argCount; j++) {
-                                if (params[j] != args[j]) {
-                                    different = true;
-                                    continue;
-                                }
-                            }
-                            if (different) {
-                                continue;
-                            }
-                        }
-                    }
-                    return method;
+                catch (NoSuchMethodException exception) {
+                    // continue search for a method with the specified count of parameters
                 }
             }
         }
-        method = null;
-
-        // Now check any inherited interfaces.  This is necessary both when
-        // the argument class is itself an interface, and when the argument
-        // class is an abstract class.
-        Class ifcs[] = start.getInterfaces();
-        for (int i = 0 ; i < ifcs.length; i++) {
-            // Note: The original implementation had both methods calling
-            // the 3 arg method. This is preserved but perhaps it should
-            // pass the args array instead of null.
-            method = internalFindMethod(ifcs[i], methodName, argCount, null);
-            if (method != null) {
-                break;
-            }
-        }
-        return method;
+        return null;
     }
 
-    /**
-     * Find a target methodName on a given class.
-     */
-    static Method findMethod(Class cls, String methodName, int argCount) {
-        return findMethod(cls, methodName, argCount, null);
-    }
-
-    /**
-     * Find a target methodName with specific parameter list on a given class.
-     * <p>
-     * Used in the contructors of the EventSetDescriptor,
-     * PropertyDescriptor and the IndexedPropertyDescriptor.
-     * <p>
-     * @param cls The Class object on which to retrieve the method.
-     * @param methodName Name of the method.
-     * @param argCount Number of arguments for the desired method.
-     * @param args Array of argument types for the method.
-     * @return the method or null if not found
-     */
-    static Method findMethod(Class cls, String methodName, int argCount,
-                             Class args[]) {
-        if (methodName == null) {
+    static Method findInstanceMethod(Class<?> type, String name, Class<?>... args) {
+        try {
+            return MethodFinder.findInstanceMethod(type, name, args);
+        }
+        catch (NoSuchMethodException exception) {
             return null;
         }
-        return internalFindMethod(cls, methodName, argCount, args);
     }
 
     /**
--- a/jdk/src/share/classes/java/beans/MethodDescriptor.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java	Wed Jul 05 17:17:57 2017 +0200
@@ -82,21 +82,21 @@
         Method method = getMethod0();
         if (method == null) {
             Class cls = getClass0();
-            if (cls != null) {
+            String name = getName();
+            if ((cls != null) && (name != null)) {
                 Class[] params = getParams();
                 if (params == null) {
                     for (int i = 0; i < 3; i++) {
                         // Find methods for up to 2 params. We are guessing here.
                         // This block should never execute unless the classloader
                         // that loaded the argument classes disappears.
-                        method = Introspector.findMethod(cls, getName(), i, null);
+                        method = Introspector.findMethod(cls, name, i);
                         if (method != null) {
                             break;
                         }
                     }
                 } else {
-                    method = Introspector.findMethod(cls, getName(),
-                                                     params.length, params);
+                    method = Statement.getMethod(cls, name, params);
                 }
                 setMethod(method);
             }
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java	Wed Jul 05 17:17:57 2017 +0200
@@ -112,9 +112,7 @@
         // If this class or one of its base classes allow PropertyChangeListener,
         // then we assume that any properties we discover are "bound".
         // See Introspector.getTargetPropertyInfo() method.
-        String name = "addPropertyChangeListener";
-        Class[] args = {PropertyChangeListener.class};
-        this.bound = (null != Introspector.findMethod(beanClass, name, args.length, args));
+        this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class);
     }
 
     /**
@@ -225,10 +223,10 @@
             // property type is.  For booleans, there can be "is" and "get"
             // methods.  If an "is" method exists, this is the official
             // reader method so look for this one first.
-            readMethod = Introspector.findMethod(cls, readMethodName, 0);
+            readMethod = Introspector.findInstanceMethod(cls, readMethodName);
             if (readMethod == null) {
                 readMethodName = Introspector.GET_PREFIX + getBaseName();
-                readMethod = Introspector.findMethod(cls, readMethodName, 0);
+                readMethod = Introspector.findInstanceMethod(cls, readMethodName);
             }
             try {
                 setReadMethod(readMethod);
@@ -293,8 +291,7 @@
                 writeMethodName = Introspector.SET_PREFIX + getBaseName();
             }
 
-            writeMethod = Introspector.findMethod(cls, writeMethodName, 1,
-                          (type == null) ? null : new Class[] { type });
+            writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type);
             if (writeMethod != null) {
                 if (!writeMethod.getReturnType().equals(void.class)) {
                     writeMethod = null;
--- a/jdk/src/share/classes/java/beans/PropertyEditorManager.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyEditorManager.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -81,10 +81,7 @@
         if (sm != null) {
             sm.checkPropertiesAccess();
         }
-        PropertyEditorFinder finder = getFinder();
-        synchronized (finder) {
-            finder.register(targetType, editorClass);
-        }
+        getFinder().register(targetType, editorClass);
     }
 
     /**
@@ -95,10 +92,7 @@
      * The result is null if no suitable editor can be found.
      */
     public static PropertyEditor findEditor(Class<?> targetType) {
-        PropertyEditorFinder finder = getFinder();
-        synchronized (finder) {
-            return finder.find(targetType);
-        }
+        return getFinder().find(targetType);
     }
 
     /**
@@ -110,10 +104,7 @@
      *         e.g. Sun implementation initially sets to  {"sun.beans.editors"}.
      */
     public static String[] getEditorSearchPath() {
-        PropertyEditorFinder finder = getFinder();
-        synchronized (finder) {
-            return finder.getPackages();
-        }
+        return getFinder().getPackages();
     }
 
     /**
@@ -134,10 +125,7 @@
         if (sm != null) {
             sm.checkPropertiesAccess();
         }
-        PropertyEditorFinder finder = getFinder();
-        synchronized (finder) {
-            finder.setPackages(path);
-        }
+        getFinder().setPackages(path);
     }
 
     private static PropertyEditorFinder getFinder() {
--- a/jdk/src/share/classes/java/beans/XMLDecoder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/XMLDecoder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -60,7 +60,7 @@
  *
  * @author Philip Milne
  */
-public class XMLDecoder {
+public class XMLDecoder implements AutoCloseable {
     private final DocumentHandler handler = new DocumentHandler();
     private final InputSource input;
     private Object owner;
--- a/jdk/src/share/classes/java/beans/XMLEncoder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/beans/XMLEncoder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -204,7 +204,7 @@
  *
  * @author Philip Milne
  */
-public class XMLEncoder extends Encoder {
+public class XMLEncoder extends Encoder implements AutoCloseable {
 
     private final CharsetEncoder encoder;
     private final String charset;
--- a/jdk/src/share/classes/java/io/Bits.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/io/Bits.java	Wed Jul 05 17:17:57 2017 +0200
@@ -41,51 +41,39 @@
     }
 
     static char getChar(byte[] b, int off) {
-        return (char) (((b[off + 1] & 0xFF) << 0) +
-                       ((b[off + 0]) << 8));
+        return (char) ((b[off + 1] & 0xFF) +
+                       (b[off] << 8));
     }
 
     static short getShort(byte[] b, int off) {
-        return (short) (((b[off + 1] & 0xFF) << 0) +
-                        ((b[off + 0]) << 8));
+        return (short) ((b[off + 1] & 0xFF) +
+                        (b[off] << 8));
     }
 
     static int getInt(byte[] b, int off) {
-        return ((b[off + 3] & 0xFF) << 0) +
-               ((b[off + 2] & 0xFF) << 8) +
+        return ((b[off + 3] & 0xFF)      ) +
+               ((b[off + 2] & 0xFF) <<  8) +
                ((b[off + 1] & 0xFF) << 16) +
-               ((b[off + 0]) << 24);
+               ((b[off    ]       ) << 24);
     }
 
     static float getFloat(byte[] b, int off) {
-        int i = ((b[off + 3] & 0xFF) << 0) +
-                ((b[off + 2] & 0xFF) << 8) +
-                ((b[off + 1] & 0xFF) << 16) +
-                ((b[off + 0]) << 24);
-        return Float.intBitsToFloat(i);
+        return Float.intBitsToFloat(getInt(b, off));
     }
 
     static long getLong(byte[] b, int off) {
-        return ((b[off + 7] & 0xFFL) << 0) +
-               ((b[off + 6] & 0xFFL) << 8) +
+        return ((b[off + 7] & 0xFFL)      ) +
+               ((b[off + 6] & 0xFFL) <<  8) +
                ((b[off + 5] & 0xFFL) << 16) +
                ((b[off + 4] & 0xFFL) << 24) +
                ((b[off + 3] & 0xFFL) << 32) +
                ((b[off + 2] & 0xFFL) << 40) +
                ((b[off + 1] & 0xFFL) << 48) +
-               (((long) b[off + 0]) << 56);
+               (((long) b[off])      << 56);
     }
 
     static double getDouble(byte[] b, int off) {
-        long j = ((b[off + 7] & 0xFFL) << 0) +
-                 ((b[off + 6] & 0xFFL) << 8) +
-                 ((b[off + 5] & 0xFFL) << 16) +
-                 ((b[off + 4] & 0xFFL) << 24) +
-                 ((b[off + 3] & 0xFFL) << 32) +
-                 ((b[off + 2] & 0xFFL) << 40) +
-                 ((b[off + 1] & 0xFFL) << 48) +
-                 (((long) b[off + 0]) << 56);
-        return Double.longBitsToDouble(j);
+        return Double.longBitsToDouble(getLong(b, off));
     }
 
     /*
@@ -98,50 +86,38 @@
     }
 
     static void putChar(byte[] b, int off, char val) {
-        b[off + 1] = (byte) (val >>> 0);
-        b[off + 0] = (byte) (val >>> 8);
+        b[off + 1] = (byte) (val      );
+        b[off    ] = (byte) (val >>> 8);
     }
 
     static void putShort(byte[] b, int off, short val) {
-        b[off + 1] = (byte) (val >>> 0);
-        b[off + 0] = (byte) (val >>> 8);
+        b[off + 1] = (byte) (val      );
+        b[off    ] = (byte) (val >>> 8);
     }
 
     static void putInt(byte[] b, int off, int val) {
-        b[off + 3] = (byte) (val >>> 0);
-        b[off + 2] = (byte) (val >>> 8);
+        b[off + 3] = (byte) (val       );
+        b[off + 2] = (byte) (val >>>  8);
         b[off + 1] = (byte) (val >>> 16);
-        b[off + 0] = (byte) (val >>> 24);
+        b[off    ] = (byte) (val >>> 24);
     }
 
     static void putFloat(byte[] b, int off, float val) {
-        int i = Float.floatToIntBits(val);
-        b[off + 3] = (byte) (i >>> 0);
-        b[off + 2] = (byte) (i >>> 8);
-        b[off + 1] = (byte) (i >>> 16);
-        b[off + 0] = (byte) (i >>> 24);
+        putInt(b, off,  Float.floatToIntBits(val));
     }
 
     static void putLong(byte[] b, int off, long val) {
-        b[off + 7] = (byte) (val >>> 0);
-        b[off + 6] = (byte) (val >>> 8);
+        b[off + 7] = (byte) (val       );
+        b[off + 6] = (byte) (val >>>  8);
         b[off + 5] = (byte) (val >>> 16);
         b[off + 4] = (byte) (val >>> 24);
         b[off + 3] = (byte) (val >>> 32);
         b[off + 2] = (byte) (val >>> 40);
         b[off + 1] = (byte) (val >>> 48);
-        b[off + 0] = (byte) (val >>> 56);
+        b[off    ] = (byte) (val >>> 56);
     }
 
     static void putDouble(byte[] b, int off, double val) {
-        long j = Double.doubleToLongBits(val);
-        b[off + 7] = (byte) (j >>> 0);
-        b[off + 6] = (byte) (j >>> 8);
-        b[off + 5] = (byte) (j >>> 16);
-        b[off + 4] = (byte) (j >>> 24);
-        b[off + 3] = (byte) (j >>> 32);
-        b[off + 2] = (byte) (j >>> 40);
-        b[off + 1] = (byte) (j >>> 48);
-        b[off + 0] = (byte) (j >>> 56);
+        putLong(b, off, Double.doubleToLongBits(val));
     }
 }
--- a/jdk/src/share/classes/java/io/Closeable.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/io/Closeable.java	Wed Jul 05 17:17:57 2017 +0200
@@ -28,14 +28,14 @@
 import java.io.IOException;
 
 /**
- * A <tt>Closeable</tt> is a source or destination of data that can be closed.
+ * A {@code Closeable} is a source or destination of data that can be closed.
  * The close method is invoked to release resources that the object is
  * holding (such as open files).
  *
  * @since 1.5
  */
 
-public interface Closeable {
+public interface Closeable extends AutoCloseable {
 
     /**
      * Closes this stream and releases any system resources associated
@@ -45,5 +45,4 @@
      * @throws IOException if an I/O error occurs
      */
     public void close() throws IOException;
-
 }
--- a/jdk/src/share/classes/java/io/ObjectInput.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/io/ObjectInput.java	Wed Jul 05 17:17:57 2017 +0200
@@ -36,7 +36,7 @@
  * @see java.io.ObjectInputStream
  * @since   JDK1.1
  */
-public interface ObjectInput extends DataInput {
+public interface ObjectInput extends DataInput, AutoCloseable {
     /**
      * Read and return an object. The class that implements this interface
      * defines where the object is "read" from.
--- a/jdk/src/share/classes/java/io/ObjectOutput.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/io/ObjectOutput.java	Wed Jul 05 17:17:57 2017 +0200
@@ -36,7 +36,7 @@
  * @see java.io.ObjectInputStream
  * @since   JDK1.1
  */
-public interface ObjectOutput extends DataOutput {
+public interface ObjectOutput extends DataOutput, AutoCloseable {
     /**
      * Write an object to the underlying storage or stream.  The
      * class that implements this interface defines how the object is
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -721,20 +721,19 @@
      * {@code codePoint} isn't a valid Unicode code point
      */
     public AbstractStringBuilder appendCodePoint(int codePoint) {
-        if (!Character.isValidCodePoint(codePoint)) {
+        final int count = this.count;
+
+        if (Character.isBmpCodePoint(codePoint)) {
+            ensureCapacityInternal(count + 1);
+            value[count] = (char) codePoint;
+            this.count = count + 1;
+        } else if (Character.isValidCodePoint(codePoint)) {
+            ensureCapacityInternal(count + 2);
+            Character.toSurrogates(codePoint, value, count);
+            this.count = count + 2;
+        } else {
             throw new IllegalArgumentException();
         }
-        int n = 1;
-        if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            n++;
-        }
-        ensureCapacityInternal(count + n);
-        if (n == 1) {
-            value[count++] = (char) codePoint;
-        } else {
-            Character.toSurrogates(codePoint, value, count);
-            count += n;
-        }
         return this;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/AutoCloseable.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009, 2010, 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 java.lang;
+
+/**
+ * A resource that must be closed when it is no longer needed.
+ *
+ * @author Josh Bloch
+ * @since 1.7
+ */
+public interface AutoCloseable {
+    /**
+     * Close this resource, relinquishing any underlying resources.
+     * This method is invoked automatically by the automatic resource
+     * management block construct.
+     *
+     * <p>Classes implementing this method are strongly encouraged to
+     * be declared to throw more specific exceptions (or no exception
+     * at all, if the close cannot fail).
+     *
+     * @throws Exception if this resource cannot be closed
+     */
+    void close() throws Exception;
+}
--- a/jdk/src/share/classes/java/lang/Character.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/lang/Character.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
  */
 
 package java.lang;
+
 import java.util.Arrays;
 import java.util.Map;
 import java.util.HashMap;
@@ -67,17 +68,16 @@
  * definition</i></a> of the U+<i>n</i> notation in the Unicode
  * standard.)
  *
- * <p>The set of characters from U+0000 to U+FFFF is sometimes
- * referred to as the <em>Basic Multilingual Plane (BMP)</em>. <a
- * name="supplementary">Characters</a> whose code points are greater
+ * <p><a name="BMP">The set of characters from U+0000 to U+FFFF is
+ * sometimes referred to as the <em>Basic Multilingual Plane (BMP)</em>.
+ * <a name="supplementary">Characters</a> whose code points are greater
  * than U+FFFF are called <em>supplementary character</em>s.  The Java
- * 2 platform uses the UTF-16 representation in <code>char</code>
- * arrays and in the <code>String</code> and <code>StringBuffer</code>
- * classes. In this representation, supplementary characters are
- * represented as a pair of <code>char</code> values, the first from
- * the <em>high-surrogates</em> range, (&#92;uD800-&#92;uDBFF), the
- * second from the <em>low-surrogates</em> range
- * (&#92;uDC00-&#92;uDFFF).
+ * platform uses the UTF-16 representation in <code>char</code> arrays and
+ * in the <code>String</code> and <code>StringBuffer</code> classes. In
+ * this representation, supplementary characters are represented as a pair
+ * of <code>char</code> values, the first from the <em>high-surrogates</em>
+ * range, (&#92;uD800-&#92;uDBFF), the second from the
+ * <em>low-surrogates</em> range (&#92;uDC00-&#92;uDFFF).
  *
  * <p>A <code>char</code> value, therefore, represents Basic
  * Multilingual Plane (BMP) code points, including the surrogate
@@ -115,10 +115,12 @@
  * @author  Lee Boynton
  * @author  Guy Steele
  * @author  Akira Tanaka
+ * @author  Martin Buchholz
+ * @author  Ulf Zibis
  * @since   1.0
  */
 public final
-class Character extends Object implements java.io.Serializable, Comparable<Character> {
+class Character implements java.io.Serializable, Comparable<Character> {
     /**
      * The minimum radix available for conversion to and from strings.
      * The constant value of this field is the smallest value permitted
@@ -127,10 +129,10 @@
      * method, and the <code>toString</code> method of class
      * <code>Integer</code>.
      *
-     * @see     java.lang.Character#digit(char, int)
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Integer#toString(int, int)
-     * @see     java.lang.Integer#valueOf(java.lang.String)
+     * @see     Character#digit(char, int)
+     * @see     Character#forDigit(int, int)
+     * @see     Integer#toString(int, int)
+     * @see     Integer#valueOf(String)
      */
     public static final int MIN_RADIX = 2;
 
@@ -142,10 +144,10 @@
      * method, and the <code>toString</code> method of class
      * <code>Integer</code>.
      *
-     * @see     java.lang.Character#digit(char, int)
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Integer#toString(int, int)
-     * @see     java.lang.Integer#valueOf(java.lang.String)
+     * @see     Character#digit(char, int)
+     * @see     Character#forDigit(int, int)
+     * @see     Integer#toString(int, int)
+     * @see     Integer#valueOf(String)
      */
     public static final int MAX_RADIX = 36;
 
@@ -155,7 +157,7 @@
      *
      * @since   1.0.2
      */
-    public static final char   MIN_VALUE = '\u0000';
+    public static final char MIN_VALUE = '\u0000';
 
     /**
      * The constant value of this field is the largest value of type
@@ -163,7 +165,7 @@
      *
      * @since   1.0.2
      */
-    public static final char   MAX_VALUE = '\uFFFF';
+    public static final char MAX_VALUE = '\uFFFF';
 
     /**
      * The <code>Class</code> instance representing the primitive type
@@ -171,230 +173,201 @@
      *
      * @since   1.1
      */
+    @SuppressWarnings("unchecked")
     public static final Class<Character> TYPE = Class.getPrimitiveClass("char");
 
-   /*
-    * Normative general types
-    */
-
-   /*
-    * General character types
-    */
-
-   /**
-    * General category "Cn" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        UNASSIGNED                  = 0;
-
-   /**
-    * General category "Lu" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        UPPERCASE_LETTER            = 1;
-
-   /**
-    * General category "Ll" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        LOWERCASE_LETTER            = 2;
-
-   /**
-    * General category "Lt" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        TITLECASE_LETTER            = 3;
-
-   /**
-    * General category "Lm" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        MODIFIER_LETTER             = 4;
-
-   /**
-    * General category "Lo" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        OTHER_LETTER                = 5;
-
-   /**
-    * General category "Mn" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        NON_SPACING_MARK            = 6;
-
-   /**
-    * General category "Me" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        ENCLOSING_MARK              = 7;
-
-   /**
-    * General category "Mc" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        COMBINING_SPACING_MARK      = 8;
-
-   /**
-    * General category "Nd" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        DECIMAL_DIGIT_NUMBER        = 9;
-
-   /**
-    * General category "Nl" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        LETTER_NUMBER               = 10;
-
-   /**
-    * General category "No" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        OTHER_NUMBER                = 11;
-
-   /**
-    * General category "Zs" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        SPACE_SEPARATOR             = 12;
-
-   /**
-    * General category "Zl" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        LINE_SEPARATOR              = 13;
-
-   /**
-    * General category "Zp" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        PARAGRAPH_SEPARATOR         = 14;
-
-   /**
-    * General category "Cc" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        CONTROL                     = 15;
-
-   /**
-    * General category "Cf" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        FORMAT                      = 16;
-
-   /**
-    * General category "Co" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        PRIVATE_USE                 = 18;
-
-   /**
-    * General category "Cs" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        SURROGATE                   = 19;
-
-   /**
-    * General category "Pd" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        DASH_PUNCTUATION            = 20;
-
-   /**
-    * General category "Ps" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        START_PUNCTUATION           = 21;
-
-   /**
-    * General category "Pe" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        END_PUNCTUATION             = 22;
-
-   /**
-    * General category "Pc" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        CONNECTOR_PUNCTUATION       = 23;
-
-   /**
-    * General category "Po" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        OTHER_PUNCTUATION           = 24;
-
-   /**
-    * General category "Sm" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        MATH_SYMBOL                 = 25;
-
-   /**
-    * General category "Sc" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        CURRENCY_SYMBOL             = 26;
-
-   /**
-    * General category "Sk" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        MODIFIER_SYMBOL             = 27;
-
-   /**
-    * General category "So" in the Unicode specification.
-    * @since   1.1
-    */
-    public static final byte
-        OTHER_SYMBOL                = 28;
-
-   /**
-    * General category "Pi" in the Unicode specification.
-    * @since   1.4
-    */
-    public static final byte
-        INITIAL_QUOTE_PUNCTUATION   = 29;
-
-   /**
-    * General category "Pf" in the Unicode specification.
-    * @since   1.4
-    */
-    public static final byte
-        FINAL_QUOTE_PUNCTUATION     = 30;
+    /*
+     * Normative general types
+     */
+
+    /*
+     * General character types
+     */
+
+    /**
+     * General category "Cn" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte UNASSIGNED = 0;
+
+    /**
+     * General category "Lu" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte UPPERCASE_LETTER = 1;
+
+    /**
+     * General category "Ll" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte LOWERCASE_LETTER = 2;
+
+    /**
+     * General category "Lt" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte TITLECASE_LETTER = 3;
+
+    /**
+     * General category "Lm" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte MODIFIER_LETTER = 4;
+
+    /**
+     * General category "Lo" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte OTHER_LETTER = 5;
+
+    /**
+     * General category "Mn" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte NON_SPACING_MARK = 6;
+
+    /**
+     * General category "Me" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte ENCLOSING_MARK = 7;
+
+    /**
+     * General category "Mc" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte COMBINING_SPACING_MARK = 8;
+
+    /**
+     * General category "Nd" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte DECIMAL_DIGIT_NUMBER        = 9;
+
+    /**
+     * General category "Nl" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte LETTER_NUMBER = 10;
+
+    /**
+     * General category "No" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte OTHER_NUMBER = 11;
+
+    /**
+     * General category "Zs" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte SPACE_SEPARATOR = 12;
+
+    /**
+     * General category "Zl" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte LINE_SEPARATOR = 13;
+
+    /**
+     * General category "Zp" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte PARAGRAPH_SEPARATOR = 14;
+
+    /**
+     * General category "Cc" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte CONTROL = 15;
+
+    /**
+     * General category "Cf" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte FORMAT = 16;
+
+    /**
+     * General category "Co" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte PRIVATE_USE = 18;
+
+    /**
+     * General category "Cs" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte SURROGATE = 19;
+
+    /**
+     * General category "Pd" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte DASH_PUNCTUATION = 20;
+
+    /**
+     * General category "Ps" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte START_PUNCTUATION = 21;
+
+    /**
+     * General category "Pe" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte END_PUNCTUATION = 22;
+
+    /**
+     * General category "Pc" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte CONNECTOR_PUNCTUATION = 23;
+
+    /**
+     * General category "Po" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte OTHER_PUNCTUATION = 24;
+
+    /**
+     * General category "Sm" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte MATH_SYMBOL = 25;
+
+    /**
+     * General category "Sc" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte CURRENCY_SYMBOL = 26;
+
+    /**
+     * General category "Sk" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte MODIFIER_SYMBOL = 27;
+
+    /**
+     * General category "So" in the Unicode specification.
+     * @since   1.1
+     */
+    public static final byte OTHER_SYMBOL = 28;
+
+    /**
+     * General category "Pi" in the Unicode specification.
+     * @since   1.4
+     */
+    public static final byte INITIAL_QUOTE_PUNCTUATION = 29;
+
+    /**
+     * General category "Pf" in the Unicode specification.
+     * @since   1.4
+     */
+    public static final byte FINAL_QUOTE_PUNCTUATION = 30;
 
     /**
      * Error flag. Use int (code point) to avoid confusion with U+FFFF.
      */
-     static final int ERROR = 0xFFFFFFFF;
+    static final int ERROR = 0xFFFFFFFF;
 
 
     /**
@@ -402,7 +375,7 @@
      * values have undefined directionality in the Unicode specification.
      * @since 1.4
      */
-     public static final byte DIRECTIONALITY_UNDEFINED = -1;
+    public static final byte DIRECTIONALITY_UNDEFINED = -1;
 
     /**
      * Strong bidirectional character type "L" in the Unicode specification.
@@ -609,9 +582,9 @@
     /**
      * Instances of this class represent particular subsets of the Unicode
      * character set.  The only family of subsets defined in the
-     * <code>Character</code> class is <code>{@link Character.UnicodeBlock
-     * UnicodeBlock}</code>.  Other portions of the Java API may define other
-     * subsets for their own purposes.
+     * <code>Character</code> class is {@link Character.UnicodeBlock}.
+     * Other portions of the Java API may define other subsets for their
+     * own purposes.
      *
      * @since 1.2
      */
@@ -624,6 +597,7 @@
          *
          * @exception NullPointerException if name is <code>null</code>
          * @param  name  The name of this subset
+         * @exception NullPointerException if name is <code>null</code>
          */
         protected Subset(String name) {
             if (name == null) {
@@ -662,6 +636,9 @@
         }
     }
 
+    // See http://www.unicode.org/Public/UNIDATA/Blocks.txt
+    // for the latest specification of Unicode Blocks.
+
     /**
      * A family of character subsets representing the character blocks in the
      * Unicode specification. Character blocks generally define characters
@@ -672,37 +649,35 @@
      */
     public static final class UnicodeBlock extends Subset {
 
-        private static Map map = new HashMap();
-
-        /**
-         * Create a UnicodeBlock with the given identifier name.
+        private static Map<String, UnicodeBlock> map
+            = new HashMap<String, UnicodeBlock>(256);
+
+        /**
+         * Creates a UnicodeBlock with the given identifier name.
          * This name must be the same as the block identifier.
          */
         private UnicodeBlock(String idName) {
             super(idName);
-            map.put(idName.toUpperCase(Locale.US), this);
+            map.put(idName, this);
         }
 
         /**
-         * Create a UnicodeBlock with the given identifier name and
+         * Creates a UnicodeBlock with the given identifier name and
          * alias name.
          */
         private UnicodeBlock(String idName, String alias) {
             this(idName);
-            map.put(alias.toUpperCase(Locale.US), this);
+            map.put(alias, this);
         }
 
         /**
-         * Create a UnicodeBlock with the given identifier name and
+         * Creates a UnicodeBlock with the given identifier name and
          * alias names.
          */
-        private UnicodeBlock(String idName, String[] aliasName) {
+        private UnicodeBlock(String idName, String... aliases) {
             this(idName);
-            if (aliasName != null) {
-                for(int x=0; x<aliasName.length; ++x) {
-                    map.put(aliasName[x].toUpperCase(Locale.US), this);
-                }
-            }
+            for (String alias : aliases)
+                map.put(alias, this);
         }
 
         /**
@@ -710,51 +685,63 @@
          * @since 1.2
          */
         public static final UnicodeBlock  BASIC_LATIN =
-            new UnicodeBlock("BASIC_LATIN", new String[] {"Basic Latin", "BasicLatin" });
+            new UnicodeBlock("BASIC_LATIN",
+                             "BASIC LATIN",
+                             "BASICLATIN");
 
         /**
          * Constant for the "Latin-1 Supplement" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock LATIN_1_SUPPLEMENT =
-            new UnicodeBlock("LATIN_1_SUPPLEMENT", new String[]{ "Latin-1 Supplement", "Latin-1Supplement"});
+            new UnicodeBlock("LATIN_1_SUPPLEMENT",
+                             "LATIN-1 SUPPLEMENT",
+                             "LATIN-1SUPPLEMENT");
 
         /**
          * Constant for the "Latin Extended-A" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock LATIN_EXTENDED_A =
-            new UnicodeBlock("LATIN_EXTENDED_A", new String[]{ "Latin Extended-A", "LatinExtended-A"});
+            new UnicodeBlock("LATIN_EXTENDED_A",
+                             "LATIN EXTENDED-A",
+                             "LATINEXTENDED-A");
 
         /**
          * Constant for the "Latin Extended-B" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock LATIN_EXTENDED_B =
-            new UnicodeBlock("LATIN_EXTENDED_B", new String[] {"Latin Extended-B", "LatinExtended-B"});
+            new UnicodeBlock("LATIN_EXTENDED_B",
+                             "LATIN EXTENDED-B",
+                             "LATINEXTENDED-B");
 
         /**
          * Constant for the "IPA Extensions" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock IPA_EXTENSIONS =
-            new UnicodeBlock("IPA_EXTENSIONS", new String[] {"IPA Extensions", "IPAExtensions"});
+            new UnicodeBlock("IPA_EXTENSIONS",
+                             "IPA EXTENSIONS",
+                             "IPAEXTENSIONS");
 
         /**
          * Constant for the "Spacing Modifier Letters" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock SPACING_MODIFIER_LETTERS =
-            new UnicodeBlock("SPACING_MODIFIER_LETTERS", new String[] { "Spacing Modifier Letters",
-                                                                        "SpacingModifierLetters"});
+            new UnicodeBlock("SPACING_MODIFIER_LETTERS",
+                             "SPACING MODIFIER LETTERS",
+                             "SPACINGMODIFIERLETTERS");
 
         /**
          * Constant for the "Combining Diacritical Marks" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS =
-            new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", new String[] {"Combining Diacritical Marks",
-                                                                          "CombiningDiacriticalMarks" });
+            new UnicodeBlock("COMBINING_DIACRITICAL_MARKS",
+                             "COMBINING DIACRITICAL MARKS",
+                             "COMBININGDIACRITICALMARKS");
 
         /**
          * Constant for the "Greek and Coptic" Unicode character block.
@@ -763,8 +750,10 @@
          *
          * @since 1.2
          */
-        public static final UnicodeBlock GREEK
-            = new UnicodeBlock("GREEK", new String[] {"Greek and Coptic", "GreekandCoptic"});
+        public static final UnicodeBlock GREEK =
+            new UnicodeBlock("GREEK",
+                             "GREEK AND COPTIC",
+                             "GREEKANDCOPTIC");
 
         /**
          * Constant for the "Cyrillic" Unicode character block.
@@ -890,44 +879,54 @@
          * @since 1.2
          */
         public static final UnicodeBlock HANGUL_JAMO =
-            new UnicodeBlock("HANGUL_JAMO", new String[] {"Hangul Jamo", "HangulJamo"});
+            new UnicodeBlock("HANGUL_JAMO",
+                             "HANGUL JAMO",
+                             "HANGULJAMO");
 
         /**
          * Constant for the "Latin Extended Additional" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL =
-            new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", new String[] {"Latin Extended Additional",
-                                                                        "LatinExtendedAdditional"});
+            new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL",
+                             "LATIN EXTENDED ADDITIONAL",
+                             "LATINEXTENDEDADDITIONAL");
 
         /**
          * Constant for the "Greek Extended" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock GREEK_EXTENDED =
-            new UnicodeBlock("GREEK_EXTENDED", new String[] {"Greek Extended", "GreekExtended"});
+            new UnicodeBlock("GREEK_EXTENDED",
+                             "GREEK EXTENDED",
+                             "GREEKEXTENDED");
 
         /**
          * Constant for the "General Punctuation" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock GENERAL_PUNCTUATION =
-            new UnicodeBlock("GENERAL_PUNCTUATION", new String[] {"General Punctuation", "GeneralPunctuation"});
+            new UnicodeBlock("GENERAL_PUNCTUATION",
+                             "GENERAL PUNCTUATION",
+                             "GENERALPUNCTUATION");
 
         /**
          * Constant for the "Superscripts and Subscripts" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS =
-            new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", new String[] {"Superscripts and Subscripts",
-                                                                          "SuperscriptsandSubscripts" });
+            new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS",
+                             "SUPERSCRIPTS AND SUBSCRIPTS",
+                             "SUPERSCRIPTSANDSUBSCRIPTS");
 
         /**
          * Constant for the "Currency Symbols" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock CURRENCY_SYMBOLS =
-            new UnicodeBlock("CURRENCY_SYMBOLS", new String[] { "Currency Symbols", "CurrencySymbols"});
+            new UnicodeBlock("CURRENCY_SYMBOLS",
+                             "CURRENCY SYMBOLS",
+                             "CURRENCYSYMBOLS");
 
         /**
          * Constant for the "Combining Diacritical Marks for Symbols" Unicode character block.
@@ -936,24 +935,29 @@
          * @since 1.2
          */
         public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS =
-            new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", new String[] {"Combining Diacritical Marks for Symbols",
-                                                                                                                                                   "CombiningDiacriticalMarksforSymbols",
-                                                                           "Combining Marks for Symbols",
-                                                                           "CombiningMarksforSymbols" });
+            new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS",
+                             "COMBINING DIACRITICAL MARKS FOR SYMBOLS",
+                             "COMBININGDIACRITICALMARKSFORSYMBOLS",
+                             "COMBINING MARKS FOR SYMBOLS",
+                             "COMBININGMARKSFORSYMBOLS");
 
         /**
          * Constant for the "Letterlike Symbols" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock LETTERLIKE_SYMBOLS =
-            new UnicodeBlock("LETTERLIKE_SYMBOLS", new String[] { "Letterlike Symbols", "LetterlikeSymbols"});
+            new UnicodeBlock("LETTERLIKE_SYMBOLS",
+                             "LETTERLIKE SYMBOLS",
+                             "LETTERLIKESYMBOLS");
 
         /**
          * Constant for the "Number Forms" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock NUMBER_FORMS =
-            new UnicodeBlock("NUMBER_FORMS", new String[] {"Number Forms", "NumberForms"});
+            new UnicodeBlock("NUMBER_FORMS",
+                             "NUMBER FORMS",
+                             "NUMBERFORMS");
 
         /**
          * Constant for the "Arrows" Unicode character block.
@@ -967,68 +971,81 @@
          * @since 1.2
          */
         public static final UnicodeBlock MATHEMATICAL_OPERATORS =
-            new UnicodeBlock("MATHEMATICAL_OPERATORS", new String[] {"Mathematical Operators",
-                                                                     "MathematicalOperators"});
+            new UnicodeBlock("MATHEMATICAL_OPERATORS",
+                             "MATHEMATICAL OPERATORS",
+                             "MATHEMATICALOPERATORS");
 
         /**
          * Constant for the "Miscellaneous Technical" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock MISCELLANEOUS_TECHNICAL =
-            new UnicodeBlock("MISCELLANEOUS_TECHNICAL", new String[] {"Miscellaneous Technical",
-                                                                      "MiscellaneousTechnical"});
+            new UnicodeBlock("MISCELLANEOUS_TECHNICAL",
+                             "MISCELLANEOUS TECHNICAL",
+                             "MISCELLANEOUSTECHNICAL");
 
         /**
          * Constant for the "Control Pictures" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock CONTROL_PICTURES =
-            new UnicodeBlock("CONTROL_PICTURES", new String[] {"Control Pictures", "ControlPictures"});
+            new UnicodeBlock("CONTROL_PICTURES",
+                             "CONTROL PICTURES",
+                             "CONTROLPICTURES");
 
         /**
          * Constant for the "Optical Character Recognition" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION =
-            new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", new String[] {"Optical Character Recognition",
-                                                                            "OpticalCharacterRecognition"});
+            new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION",
+                             "OPTICAL CHARACTER RECOGNITION",
+                             "OPTICALCHARACTERRECOGNITION");
 
         /**
          * Constant for the "Enclosed Alphanumerics" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock ENCLOSED_ALPHANUMERICS =
-            new UnicodeBlock("ENCLOSED_ALPHANUMERICS", new String[] {"Enclosed Alphanumerics",
-                                                                     "EnclosedAlphanumerics"});
+            new UnicodeBlock("ENCLOSED_ALPHANUMERICS",
+                             "ENCLOSED ALPHANUMERICS",
+                             "ENCLOSEDALPHANUMERICS");
 
         /**
          * Constant for the "Box Drawing" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock BOX_DRAWING =
-            new UnicodeBlock("BOX_DRAWING", new String[] {"Box Drawing", "BoxDrawing"});
+            new UnicodeBlock("BOX_DRAWING",
+                             "BOX DRAWING",
+                             "BOXDRAWING");
 
         /**
          * Constant for the "Block Elements" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock BLOCK_ELEMENTS =
-            new UnicodeBlock("BLOCK_ELEMENTS", new String[] {"Block Elements", "BlockElements"});
+            new UnicodeBlock("BLOCK_ELEMENTS",
+                             "BLOCK ELEMENTS",
+                             "BLOCKELEMENTS");
 
         /**
          * Constant for the "Geometric Shapes" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock GEOMETRIC_SHAPES =
-            new UnicodeBlock("GEOMETRIC_SHAPES", new String[] {"Geometric Shapes", "GeometricShapes"});
+            new UnicodeBlock("GEOMETRIC_SHAPES",
+                             "GEOMETRIC SHAPES",
+                             "GEOMETRICSHAPES");
 
         /**
          * Constant for the "Miscellaneous Symbols" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock MISCELLANEOUS_SYMBOLS =
-            new UnicodeBlock("MISCELLANEOUS_SYMBOLS", new String[] {"Miscellaneous Symbols",
-                                                                    "MiscellaneousSymbols"});
+            new UnicodeBlock("MISCELLANEOUS_SYMBOLS",
+                             "MISCELLANEOUS SYMBOLS",
+                             "MISCELLANEOUSSYMBOLS");
 
         /**
          * Constant for the "Dingbats" Unicode character block.
@@ -1042,8 +1059,9 @@
          * @since 1.2
          */
         public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION =
-            new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", new String[] {"CJK Symbols and Punctuation",
-                                                                          "CJKSymbolsandPunctuation"});
+            new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION",
+                             "CJK SYMBOLS AND PUNCTUATION",
+                             "CJKSYMBOLSANDPUNCTUATION");
 
         /**
          * Constant for the "Hiragana" Unicode character block.
@@ -1071,8 +1089,9 @@
          * @since 1.2
          */
         public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO =
-            new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", new String[] {"Hangul Compatibility Jamo",
-                                                                        "HangulCompatibilityJamo"});
+            new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO",
+                             "HANGUL COMPATIBILITY JAMO",
+                             "HANGULCOMPATIBILITYJAMO");
 
         /**
          * Constant for the "Kanbun" Unicode character block.
@@ -1086,37 +1105,45 @@
          * @since 1.2
          */
         public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS =
-            new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", new String[] {"Enclosed CJK Letters and Months",
-                                                                              "EnclosedCJKLettersandMonths"});
+            new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS",
+                             "ENCLOSED CJK LETTERS AND MONTHS",
+                             "ENCLOSEDCJKLETTERSANDMONTHS");
 
         /**
          * Constant for the "CJK Compatibility" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock CJK_COMPATIBILITY =
-            new UnicodeBlock("CJK_COMPATIBILITY", new String[] {"CJK Compatibility", "CJKCompatibility"});
+            new UnicodeBlock("CJK_COMPATIBILITY",
+                             "CJK COMPATIBILITY",
+                             "CJKCOMPATIBILITY");
 
         /**
          * Constant for the "CJK Unified Ideographs" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS =
-            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", new String[] {"CJK Unified Ideographs",
-                                                                     "CJKUnifiedIdeographs"});
+            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS",
+                             "CJK UNIFIED IDEOGRAPHS",
+                             "CJKUNIFIEDIDEOGRAPHS");
 
         /**
          * Constant for the "Hangul Syllables" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock HANGUL_SYLLABLES =
-            new UnicodeBlock("HANGUL_SYLLABLES", new String[] {"Hangul Syllables", "HangulSyllables"});
+            new UnicodeBlock("HANGUL_SYLLABLES",
+                             "HANGUL SYLLABLES",
+                             "HANGULSYLLABLES");
 
         /**
          * Constant for the "Private Use Area" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock PRIVATE_USE_AREA =
-            new UnicodeBlock("PRIVATE_USE_AREA", new String[] {"Private Use Area", "PrivateUseArea"});
+            new UnicodeBlock("PRIVATE_USE_AREA",
+                             "PRIVATE USE AREA",
+                             "PRIVATEUSEAREA");
 
         /**
          * Constant for the "CJK Compatibility Ideographs" Unicode character block.
@@ -1124,56 +1151,62 @@
          */
         public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS =
             new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS",
-                             new String[] {"CJK Compatibility Ideographs",
-                                           "CJKCompatibilityIdeographs"});
+                             "CJK COMPATIBILITY IDEOGRAPHS",
+                             "CJKCOMPATIBILITYIDEOGRAPHS");
 
         /**
          * Constant for the "Alphabetic Presentation Forms" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS =
-            new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", new String[] {"Alphabetic Presentation Forms",
-                                                                            "AlphabeticPresentationForms"});
+            new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS",
+                             "ALPHABETIC PRESENTATION FORMS",
+                             "ALPHABETICPRESENTATIONFORMS");
 
         /**
          * Constant for the "Arabic Presentation Forms-A" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A =
-            new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", new String[] {"Arabic Presentation Forms-A",
-                                                                          "ArabicPresentationForms-A"});
+            new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A",
+                             "ARABIC PRESENTATION FORMS-A",
+                             "ARABICPRESENTATIONFORMS-A");
 
         /**
          * Constant for the "Combining Half Marks" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock COMBINING_HALF_MARKS =
-            new UnicodeBlock("COMBINING_HALF_MARKS", new String[] {"Combining Half Marks",
-                                                                   "CombiningHalfMarks"});
+            new UnicodeBlock("COMBINING_HALF_MARKS",
+                             "COMBINING HALF MARKS",
+                             "COMBININGHALFMARKS");
 
         /**
          * Constant for the "CJK Compatibility Forms" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock CJK_COMPATIBILITY_FORMS =
-            new UnicodeBlock("CJK_COMPATIBILITY_FORMS", new String[] {"CJK Compatibility Forms",
-                                                                      "CJKCompatibilityForms"});
+            new UnicodeBlock("CJK_COMPATIBILITY_FORMS",
+                             "CJK COMPATIBILITY FORMS",
+                             "CJKCOMPATIBILITYFORMS");
 
         /**
          * Constant for the "Small Form Variants" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock SMALL_FORM_VARIANTS =
-            new UnicodeBlock("SMALL_FORM_VARIANTS", new String[] {"Small Form Variants",
-                                                                  "SmallFormVariants"});
+            new UnicodeBlock("SMALL_FORM_VARIANTS",
+                             "SMALL FORM VARIANTS",
+                             "SMALLFORMVARIANTS");
 
         /**
          * Constant for the "Arabic Presentation Forms-B" Unicode character block.
          * @since 1.2
          */
         public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B =
-            new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", new String[] {"Arabic Presentation Forms-B",
-                                                                          "ArabicPresentationForms-B"});
+            new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B",
+                             "ARABIC PRESENTATION FORMS-B",
+                             "ARABICPRESENTATIONFORMS-B");
 
         /**
          * Constant for the "Halfwidth and Fullwidth Forms" Unicode character block.
@@ -1181,8 +1214,8 @@
          */
         public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS =
             new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS",
-                             new String[] {"Halfwidth and Fullwidth Forms",
-                                           "HalfwidthandFullwidthForms"});
+                             "HALFWIDTH AND FULLWIDTH FORMS",
+                             "HALFWIDTHANDFULLWIDTHFORMS");
 
         /**
          * Constant for the "Specials" Unicode character block.
@@ -1251,97 +1284,108 @@
          */
         public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS =
             new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS",
-                             new String[] {"Unified Canadian Aboriginal Syllabics",
-                                           "UnifiedCanadianAboriginalSyllabics"});
+                             "UNIFIED CANADIAN ABORIGINAL SYLLABICS",
+                             "UNIFIEDCANADIANABORIGINALSYLLABICS");
 
         /**
          * Constant for the "Ogham" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock OGHAM =
-                             new UnicodeBlock("OGHAM");
+            new UnicodeBlock("OGHAM");
 
         /**
          * Constant for the "Runic" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock RUNIC =
-                             new UnicodeBlock("RUNIC");
+            new UnicodeBlock("RUNIC");
 
         /**
          * Constant for the "Khmer" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock KHMER =
-                             new UnicodeBlock("KHMER");
+            new UnicodeBlock("KHMER");
 
         /**
          * Constant for the "Mongolian" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock MONGOLIAN =
-                             new UnicodeBlock("MONGOLIAN");
+            new UnicodeBlock("MONGOLIAN");
 
         /**
          * Constant for the "Braille Patterns" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock BRAILLE_PATTERNS =
-            new UnicodeBlock("BRAILLE_PATTERNS", new String[] {"Braille Patterns",
-                                                               "BraillePatterns"});
+            new UnicodeBlock("BRAILLE_PATTERNS",
+                             "BRAILLE PATTERNS",
+                             "BRAILLEPATTERNS");
 
         /**
          * Constant for the "CJK Radicals Supplement" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT =
-             new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", new String[] {"CJK Radicals Supplement",
-                                                                       "CJKRadicalsSupplement"});
+            new UnicodeBlock("CJK_RADICALS_SUPPLEMENT",
+                             "CJK RADICALS SUPPLEMENT",
+                             "CJKRADICALSSUPPLEMENT");
 
         /**
          * Constant for the "Kangxi Radicals" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock KANGXI_RADICALS =
-            new UnicodeBlock("KANGXI_RADICALS", new String[] {"Kangxi Radicals", "KangxiRadicals"});
+            new UnicodeBlock("KANGXI_RADICALS",
+                             "KANGXI RADICALS",
+                             "KANGXIRADICALS");
 
         /**
          * Constant for the "Ideographic Description Characters" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS =
-            new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", new String[] {"Ideographic Description Characters",
-                                                                                 "IdeographicDescriptionCharacters"});
+            new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS",
+                             "IDEOGRAPHIC DESCRIPTION CHARACTERS",
+                             "IDEOGRAPHICDESCRIPTIONCHARACTERS");
 
         /**
          * Constant for the "Bopomofo Extended" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock BOPOMOFO_EXTENDED =
-            new UnicodeBlock("BOPOMOFO_EXTENDED", new String[] {"Bopomofo Extended",
-                                                                "BopomofoExtended"});
+            new UnicodeBlock("BOPOMOFO_EXTENDED",
+                             "BOPOMOFO EXTENDED",
+                             "BOPOMOFOEXTENDED");
 
         /**
          * Constant for the "CJK Unified Ideographs Extension A" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A =
-            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", new String[] {"CJK Unified Ideographs Extension A",
-                                                                                 "CJKUnifiedIdeographsExtensionA"});
+            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A",
+                             "CJK UNIFIED IDEOGRAPHS EXTENSION A",
+                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONA");
 
         /**
          * Constant for the "Yi Syllables" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock YI_SYLLABLES =
-            new UnicodeBlock("YI_SYLLABLES", new String[] {"Yi Syllables", "YiSyllables"});
+            new UnicodeBlock("YI_SYLLABLES",
+                             "YI SYLLABLES",
+                             "YISYLLABLES");
 
         /**
          * Constant for the "Yi Radicals" Unicode character block.
          * @since 1.4
          */
         public static final UnicodeBlock YI_RADICALS =
-            new UnicodeBlock("YI_RADICALS", new String[] {"Yi Radicals", "YiRadicals"});
+            new UnicodeBlock("YI_RADICALS",
+                             "YI RADICALS",
+                             "YIRADICALS");
 
 
         /**
@@ -1350,10 +1394,10 @@
          */
         public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY =
             new UnicodeBlock("CYRILLIC_SUPPLEMENTARY",
-                             new String[] {"Cyrillic Supplementary",
-                                           "CyrillicSupplementary",
-                                           "Cyrillic Supplement",
-                                           "CyrillicSupplement"});
+                             "CYRILLIC SUPPLEMENTARY",
+                             "CYRILLICSUPPLEMENTARY",
+                             "CYRILLIC SUPPLEMENT",
+                             "CYRILLICSUPPLEMENT");
 
         /**
          * Constant for the "Tagalog" Unicode character block.
@@ -1395,21 +1439,27 @@
          * @since 1.5
          */
         public static final UnicodeBlock TAI_LE =
-            new UnicodeBlock("TAI_LE", new String[] {"Tai Le", "TaiLe"});
+            new UnicodeBlock("TAI_LE",
+                             "TAI LE",
+                             "TAILE");
 
         /**
          * Constant for the "Khmer Symbols" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock KHMER_SYMBOLS =
-            new UnicodeBlock("KHMER_SYMBOLS", new String[] {"Khmer Symbols", "KhmerSymbols"});
+            new UnicodeBlock("KHMER_SYMBOLS",
+                             "KHMER SYMBOLS",
+                             "KHMERSYMBOLS");
 
         /**
          * Constant for the "Phonetic Extensions" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock PHONETIC_EXTENSIONS =
-            new UnicodeBlock("PHONETIC_EXTENSIONS", new String[] {"Phonetic Extensions", "PhoneticExtensions"});
+            new UnicodeBlock("PHONETIC_EXTENSIONS",
+                             "PHONETIC EXTENSIONS",
+                             "PHONETICEXTENSIONS");
 
         /**
          * Constant for the "Miscellaneous Mathematical Symbols-A" Unicode character block.
@@ -1417,33 +1467,35 @@
          */
         public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A =
             new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A",
-                             new String[]{"Miscellaneous Mathematical Symbols-A",
-                                          "MiscellaneousMathematicalSymbols-A"});
+                             "MISCELLANEOUS MATHEMATICAL SYMBOLS-A",
+                             "MISCELLANEOUSMATHEMATICALSYMBOLS-A");
 
         /**
          * Constant for the "Supplemental Arrows-A" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A =
-            new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", new String[] {"Supplemental Arrows-A",
-                                                                    "SupplementalArrows-A"});
+            new UnicodeBlock("SUPPLEMENTAL_ARROWS_A",
+                             "SUPPLEMENTAL ARROWS-A",
+                             "SUPPLEMENTALARROWS-A");
 
         /**
          * Constant for the "Supplemental Arrows-B" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B =
-            new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", new String[] {"Supplemental Arrows-B",
-                                                                    "SupplementalArrows-B"});
+            new UnicodeBlock("SUPPLEMENTAL_ARROWS_B",
+                             "SUPPLEMENTAL ARROWS-B",
+                             "SUPPLEMENTALARROWS-B");
 
         /**
          * Constant for the "Miscellaneous Mathematical Symbols-B" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B
-                = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B",
-                                   new String[] {"Miscellaneous Mathematical Symbols-B",
-                                                 "MiscellaneousMathematicalSymbols-B"});
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B =
+            new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B",
+                             "MISCELLANEOUS MATHEMATICAL SYMBOLS-B",
+                             "MISCELLANEOUSMATHEMATICALSYMBOLS-B");
 
         /**
          * Constant for the "Supplemental Mathematical Operators" Unicode character block.
@@ -1451,127 +1503,151 @@
          */
         public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS =
             new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS",
-                             new String[]{"Supplemental Mathematical Operators",
-                                          "SupplementalMathematicalOperators"} );
+                             "SUPPLEMENTAL MATHEMATICAL OPERATORS",
+                             "SUPPLEMENTALMATHEMATICALOPERATORS");
 
         /**
          * Constant for the "Miscellaneous Symbols and Arrows" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS =
-            new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", new String[] {"Miscellaneous Symbols and Arrows",
-                                                                               "MiscellaneousSymbolsandArrows"});
+            new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS",
+                             "MISCELLANEOUS SYMBOLS AND ARROWS",
+                             "MISCELLANEOUSSYMBOLSANDARROWS");
 
         /**
          * Constant for the "Katakana Phonetic Extensions" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS =
-            new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", new String[] {"Katakana Phonetic Extensions",
-                                                                           "KatakanaPhoneticExtensions"});
+            new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS",
+                             "KATAKANA PHONETIC EXTENSIONS",
+                             "KATAKANAPHONETICEXTENSIONS");
 
         /**
          * Constant for the "Yijing Hexagram Symbols" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS =
-            new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", new String[] {"Yijing Hexagram Symbols",
-                                                                      "YijingHexagramSymbols"});
+            new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS",
+                             "YIJING HEXAGRAM SYMBOLS",
+                             "YIJINGHEXAGRAMSYMBOLS");
 
         /**
          * Constant for the "Variation Selectors" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock VARIATION_SELECTORS =
-            new UnicodeBlock("VARIATION_SELECTORS", new String[] {"Variation Selectors", "VariationSelectors"});
+            new UnicodeBlock("VARIATION_SELECTORS",
+                             "VARIATION SELECTORS",
+                             "VARIATIONSELECTORS");
 
         /**
          * Constant for the "Linear B Syllabary" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock LINEAR_B_SYLLABARY =
-            new UnicodeBlock("LINEAR_B_SYLLABARY", new String[] {"Linear B Syllabary", "LinearBSyllabary"});
+            new UnicodeBlock("LINEAR_B_SYLLABARY",
+                             "LINEAR B SYLLABARY",
+                             "LINEARBSYLLABARY");
 
         /**
          * Constant for the "Linear B Ideograms" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock LINEAR_B_IDEOGRAMS =
-            new UnicodeBlock("LINEAR_B_IDEOGRAMS", new String[] {"Linear B Ideograms", "LinearBIdeograms"});
+            new UnicodeBlock("LINEAR_B_IDEOGRAMS",
+                             "LINEAR B IDEOGRAMS",
+                             "LINEARBIDEOGRAMS");
 
         /**
          * Constant for the "Aegean Numbers" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock AEGEAN_NUMBERS =
-            new UnicodeBlock("AEGEAN_NUMBERS", new String[] {"Aegean Numbers", "AegeanNumbers"});
+            new UnicodeBlock("AEGEAN_NUMBERS",
+                             "AEGEAN NUMBERS",
+                             "AEGEANNUMBERS");
 
         /**
          * Constant for the "Old Italic" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock OLD_ITALIC =
-            new UnicodeBlock("OLD_ITALIC", new String[] {"Old Italic", "OldItalic"});
+            new UnicodeBlock("OLD_ITALIC",
+                             "OLD ITALIC",
+                             "OLDITALIC");
 
         /**
          * Constant for the "Gothic" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC");
+        public static final UnicodeBlock GOTHIC =
+            new UnicodeBlock("GOTHIC");
 
         /**
          * Constant for the "Ugaritic" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC");
+        public static final UnicodeBlock UGARITIC =
+            new UnicodeBlock("UGARITIC");
 
         /**
          * Constant for the "Deseret" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET");
+        public static final UnicodeBlock DESERET =
+            new UnicodeBlock("DESERET");
 
         /**
          * Constant for the "Shavian" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN");
+        public static final UnicodeBlock SHAVIAN =
+            new UnicodeBlock("SHAVIAN");
 
         /**
          * Constant for the "Osmanya" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA");
+        public static final UnicodeBlock OSMANYA =
+            new UnicodeBlock("OSMANYA");
 
         /**
          * Constant for the "Cypriot Syllabary" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock CYPRIOT_SYLLABARY =
-            new UnicodeBlock("CYPRIOT_SYLLABARY", new String[] {"Cypriot Syllabary", "CypriotSyllabary"});
+            new UnicodeBlock("CYPRIOT_SYLLABARY",
+                             "CYPRIOT SYLLABARY",
+                             "CYPRIOTSYLLABARY");
 
         /**
          * Constant for the "Byzantine Musical Symbols" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS =
-            new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", new String[] {"Byzantine Musical Symbols",
-                                                                        "ByzantineMusicalSymbols"});
+            new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS",
+                             "BYZANTINE MUSICAL SYMBOLS",
+                             "BYZANTINEMUSICALSYMBOLS");
 
         /**
          * Constant for the "Musical Symbols" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock MUSICAL_SYMBOLS =
-            new UnicodeBlock("MUSICAL_SYMBOLS", new String[] {"Musical Symbols", "MusicalSymbols"});
+            new UnicodeBlock("MUSICAL_SYMBOLS",
+                             "MUSICAL SYMBOLS",
+                             "MUSICALSYMBOLS");
 
         /**
          * Constant for the "Tai Xuan Jing Symbols" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS =
-            new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", new String[] {"Tai Xuan Jing Symbols",
-                                                                     "TaiXuanJingSymbols"});
+            new UnicodeBlock("TAI_XUAN_JING_SYMBOLS",
+                             "TAI XUAN JING SYMBOLS",
+                             "TAIXUANJINGSYMBOLS");
 
         /**
          * Constant for the "Mathematical Alphanumeric Symbols" Unicode character block.
@@ -1579,7 +1655,8 @@
          */
         public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS =
             new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS",
-                             new String[] {"Mathematical Alphanumeric Symbols", "MathematicalAlphanumericSymbols"});
+                             "MATHEMATICAL ALPHANUMERIC SYMBOLS",
+                             "MATHEMATICALALPHANUMERICSYMBOLS");
 
         /**
          * Constant for the "CJK Unified Ideographs Extension B" Unicode character block.
@@ -1587,7 +1664,8 @@
          */
         public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B =
             new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B",
-                             new String[] {"CJK Unified Ideographs Extension B", "CJKUnifiedIdeographsExtensionB"});
+                             "CJK UNIFIED IDEOGRAPHS EXTENSION B",
+                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONB");
 
         /**
          * Constant for the "CJK Compatibility Ideographs Supplement" Unicode character block.
@@ -1595,22 +1673,24 @@
          */
         public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT =
             new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT",
-                             new String[]{"CJK Compatibility Ideographs Supplement",
-                                          "CJKCompatibilityIdeographsSupplement"});
+                             "CJK COMPATIBILITY IDEOGRAPHS SUPPLEMENT",
+                             "CJKCOMPATIBILITYIDEOGRAPHSSUPPLEMENT");
 
         /**
          * Constant for the "Tags" Unicode character block.
          * @since 1.5
          */
-        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS");
+        public static final UnicodeBlock TAGS =
+            new UnicodeBlock("TAGS");
 
         /**
          * Constant for the "Variation Selectors Supplement" Unicode character block.
          * @since 1.5
          */
         public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT =
-            new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", new String[] {"Variation Selectors Supplement",
-                                                                             "VariationSelectorsSupplement"});
+            new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT",
+                             "VARIATION SELECTORS SUPPLEMENT",
+                             "VARIATIONSELECTORSSUPPLEMENT");
 
         /**
          * Constant for the "Supplementary Private Use Area-A" Unicode character block.
@@ -1618,8 +1698,8 @@
          */
         public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A =
             new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A",
-                             new String[] {"Supplementary Private Use Area-A",
-                                           "SupplementaryPrivateUseArea-A"});
+                             "SUPPLEMENTARY PRIVATE USE AREA-A",
+                             "SUPPLEMENTARYPRIVATEUSEAREA-A");
 
         /**
          * Constant for the "Supplementary Private Use Area-B" Unicode character block.
@@ -1627,39 +1707,44 @@
          */
         public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B =
             new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B",
-                             new String[] {"Supplementary Private Use Area-B",
-                                           "SupplementaryPrivateUseArea-B"});
+                             "SUPPLEMENTARY PRIVATE USE AREA-B",
+                             "SUPPLEMENTARYPRIVATEUSEAREA-B");
 
         /**
          * Constant for the "High Surrogates" Unicode character block.
          * This block represents codepoint values in the high surrogate
-         * range: 0xD800 through 0xDB7F
+         * range: U+D800 through U+DB7F
          *
          * @since 1.5
          */
         public static final UnicodeBlock HIGH_SURROGATES =
-            new UnicodeBlock("HIGH_SURROGATES", new String[] {"High Surrogates", "HighSurrogates"});
+            new UnicodeBlock("HIGH_SURROGATES",
+                             "HIGH SURROGATES",
+                             "HIGHSURROGATES");
 
         /**
          * Constant for the "High Private Use Surrogates" Unicode character block.
-         * This block represents codepoint values in the high surrogate
-         * range: 0xDB80 through 0xDBFF
+         * This block represents codepoint values in the private use high surrogate
+         * range: U+DB80 through U+DBFF
          *
          * @since 1.5
          */
         public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES =
-            new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", new String[] { "High Private Use Surrogates",
-                                                                           "HighPrivateUseSurrogates"});
+            new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES",
+                             "HIGH PRIVATE USE SURROGATES",
+                             "HIGHPRIVATEUSESURROGATES");
 
         /**
          * Constant for the "Low Surrogates" Unicode character block.
-         * This block represents codepoint values in the high surrogate
-         * range: 0xDC00 through 0xDFFF
+         * This block represents codepoint values in the low surrogate
+         * range: U+DC00 through U+DFFF
          *
          * @since 1.5
          */
         public static final UnicodeBlock LOW_SURROGATES =
-            new UnicodeBlock("LOW_SURROGATES", new String[] {"Low Surrogates", "LowSurrogates"});
+            new UnicodeBlock("LOW_SURROGATES",
+                             "LOW SURROGATES",
+                             "LOWSURROGATES");
 
         /**
          * Constant for the "Arabic Supplement" Unicode character block.
@@ -1667,14 +1752,15 @@
          */
         public static final UnicodeBlock ARABIC_SUPPLEMENT =
             new UnicodeBlock("ARABIC_SUPPLEMENT",
-                             new String[] { "Arabic Supplement",
-                                            "ArabicSupplement"});
+                             "ARABIC SUPPLEMENT",
+                             "ARABICSUPPLEMENT");
 
         /**
          * Constant for the "NKo" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock NKO = new UnicodeBlock("NKO");
+        public static final UnicodeBlock NKO =
+            new UnicodeBlock("NKO");
 
         /**
          * Constant for the "Ethiopic Supplement" Unicode character block.
@@ -1682,8 +1768,8 @@
          */
         public static final UnicodeBlock ETHIOPIC_SUPPLEMENT =
             new UnicodeBlock("ETHIOPIC_SUPPLEMENT",
-                             new String[] { "Ethiopic Supplement",
-                                            "EthiopicSupplement"});
+                             "ETHIOPIC SUPPLEMENT",
+                             "ETHIOPICSUPPLEMENT");
 
         /**
          * Constant for the "New Tai Lue" Unicode character block.
@@ -1691,8 +1777,8 @@
          */
         public static final UnicodeBlock NEW_TAI_LUE =
             new UnicodeBlock("NEW_TAI_LUE",
-                             new String[] { "New Tai Lue",
-                                            "NewTaiLue"});
+                             "NEW TAI LUE",
+                             "NEWTAILUE");
 
         /**
          * Constant for the "Buginese" Unicode character block.
@@ -1719,7 +1805,8 @@
          * Constant for the "Lepcha" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock LEPCHA = new UnicodeBlock("LEPCHA");
+        public static final UnicodeBlock LEPCHA =
+            new UnicodeBlock("LEPCHA");
 
         /**
          * Constant for the "Ol Chiki" Unicode character block.
@@ -1727,8 +1814,8 @@
          */
         public static final UnicodeBlock OL_CHIKI =
             new UnicodeBlock("OL_CHIKI",
-                             new String[] { "Ol Chiki",
-                                            "OlChiki"});
+                             "OL CHIKI",
+                             "OLCHIKI");
 
         /**
          * Constant for the "Phonetic Extensions Supplement" Unicode character
@@ -1737,8 +1824,8 @@
          */
         public static final UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT =
             new UnicodeBlock("PHONETIC_EXTENSIONS_SUPPLEMENT",
-                             new String[] { "Phonetic Extensions Supplement",
-                                            "PhoneticExtensionsSupplement"});
+                             "PHONETIC EXTENSIONS SUPPLEMENT",
+                             "PHONETICEXTENSIONSSUPPLEMENT");
 
         /**
          * Constant for the "Combining Diacritical Marks Supplement" Unicode
@@ -1747,8 +1834,8 @@
          */
         public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT =
             new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_SUPPLEMENT",
-                             new String[] { "Combining Diacritical Marks Supplement",
-                                            "CombiningDiacriticalMarksSupplement"});
+                             "COMBINING DIACRITICAL MARKS SUPPLEMENT",
+                             "COMBININGDIACRITICALMARKSSUPPLEMENT");
 
         /**
          * Constant for the "Glagolitic" Unicode character block.
@@ -1763,14 +1850,15 @@
          */
         public static final UnicodeBlock LATIN_EXTENDED_C =
             new UnicodeBlock("LATIN_EXTENDED_C",
-                             new String[] { "Latin Extended-C",
-                                            "LatinExtended-C"});
+                             "LATIN EXTENDED-C",
+                             "LATINEXTENDED-C");
 
         /**
          * Constant for the "Coptic" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock COPTIC = new UnicodeBlock("COPTIC");
+        public static final UnicodeBlock COPTIC =
+            new UnicodeBlock("COPTIC");
 
         /**
          * Constant for the "Georgian Supplement" Unicode character block.
@@ -1778,8 +1866,8 @@
          */
         public static final UnicodeBlock GEORGIAN_SUPPLEMENT =
             new UnicodeBlock("GEORGIAN_SUPPLEMENT",
-                             new String[] { "Georgian Supplement",
-                                            "GeorgianSupplement"});
+                             "GEORGIAN SUPPLEMENT",
+                             "GEORGIANSUPPLEMENT");
 
         /**
          * Constant for the "Tifinagh" Unicode character block.
@@ -1794,8 +1882,8 @@
          */
         public static final UnicodeBlock ETHIOPIC_EXTENDED =
             new UnicodeBlock("ETHIOPIC_EXTENDED",
-                             new String[] { "Ethiopic Extended",
-                                            "EthiopicExtended"});
+                             "ETHIOPIC EXTENDED",
+                             "ETHIOPICEXTENDED");
 
         /**
          * Constant for the "Cyrillic Extended-A" Unicode character block.
@@ -1803,8 +1891,8 @@
          */
         public static final UnicodeBlock CYRILLIC_EXTENDED_A =
             new UnicodeBlock("CYRILLIC_EXTENDED_A",
-                             new String[] { "Cyrillic Extended-A",
-                                            "CyrillicExtended-A"});
+                             "CYRILLIC EXTENDED-A",
+                             "CYRILLICEXTENDED-A");
 
         /**
          * Constant for the "Supplemental Punctuation" Unicode character block.
@@ -1812,8 +1900,8 @@
          */
         public static final UnicodeBlock SUPPLEMENTAL_PUNCTUATION =
             new UnicodeBlock("SUPPLEMENTAL_PUNCTUATION",
-                             new String[] { "Supplemental Punctuation",
-                                            "SupplementalPunctuation"});
+                             "SUPPLEMENTAL PUNCTUATION",
+                             "SUPPLEMENTALPUNCTUATION");
 
         /**
          * Constant for the "CJK Strokes" Unicode character block.
@@ -1821,14 +1909,15 @@
          */
         public static final UnicodeBlock CJK_STROKES =
             new UnicodeBlock("CJK_STROKES",
-                             new String[] { "CJK Strokes",
-                                            "CJKStrokes"});
+                             "CJK STROKES",
+                             "CJKSTROKES");
 
         /**
          * Constant for the "Vai" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock VAI = new UnicodeBlock("VAI");
+        public static final UnicodeBlock VAI =
+            new UnicodeBlock("VAI");
 
         /**
          * Constant for the "Cyrillic Extended-B" Unicode character block.
@@ -1836,8 +1925,8 @@
          */
         public static final UnicodeBlock CYRILLIC_EXTENDED_B =
             new UnicodeBlock("CYRILLIC_EXTENDED_B",
-                             new String[] { "Cyrillic Extended-B",
-                                            "CyrillicExtended-B"});
+                             "CYRILLIC EXTENDED-B",
+                             "CYRILLICEXTENDED-B");
 
         /**
          * Constant for the "Modifier Tone Letters" Unicode character block.
@@ -1845,8 +1934,8 @@
          */
         public static final UnicodeBlock MODIFIER_TONE_LETTERS =
             new UnicodeBlock("MODIFIER_TONE_LETTERS",
-                             new String[] { "Modifier Tone Letters",
-                                            "ModifierToneLetters"});
+                             "MODIFIER TONE LETTERS",
+                             "MODIFIERTONELETTERS");
 
         /**
          * Constant for the "Latin Extended-D" Unicode character block.
@@ -1854,8 +1943,8 @@
          */
         public static final UnicodeBlock LATIN_EXTENDED_D =
             new UnicodeBlock("LATIN_EXTENDED_D",
-                             new String[] { "Latin Extended-D",
-                                            "LatinExtended-D"});
+                             "LATIN EXTENDED-D",
+                             "LATINEXTENDED-D");
 
         /**
          * Constant for the "Syloti Nagri" Unicode character block.
@@ -1863,15 +1952,16 @@
          */
         public static final UnicodeBlock SYLOTI_NAGRI =
             new UnicodeBlock("SYLOTI_NAGRI",
-                             new String[] { "Syloti Nagri",
-                                            "SylotiNagri"});
+                             "SYLOTI NAGRI",
+                             "SYLOTINAGRI");
 
         /**
          * Constant for the "Phags-pa" Unicode character block.
          * @since 1.7
          */
         public static final UnicodeBlock PHAGS_PA =
-            new UnicodeBlock("PHAGS_PA", new String[] { "Phags-pa"});
+            new UnicodeBlock("PHAGS_PA",
+                             "PHAGS-PA");
 
         /**
          * Constant for the "Saurashtra" Unicode character block.
@@ -1886,20 +1976,22 @@
          */
         public static final UnicodeBlock KAYAH_LI =
             new UnicodeBlock("KAYAH_LI",
-                             new String[] { "Kayah Li",
-                                            "KayahLi"});
+                             "KAYAH LI",
+                             "KAYAHLI");
 
         /**
          * Constant for the "Rejang" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock REJANG = new UnicodeBlock("REJANG");
+        public static final UnicodeBlock REJANG =
+            new UnicodeBlock("REJANG");
 
         /**
          * Constant for the "Cham" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock CHAM = new UnicodeBlock("CHAM");
+        public static final UnicodeBlock CHAM =
+            new UnicodeBlock("CHAM");
 
         /**
          * Constant for the "Vertical Forms" Unicode character block.
@@ -1907,8 +1999,8 @@
          */
         public static final UnicodeBlock VERTICAL_FORMS =
             new UnicodeBlock("VERTICAL_FORMS",
-                             new String[] { "Vertical Forms",
-                                            "VerticalForms"});
+                             "VERTICAL FORMS",
+                             "VERTICALFORMS");
 
         /**
          * Constant for the "Ancient Greek Numbers" Unicode character block.
@@ -1916,8 +2008,8 @@
          */
         public static final UnicodeBlock ANCIENT_GREEK_NUMBERS =
             new UnicodeBlock("ANCIENT_GREEK_NUMBERS",
-                             new String[] { "Ancient Greek Numbers",
-                                            "AncientGreekNumbers"});
+                             "ANCIENT GREEK NUMBERS",
+                             "ANCIENTGREEKNUMBERS");
 
         /**
          * Constant for the "Ancient Symbols" Unicode character block.
@@ -1925,8 +2017,8 @@
          */
         public static final UnicodeBlock ANCIENT_SYMBOLS =
             new UnicodeBlock("ANCIENT_SYMBOLS",
-                             new String[] { "Ancient Symbols",
-                                            "AncientSymbols"});
+                             "ANCIENT SYMBOLS",
+                             "ANCIENTSYMBOLS");
 
         /**
          * Constant for the "Phaistos Disc" Unicode character block.
@@ -1934,20 +2026,22 @@
          */
         public static final UnicodeBlock PHAISTOS_DISC =
             new UnicodeBlock("PHAISTOS_DISC",
-                             new String[] { "Phaistos Disc",
-                                            "PhaistosDisc"});
+                             "PHAISTOS DISC",
+                             "PHAISTOSDISC");
 
         /**
          * Constant for the "Lycian" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock LYCIAN = new UnicodeBlock("LYCIAN");
+        public static final UnicodeBlock LYCIAN =
+            new UnicodeBlock("LYCIAN");
 
         /**
          * Constant for the "Carian" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock CARIAN = new UnicodeBlock("CARIAN");
+        public static final UnicodeBlock CARIAN =
+            new UnicodeBlock("CARIAN");
 
         /**
          * Constant for the "Old Persian" Unicode character block.
@@ -1955,8 +2049,8 @@
          */
         public static final UnicodeBlock OLD_PERSIAN =
             new UnicodeBlock("OLD_PERSIAN",
-                             new String[] { "Old Persian",
-                                            "OldPersian"});
+                             "OLD PERSIAN",
+                             "OLDPERSIAN");
 
         /**
          * Constant for the "Phoenician" Unicode character block.
@@ -1969,7 +2063,8 @@
          * Constant for the "Lydian" Unicode character block.
          * @since 1.7
          */
-        public static final UnicodeBlock LYDIAN = new UnicodeBlock("LYDIAN");
+        public static final UnicodeBlock LYDIAN =
+            new UnicodeBlock("LYDIAN");
 
         /**
          * Constant for the "Kharoshthi" Unicode character block.
@@ -1992,8 +2087,8 @@
          */
         public static final UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION =
             new UnicodeBlock("CUNEIFORM_NUMBERS_AND_PUNCTUATION",
-                             new String[] { "Cuneiform Numbers and Punctuation",
-                                            "CuneiformNumbersandPunctuation"});
+                             "CUNEIFORM NUMBERS AND PUNCTUATION",
+                             "CUNEIFORMNUMBERSANDPUNCTUATION");
 
         /**
          * Constant for the "Ancient Greek Musical Notation" Unicode character
@@ -2002,8 +2097,8 @@
          */
         public static final UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION =
             new UnicodeBlock("ANCIENT_GREEK_MUSICAL_NOTATION",
-                             new String[] { "Ancient Greek Musical Notation",
-                                            "AncientGreekMusicalNotation"});
+                             "ANCIENT GREEK MUSICAL NOTATION",
+                             "ANCIENTGREEKMUSICALNOTATION");
 
         /**
          * Constant for the "Counting Rod Numerals" Unicode character block.
@@ -2011,8 +2106,8 @@
          */
         public static final UnicodeBlock COUNTING_ROD_NUMERALS =
             new UnicodeBlock("COUNTING_ROD_NUMERALS",
-                             new String[] { "Counting Rod Numerals",
-                                            "CountingRodNumerals"});
+                             "COUNTING ROD NUMERALS",
+                             "COUNTINGRODNUMERALS");
 
         /**
          * Constant for the "Mahjong Tiles" Unicode character block.
@@ -2020,8 +2115,8 @@
          */
         public static final UnicodeBlock MAHJONG_TILES =
             new UnicodeBlock("MAHJONG_TILES",
-                             new String[] { "Mahjong Tiles",
-                                            "MahjongTiles"});
+                             "MAHJONG TILES",
+                             "MAHJONGTILES");
 
         /**
          * Constant for the "Domino Tiles" Unicode character block.
@@ -2029,8 +2124,8 @@
          */
         public static final UnicodeBlock DOMINO_TILES =
             new UnicodeBlock("DOMINO_TILES",
-                             new String[] { "Domino Tiles",
-                                            "DominoTiles"});
+                             "DOMINO TILES",
+                             "DOMINOTILES");
 
         private static final int blockStarts[] = {
             0x0000,   // 0000..007F; Basic Latin
@@ -2046,7 +2141,7 @@
             0x0530,   // 0530..058F; Armenian
             0x0590,   // 0590..05FF; Hebrew
             0x0600,   // 0600..06FF; Arabic
-            0x0700,   // 0700..074F; Syria
+            0x0700,   // 0700..074F; Syriac
             0x0750,   // 0750..077F; Arabic Supplement
             0x0780,   // 0780..07BF; Thaana
             0x07C0,   // 07C0..07FF; NKo
@@ -2446,11 +2541,10 @@
          * given character, or <code>null</code> if the character is not a
          * member of a defined block.
          *
-                 * <p><b>Note:</b> This method cannot handle <a
-                 * href="Character.html#supplementary"> supplementary
-                 * characters</a>. To support all Unicode characters,
-                 * including supplementary characters, use the {@link
-                 * #of(int)} method.
+         * <p><b>Note:</b> This method cannot handle
+         * <a href="Character.html#supplementary"> supplementary
+         * characters</a>.  To support all Unicode characters, including
+         * supplementary characters, use the {@link #of(int)} method.
          *
          * @param   c  The character in question
          * @return  The <code>UnicodeBlock</code> instance representing the
@@ -2462,22 +2556,21 @@
             return of((int)c);
         }
 
-
         /**
          * Returns the object representing the Unicode block
          * containing the given character (Unicode code point), or
          * <code>null</code> if the character is not a member of a
          * defined block.
          *
-                 * @param   codePoint the character (Unicode code point) in question.
+         * @param   codePoint the character (Unicode code point) in question.
          * @return  The <code>UnicodeBlock</code> instance representing the
          *          Unicode block of which this character is a member, or
          *          <code>null</code> if the character is not a member of any
          *          Unicode block
-                 * @exception IllegalArgumentException if the specified
-                 * <code>codePoint</code> is an invalid Unicode code point.
-                 * @see Character#isValidCodePoint(int)
-                 * @since   1.5
+         * @exception IllegalArgumentException if the specified
+         * <code>codePoint</code> is an invalid Unicode code point.
+         * @see Character#isValidCodePoint(int)
+         * @since   1.5
          */
         public static UnicodeBlock of(int codePoint) {
             if (!isValidCodePoint(codePoint)) {
@@ -2519,7 +2612,7 @@
          * <li>The text representation of each constant UnicodeBlock identifier.
          * For example, this method will return the {@link #BASIC_LATIN} block if
          * provided with the "BASIC_LATIN" name. This form replaces all spaces and
-         *  hyphens in the canonical name with underscores.
+         * hyphens in the canonical name with underscores.
          * </ol>
          * Finally, character case is ignored for all of the valid block name forms.
          * For example, "BASIC_LATIN" and "basic_latin" are both valid block names.
@@ -2538,7 +2631,7 @@
          * @since 1.5
          */
         public static final UnicodeBlock forName(String blockName) {
-            UnicodeBlock block = (UnicodeBlock)map.get(blockName.toUpperCase(Locale.US));
+            UnicodeBlock block = map.get(blockName.toUpperCase(Locale.US));
             if (block == null) {
                 throw new IllegalArgumentException();
             }
@@ -3627,7 +3720,7 @@
 
         private static HashMap<String, Character.UnicodeScript> aliases;
         static {
-            aliases = new HashMap<String, UnicodeScript>();
+            aliases = new HashMap<String, UnicodeScript>(128);
             aliases.put("ARAB", ARABIC);
             aliases.put("ARMI", IMPERIAL_ARAMAIC);
             aliases.put("ARMN", ARMENIAN);
@@ -3809,7 +3902,7 @@
         static final Character cache[] = new Character[127 + 1];
 
         static {
-            for(int i = 0; i < cache.length; i++)
+            for (int i = 0; i < cache.length; i++)
                 cache[i] = new Character((char)i);
         }
     }
@@ -3832,7 +3925,7 @@
      * @since  1.5
      */
     public static Character valueOf(char c) {
-        if(c <= 127) { // must cache
+        if (c <= 127) { // must cache
             return CharacterCache.cache[(int)c];
         }
         return new Character(c);
@@ -3914,7 +4007,29 @@
      * @since  1.5
      */
     public static boolean isValidCodePoint(int codePoint) {
-        return codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT;
+        // Optimized form of:
+        //     codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
+        int plane = codePoint >>> 16;
+        return plane < ((MAX_CODE_POINT + 1) >>> 16);
+    }
+
+    /**
+     * Determines whether the specified character (Unicode code point)
+     * is in the <a href="#BMP">Basic Multilingual Plane (BMP)</a>.
+     * Such code points can be represented using a single {@code char}.
+     *
+     * @param  codePoint the character (Unicode code point) to be tested
+     * @return {@code true} if the specified code point is between
+     *         {@link #MIN_VALUE} and {@link #MAX_VALUE} inclusive;
+     *         {@code false} otherwise.
+     * @since  1.7
+     */
+    public static boolean isBmpCodePoint(int codePoint) {
+        return codePoint >>> 16 == 0;
+        // Optimized form of:
+        //     codePoint >= MIN_VALUE && codePoint <= MAX_VALUE
+        // We consistently use logical shift (>>>) to facilitate
+        // additional runtime optimizations.
     }
 
     /**
@@ -3930,7 +4045,7 @@
      */
     public static boolean isSupplementaryCodePoint(int codePoint) {
         return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT
-            && codePoint <= MAX_CODE_POINT;
+            && codePoint <  MAX_CODE_POINT + 1;
     }
 
     /**
@@ -3949,12 +4064,13 @@
      *         {@link #MIN_HIGH_SURROGATE} and
      *         {@link #MAX_HIGH_SURROGATE} inclusive;
      *         {@code false} otherwise.
-     * @see    #isLowSurrogate(char)
+     * @see    Character#isLowSurrogate(char)
      * @see    Character.UnicodeBlock#of(int)
      * @since  1.5
      */
     public static boolean isHighSurrogate(char ch) {
-        return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE;
+        // Help VM constant-fold; MAX_HIGH_SURROGATE + 1 == MIN_LOW_SURROGATE
+        return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1);
     }
 
     /**
@@ -3973,11 +4089,11 @@
      *         {@link #MIN_LOW_SURROGATE} and
      *         {@link #MAX_LOW_SURROGATE} inclusive;
      *         {@code false} otherwise.
-     * @see    #isHighSurrogate(char)
+     * @see    Character#isHighSurrogate(char)
      * @since  1.5
      */
     public static boolean isLowSurrogate(char ch) {
-        return ch >= MIN_LOW_SURROGATE && ch <= MAX_LOW_SURROGATE;
+        return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1);
     }
 
     /**
@@ -4001,7 +4117,7 @@
      * @since  1.7
      */
     public static boolean isSurrogate(char ch) {
-        return ch >= MIN_SURROGATE && ch <= MAX_SURROGATE;
+        return ch >= MIN_SURROGATE && ch < (MAX_SURROGATE + 1);
     }
 
     /**
@@ -4039,11 +4155,11 @@
      *
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  2 if the character is a valid supplementary character; 1 otherwise.
-     * @see     #isSupplementaryCodePoint(int)
+     * @see     Character#isSupplementaryCodePoint(int)
      * @since   1.5
      */
     public static int charCount(int codePoint) {
-        return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT? 2 : 1;
+        return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1;
     }
 
     /**
@@ -4160,6 +4276,7 @@
         return codePointAtImpl(a, index, limit);
     }
 
+    // throws ArrayIndexOutofBoundsException if index out of bounds
     static int codePointAtImpl(char[] a, int index, int limit) {
         char c1 = a[index++];
         if (isHighSurrogate(c1)) {
@@ -4266,6 +4383,7 @@
         return codePointBeforeImpl(a, index, start);
     }
 
+    // throws ArrayIndexOutofBoundsException if index-1 out of bounds
     static int codePointBeforeImpl(char[] a, int index, int start) {
         char c2 = a[--index];
         if (isLowSurrogate(c2)) {
@@ -4280,6 +4398,63 @@
     }
 
     /**
+     * Returns the leading surrogate (a
+     * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
+     * high surrogate code unit</a>) of the
+     * <a href="http://www.unicode.org/glossary/#surrogate_pair">
+     * surrogate pair</a>
+     * representing the specified supplementary character (Unicode
+     * code point) in the UTF-16 encoding.  If the specified character
+     * is not a
+     * <a href="Character.html#supplementary">supplementary character</a>,
+     * an unspecified {@code char} is returned.
+     *
+     * <p>If
+     * {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)}
+     * is {@code true}, then
+     * {@link #isHighSurrogate isHighSurrogate}{@code (highSurrogate(x))} and
+     * {@link #toCodePoint toCodePoint}{@code (highSurrogate(x), }{@link #lowSurrogate lowSurrogate}{@code (x)) == x}
+     * are also always {@code true}.
+     *
+     * @param   codePoint a supplementary character (Unicode code point)
+     * @return  the leading surrogate code unit used to represent the
+     *          character in the UTF-16 encoding
+     * @since   1.7
+     */
+    public static char highSurrogate(int codePoint) {
+        return (char) ((codePoint >>> 10)
+            + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
+    }
+
+    /**
+     * Returns the trailing surrogate (a
+     * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
+     * low surrogate code unit</a>) of the
+     * <a href="http://www.unicode.org/glossary/#surrogate_pair">
+     * surrogate pair</a>
+     * representing the specified supplementary character (Unicode
+     * code point) in the UTF-16 encoding.  If the specified character
+     * is not a
+     * <a href="Character.html#supplementary">supplementary character</a>,
+     * an unspecified {@code char} is returned.
+     *
+     * <p>If
+     * {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)}
+     * is {@code true}, then
+     * {@link #isLowSurrogate isLowSurrogate}{@code (lowSurrogate(x))} and
+     * {@link #toCodePoint toCodePoint}{@code (}{@link #highSurrogate highSurrogate}{@code (x), lowSurrogate(x)) == x}
+     * are also always {@code true}.
+     *
+     * @param   codePoint a supplementary character (Unicode code point)
+     * @return  the trailing surrogate code unit used to represent the
+     *          character in the UTF-16 encoding
+     * @since   1.7
+     */
+    public static char lowSurrogate(int codePoint) {
+        return (char) ((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
+    }
+
+    /**
      * Converts the specified character (Unicode code point) to its
      * UTF-16 representation. If the specified code point is a BMP
      * (Basic Multilingual Plane or Plane 0) value, the same value is
@@ -4311,15 +4486,15 @@
      * @since  1.5
      */
     public static int toChars(int codePoint, char[] dst, int dstIndex) {
-        if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
+        if (isBmpCodePoint(codePoint)) {
+            dst[dstIndex] = (char) codePoint;
+            return 1;
+        } else if (isValidCodePoint(codePoint)) {
+            toSurrogates(codePoint, dst, dstIndex);
+            return 2;
+        } else {
             throw new IllegalArgumentException();
         }
-        if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
-            dst[dstIndex] = (char) codePoint;
-            return 1;
-        }
-        toSurrogates(codePoint, dst, dstIndex);
-        return 2;
     }
 
     /**
@@ -4339,22 +4514,21 @@
      * @since  1.5
      */
     public static char[] toChars(int codePoint) {
-        if (codePoint < 0 || codePoint > MAX_CODE_POINT) {
+        if (isBmpCodePoint(codePoint)) {
+            return new char[] { (char) codePoint };
+        } else if (isValidCodePoint(codePoint)) {
+            char[] result = new char[2];
+            toSurrogates(codePoint, result, 0);
+            return result;
+        } else {
             throw new IllegalArgumentException();
         }
-        if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
-                return new char[] { (char) codePoint };
-        }
-        char[] result = new char[2];
-        toSurrogates(codePoint, result, 0);
-        return result;
     }
 
     static void toSurrogates(int codePoint, char[] dst, int index) {
         // We write elements "backwards" to guarantee all-or-nothing
-        dst[index+1] = (char)((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
-        dst[index] = (char)((codePoint >>> 10)
-            + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
+        dst[index+1] = lowSurrogate(codePoint);
+        dst[index] = highSurrogate(codePoint);
     }
 
     /**
@@ -4385,13 +4559,12 @@
         if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) {
             throw new IndexOutOfBoundsException();
         }
-        int n = 0;
+        int n = endIndex - beginIndex;
         for (int i = beginIndex; i < endIndex; ) {
-            n++;
-            if (isHighSurrogate(seq.charAt(i++))) {
-                if (i < endIndex && isLowSurrogate(seq.charAt(i))) {
-                    i++;
-                }
+            if (isHighSurrogate(seq.charAt(i++)) && i < endIndex &&
+                isLowSurrogate(seq.charAt(i))) {
+                n--;
+                i++;
             }
         }
         return n;
@@ -4425,13 +4598,12 @@
 
     static int codePointCountImpl(char[] a, int offset, int count) {
         int endIndex = offset + count;
-        int n = 0;
+        int n = count;
         for (int i = offset; i < endIndex; ) {
-            n++;
-            if (isHighSurrogate(a[i++])) {
-                if (i < endIndex && isLowSurrogate(a[i])) {
-                    i++;
-                }
+            if (isHighSurrogate(a[i++]) && i < endIndex &&
+                isLowSurrogate(a[i])) {
+                n--;
+                i++;
             }
         }
         return n;
@@ -4470,10 +4642,9 @@
         if (codePointOffset >= 0) {
             int i;
             for (i = 0; x < length && i < codePointOffset; i++) {
-                if (isHighSurrogate(seq.charAt(x++))) {
-                    if (x < length && isLowSurrogate(seq.charAt(x))) {
-                        x++;
-                    }
+                if (isHighSurrogate(seq.charAt(x++)) && x < length &&
+                    isLowSurrogate(seq.charAt(x))) {
+                    x++;
                 }
             }
             if (i < codePointOffset) {
@@ -4482,10 +4653,9 @@
         } else {
             int i;
             for (i = codePointOffset; x > 0 && i < 0; i++) {
-                if (isLowSurrogate(seq.charAt(--x))) {
-                    if (x > 0 && isHighSurrogate(seq.charAt(x-1))) {
-                        x--;
-                    }
+                if (isLowSurrogate(seq.charAt(--x)) && x > 0 &&
+                    isHighSurrogate(seq.charAt(x-1))) {
+                    x--;
                 }
             }
             if (i < 0) {
@@ -4544,10 +4714,9 @@
             int limit = start + count;
             int i;
             for (i = 0; x < limit && i < codePointOffset; i++) {
-                if (isHighSurrogate(a[x++])) {
-                    if (x < limit && isLowSurrogate(a[x])) {
-                        x++;
-                    }
+                if (isHighSurrogate(a[x++]) && x < limit &&
+                    isLowSurrogate(a[x])) {
+                    x++;
                 }
             }
             if (i < codePointOffset) {
@@ -4556,10 +4725,9 @@
         } else {
             int i;
             for (i = codePointOffset; x > start && i < 0; i++) {
-                if (isLowSurrogate(a[--x])) {
-                    if (x > start && isHighSurrogate(a[x-1])) {
-                        x--;
-                    }
+                if (isLowSurrogate(a[--x]) && x > start &&
+                    isHighSurrogate(a[x-1])) {
+                    x--;
                 }
             }
             if (i < 0) {
@@ -4569,7 +4737,7 @@
         return x;
     }
 
-   /**
+    /**
      * Determines if the specified character is a lowercase character.
      * <p>
      * A character is lowercase if its general category type, provided
@@ -4594,10 +4762,10 @@
      * @param   ch   the character to be tested.
      * @return  <code>true</code> if the character is lowercase;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.Character#isTitleCase(char)
-     * @see     java.lang.Character#toLowerCase(char)
-     * @see     java.lang.Character#getType(char)
+     * @see     Character#isLowerCase(char)
+     * @see     Character#isTitleCase(char)
+     * @see     Character#toLowerCase(char)
+     * @see     Character#getType(char)
      */
     public static boolean isLowerCase(char ch) {
         return isLowerCase((int)ch);
@@ -4624,17 +4792,17 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is lowercase;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isLowerCase(int)
-     * @see     java.lang.Character#isTitleCase(int)
-     * @see     java.lang.Character#toLowerCase(int)
-     * @see     java.lang.Character#getType(int)
+     * @see     Character#isLowerCase(int)
+     * @see     Character#isTitleCase(int)
+     * @see     Character#toLowerCase(int)
+     * @see     Character#getType(int)
      * @since   1.5
      */
     public static boolean isLowerCase(int codePoint) {
         return getType(codePoint) == Character.LOWERCASE_LETTER;
     }
 
-   /**
+    /**
      * Determines if the specified character is an uppercase character.
      * <p>
      * A character is uppercase if its general category type, provided by
@@ -4658,10 +4826,10 @@
      * @param   ch   the character to be tested.
      * @return  <code>true</code> if the character is uppercase;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.Character#isTitleCase(char)
-     * @see     java.lang.Character#toUpperCase(char)
-     * @see     java.lang.Character#getType(char)
+     * @see     Character#isLowerCase(char)
+     * @see     Character#isTitleCase(char)
+     * @see     Character#toUpperCase(char)
+     * @see     Character#getType(char)
      * @since   1.0
      */
     public static boolean isUpperCase(char ch) {
@@ -4687,10 +4855,10 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is uppercase;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isLowerCase(int)
-     * @see     java.lang.Character#isTitleCase(int)
-     * @see     java.lang.Character#toUpperCase(int)
-     * @see     java.lang.Character#getType(int)
+     * @see     Character#isLowerCase(int)
+     * @see     Character#isTitleCase(int)
+     * @see     Character#toUpperCase(int)
+     * @see     Character#getType(int)
      * @since   1.5
      */
     public static boolean isUpperCase(int codePoint) {
@@ -4728,10 +4896,10 @@
      * @param   ch   the character to be tested.
      * @return  <code>true</code> if the character is titlecase;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.Character#isUpperCase(char)
-     * @see     java.lang.Character#toTitleCase(char)
-     * @see     java.lang.Character#getType(char)
+     * @see     Character#isLowerCase(char)
+     * @see     Character#isUpperCase(char)
+     * @see     Character#toTitleCase(char)
+     * @see     Character#getType(char)
      * @since   1.0.2
      */
     public static boolean isTitleCase(char ch) {
@@ -4764,10 +4932,10 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is titlecase;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isLowerCase(int)
-     * @see     java.lang.Character#isUpperCase(int)
-     * @see     java.lang.Character#toTitleCase(int)
-     * @see     java.lang.Character#getType(int)
+     * @see     Character#isLowerCase(int)
+     * @see     Character#isUpperCase(int)
+     * @see     Character#toTitleCase(int)
+     * @see     Character#getType(int)
      * @since   1.5
      */
     public static boolean isTitleCase(int codePoint) {
@@ -4805,9 +4973,9 @@
      * @param   ch   the character to be tested.
      * @return  <code>true</code> if the character is a digit;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#digit(char, int)
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Character#getType(char)
+     * @see     Character#digit(char, int)
+     * @see     Character#forDigit(int, int)
+     * @see     Character#getType(char)
      */
     public static boolean isDigit(char ch) {
         return isDigit((int)ch);
@@ -4839,8 +5007,8 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is a digit;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Character#getType(int)
+     * @see     Character#forDigit(int, int)
+     * @see     Character#getType(int)
      * @since   1.5
      */
     public static boolean isDigit(int codePoint) {
@@ -4864,12 +5032,12 @@
      * @param   ch   the character to be tested
      * @return  <code>true</code> if the character has a defined meaning
      *          in Unicode; <code>false</code> otherwise.
-     * @see     java.lang.Character#isDigit(char)
-     * @see     java.lang.Character#isLetter(char)
-     * @see     java.lang.Character#isLetterOrDigit(char)
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.Character#isTitleCase(char)
-     * @see     java.lang.Character#isUpperCase(char)
+     * @see     Character#isDigit(char)
+     * @see     Character#isLetter(char)
+     * @see     Character#isLetterOrDigit(char)
+     * @see     Character#isLowerCase(char)
+     * @see     Character#isTitleCase(char)
+     * @see     Character#isUpperCase(char)
      * @since   1.0.2
      */
     public static boolean isDefined(char ch) {
@@ -4888,12 +5056,12 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character has a defined meaning
      *          in Unicode; <code>false</code> otherwise.
-     * @see     java.lang.Character#isDigit(int)
-     * @see     java.lang.Character#isLetter(int)
-     * @see     java.lang.Character#isLetterOrDigit(int)
-     * @see     java.lang.Character#isLowerCase(int)
-     * @see     java.lang.Character#isTitleCase(int)
-     * @see     java.lang.Character#isUpperCase(int)
+     * @see     Character#isDigit(int)
+     * @see     Character#isLetter(int)
+     * @see     Character#isLetterOrDigit(int)
+     * @see     Character#isLowerCase(int)
+     * @see     Character#isTitleCase(int)
+     * @see     Character#isUpperCase(int)
      * @since   1.5
      */
     public static boolean isDefined(int codePoint) {
@@ -4925,15 +5093,15 @@
      * @param   ch   the character to be tested.
      * @return  <code>true</code> if the character is a letter;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isDigit(char)
-     * @see     java.lang.Character#isJavaIdentifierStart(char)
-     * @see     java.lang.Character#isJavaLetter(char)
-     * @see     java.lang.Character#isJavaLetterOrDigit(char)
-     * @see     java.lang.Character#isLetterOrDigit(char)
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.Character#isTitleCase(char)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(char)
-     * @see     java.lang.Character#isUpperCase(char)
+     * @see     Character#isDigit(char)
+     * @see     Character#isJavaIdentifierStart(char)
+     * @see     Character#isJavaLetter(char)
+     * @see     Character#isJavaLetterOrDigit(char)
+     * @see     Character#isLetterOrDigit(char)
+     * @see     Character#isLowerCase(char)
+     * @see     Character#isTitleCase(char)
+     * @see     Character#isUnicodeIdentifierStart(char)
+     * @see     Character#isUpperCase(char)
      */
     public static boolean isLetter(char ch) {
         return isLetter((int)ch);
@@ -4959,13 +5127,13 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is a letter;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isDigit(int)
-     * @see     java.lang.Character#isJavaIdentifierStart(int)
-     * @see     java.lang.Character#isLetterOrDigit(int)
-     * @see     java.lang.Character#isLowerCase(int)
-     * @see     java.lang.Character#isTitleCase(int)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(int)
-     * @see     java.lang.Character#isUpperCase(int)
+     * @see     Character#isDigit(int)
+     * @see     Character#isJavaIdentifierStart(int)
+     * @see     Character#isLetterOrDigit(int)
+     * @see     Character#isLowerCase(int)
+     * @see     Character#isTitleCase(int)
+     * @see     Character#isUnicodeIdentifierStart(int)
+     * @see     Character#isUpperCase(int)
      * @since   1.5
      */
     public static boolean isLetter(int codePoint) {
@@ -4993,12 +5161,12 @@
      * @param   ch   the character to be tested.
      * @return  <code>true</code> if the character is a letter or digit;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isDigit(char)
-     * @see     java.lang.Character#isJavaIdentifierPart(char)
-     * @see     java.lang.Character#isJavaLetter(char)
-     * @see     java.lang.Character#isJavaLetterOrDigit(char)
-     * @see     java.lang.Character#isLetter(char)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(char)
+     * @see     Character#isDigit(char)
+     * @see     Character#isJavaIdentifierPart(char)
+     * @see     Character#isJavaLetter(char)
+     * @see     Character#isJavaLetterOrDigit(char)
+     * @see     Character#isLetter(char)
+     * @see     Character#isUnicodeIdentifierPart(char)
      * @since   1.0.2
      */
     public static boolean isLetterOrDigit(char ch) {
@@ -5016,10 +5184,10 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is a letter or digit;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isDigit(int)
-     * @see     java.lang.Character#isJavaIdentifierPart(int)
-     * @see     java.lang.Character#isLetter(int)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(int)
+     * @see     Character#isDigit(int)
+     * @see     Character#isJavaIdentifierPart(int)
+     * @see     Character#isLetter(int)
+     * @see     Character#isUnicodeIdentifierPart(int)
      * @since   1.5
      */
     public static boolean isLetterOrDigit(int codePoint) {
@@ -5048,12 +5216,12 @@
      * @param   ch the character to be tested.
      * @return  <code>true</code> if the character may start a Java
      *          identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaLetterOrDigit(char)
-     * @see     java.lang.Character#isJavaIdentifierStart(char)
-     * @see     java.lang.Character#isJavaIdentifierPart(char)
-     * @see     java.lang.Character#isLetter(char)
-     * @see     java.lang.Character#isLetterOrDigit(char)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(char)
+     * @see     Character#isJavaLetterOrDigit(char)
+     * @see     Character#isJavaIdentifierStart(char)
+     * @see     Character#isJavaIdentifierPart(char)
+     * @see     Character#isLetter(char)
+     * @see     Character#isLetterOrDigit(char)
+     * @see     Character#isUnicodeIdentifierStart(char)
      * @since   1.02
      * @deprecated Replaced by isJavaIdentifierStart(char).
      */
@@ -5083,13 +5251,13 @@
      * @param   ch the character to be tested.
      * @return  <code>true</code> if the character may be part of a
      *          Java identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaLetter(char)
-     * @see     java.lang.Character#isJavaIdentifierStart(char)
-     * @see     java.lang.Character#isJavaIdentifierPart(char)
-     * @see     java.lang.Character#isLetter(char)
-     * @see     java.lang.Character#isLetterOrDigit(char)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(char)
-     * @see     java.lang.Character#isIdentifierIgnorable(char)
+     * @see     Character#isJavaLetter(char)
+     * @see     Character#isJavaIdentifierStart(char)
+     * @see     Character#isJavaIdentifierPart(char)
+     * @see     Character#isLetter(char)
+     * @see     Character#isLetterOrDigit(char)
+     * @see     Character#isUnicodeIdentifierPart(char)
+     * @see     Character#isIdentifierIgnorable(char)
      * @since   1.02
      * @deprecated Replaced by isJavaIdentifierPart(char).
      */
@@ -5119,9 +5287,9 @@
      * @param   ch the character to be tested.
      * @return  <code>true</code> if the character may start a Java identifier;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaIdentifierPart(char)
-     * @see     java.lang.Character#isLetter(char)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(char)
+     * @see     Character#isJavaIdentifierPart(char)
+     * @see     Character#isLetter(char)
+     * @see     Character#isUnicodeIdentifierStart(char)
      * @see     javax.lang.model.SourceVersion#isIdentifier(CharSequence)
      * @since   1.1
      */
@@ -5148,9 +5316,9 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character may start a Java identifier;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaIdentifierPart(int)
-     * @see     java.lang.Character#isLetter(int)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(int)
+     * @see     Character#isJavaIdentifierPart(int)
+     * @see     Character#isLetter(int)
+     * @see     Character#isUnicodeIdentifierStart(int)
      * @see     javax.lang.model.SourceVersion#isIdentifier(CharSequence)
      * @since   1.5
      */
@@ -5184,10 +5352,10 @@
      * @param   ch      the character to be tested.
      * @return <code>true</code> if the character may be part of a
      *          Java identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isIdentifierIgnorable(char)
-     * @see     java.lang.Character#isJavaIdentifierStart(char)
-     * @see     java.lang.Character#isLetterOrDigit(char)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(char)
+     * @see     Character#isIdentifierIgnorable(char)
+     * @see     Character#isJavaIdentifierStart(char)
+     * @see     Character#isLetterOrDigit(char)
+     * @see     Character#isUnicodeIdentifierPart(char)
      * @see     javax.lang.model.SourceVersion#isIdentifier(CharSequence)
      * @since   1.1
      */
@@ -5217,10 +5385,10 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return <code>true</code> if the character may be part of a
      *          Java identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isIdentifierIgnorable(int)
-     * @see     java.lang.Character#isJavaIdentifierStart(int)
-     * @see     java.lang.Character#isLetterOrDigit(int)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(int)
+     * @see     Character#isIdentifierIgnorable(int)
+     * @see     Character#isJavaIdentifierStart(int)
+     * @see     Character#isLetterOrDigit(int)
+     * @see     Character#isUnicodeIdentifierPart(int)
      * @see     javax.lang.model.SourceVersion#isIdentifier(CharSequence)
      * @since   1.5
      */
@@ -5248,9 +5416,9 @@
      * @param   ch      the character to be tested.
      * @return  <code>true</code> if the character may start a Unicode
      *          identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaIdentifierStart(char)
-     * @see     java.lang.Character#isLetter(char)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(char)
+     * @see     Character#isJavaIdentifierStart(char)
+     * @see     Character#isLetter(char)
+     * @see     Character#isUnicodeIdentifierPart(char)
      * @since   1.1
      */
     public static boolean isUnicodeIdentifierStart(char ch) {
@@ -5272,9 +5440,9 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character may start a Unicode
      *          identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaIdentifierStart(int)
-     * @see     java.lang.Character#isLetter(int)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(int)
+     * @see     Character#isJavaIdentifierStart(int)
+     * @see     Character#isLetter(int)
+     * @see     Character#isUnicodeIdentifierPart(int)
      * @since   1.5
      */
     public static boolean isUnicodeIdentifierStart(int codePoint) {
@@ -5306,10 +5474,10 @@
      * @param   ch      the character to be tested.
      * @return  <code>true</code> if the character may be part of a
      *          Unicode identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isIdentifierIgnorable(char)
-     * @see     java.lang.Character#isJavaIdentifierPart(char)
-     * @see     java.lang.Character#isLetterOrDigit(char)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(char)
+     * @see     Character#isIdentifierIgnorable(char)
+     * @see     Character#isJavaIdentifierPart(char)
+     * @see     Character#isLetterOrDigit(char)
+     * @see     Character#isUnicodeIdentifierStart(char)
      * @since   1.1
      */
     public static boolean isUnicodeIdentifierPart(char ch) {
@@ -5335,10 +5503,10 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character may be part of a
      *          Unicode identifier; <code>false</code> otherwise.
-     * @see     java.lang.Character#isIdentifierIgnorable(int)
-     * @see     java.lang.Character#isJavaIdentifierPart(int)
-     * @see     java.lang.Character#isLetterOrDigit(int)
-     * @see     java.lang.Character#isUnicodeIdentifierStart(int)
+     * @see     Character#isIdentifierIgnorable(int)
+     * @see     Character#isJavaIdentifierPart(int)
+     * @see     Character#isLetterOrDigit(int)
+     * @see     Character#isUnicodeIdentifierStart(int)
      * @since   1.5
      */
     public static boolean isUnicodeIdentifierPart(int codePoint) {
@@ -5372,8 +5540,8 @@
      * @return  <code>true</code> if the character is an ignorable control
      *          character that may be part of a Java or Unicode identifier;
      *           <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaIdentifierPart(char)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(char)
+     * @see     Character#isJavaIdentifierPart(char)
+     * @see     Character#isUnicodeIdentifierPart(char)
      * @since   1.1
      */
     public static boolean isIdentifierIgnorable(char ch) {
@@ -5402,8 +5570,8 @@
      * @return  <code>true</code> if the character is an ignorable control
      *          character that may be part of a Java or Unicode identifier;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isJavaIdentifierPart(int)
-     * @see     java.lang.Character#isUnicodeIdentifierPart(int)
+     * @see     Character#isJavaIdentifierPart(int)
+     * @see     Character#isUnicodeIdentifierPart(int)
      * @since   1.5
      */
     public static boolean isIdentifierIgnorable(int codePoint) {
@@ -5419,7 +5587,7 @@
      * does not always return <code>true</code> for some ranges of
      * characters, particularly those that are symbols or ideographs.
      *
-     * <p>In general, {@link java.lang.String#toLowerCase()} should be used to map
+     * <p>In general, {@link String#toLowerCase()} should be used to map
      * characters to lowercase. <code>String</code> case mapping methods
      * have several benefits over <code>Character</code> case mapping methods.
      * <code>String</code> case mapping methods can perform locale-sensitive
@@ -5434,8 +5602,8 @@
      * @param   ch   the character to be converted.
      * @return  the lowercase equivalent of the character, if any;
      *          otherwise, the character itself.
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.String#toLowerCase()
+     * @see     Character#isLowerCase(char)
+     * @see     String#toLowerCase()
      */
     public static char toLowerCase(char ch) {
         return (char)toLowerCase((int)ch);
@@ -5451,7 +5619,7 @@
      * does not always return <code>true</code> for some ranges of
      * characters, particularly those that are symbols or ideographs.
      *
-     * <p>In general, {@link java.lang.String#toLowerCase()} should be used to map
+     * <p>In general, {@link String#toLowerCase()} should be used to map
      * characters to lowercase. <code>String</code> case mapping methods
      * have several benefits over <code>Character</code> case mapping methods.
      * <code>String</code> case mapping methods can perform locale-sensitive
@@ -5461,8 +5629,8 @@
      * @param   codePoint   the character (Unicode code point) to be converted.
      * @return  the lowercase equivalent of the character (Unicode code
      *          point), if any; otherwise, the character itself.
-     * @see     java.lang.Character#isLowerCase(int)
-     * @see     java.lang.String#toLowerCase()
+     * @see     Character#isLowerCase(int)
+     * @see     String#toLowerCase()
      *
      * @since   1.5
      */
@@ -5479,7 +5647,7 @@
      * does not always return <code>true</code> for some ranges of
      * characters, particularly those that are symbols or ideographs.
      *
-     * <p>In general, {@link java.lang.String#toUpperCase()} should be used to map
+     * <p>In general, {@link String#toUpperCase()} should be used to map
      * characters to uppercase. <code>String</code> case mapping methods
      * have several benefits over <code>Character</code> case mapping methods.
      * <code>String</code> case mapping methods can perform locale-sensitive
@@ -5494,8 +5662,8 @@
      * @param   ch   the character to be converted.
      * @return  the uppercase equivalent of the character, if any;
      *          otherwise, the character itself.
-     * @see     java.lang.Character#isUpperCase(char)
-     * @see     java.lang.String#toUpperCase()
+     * @see     Character#isUpperCase(char)
+     * @see     String#toUpperCase()
      */
     public static char toUpperCase(char ch) {
         return (char)toUpperCase((int)ch);
@@ -5511,7 +5679,7 @@
      * does not always return <code>true</code> for some ranges of
      * characters, particularly those that are symbols or ideographs.
      *
-     * <p>In general, {@link java.lang.String#toUpperCase()} should be used to map
+     * <p>In general, {@link String#toUpperCase()} should be used to map
      * characters to uppercase. <code>String</code> case mapping methods
      * have several benefits over <code>Character</code> case mapping methods.
      * <code>String</code> case mapping methods can perform locale-sensitive
@@ -5521,8 +5689,8 @@
      * @param   codePoint   the character (Unicode code point) to be converted.
      * @return  the uppercase equivalent of the character, if any;
      *          otherwise, the character itself.
-     * @see     java.lang.Character#isUpperCase(int)
-     * @see     java.lang.String#toUpperCase()
+     * @see     Character#isUpperCase(int)
+     * @see     String#toUpperCase()
      *
      * @since   1.5
      */
@@ -5553,9 +5721,9 @@
      * @param   ch   the character to be converted.
      * @return  the titlecase equivalent of the character, if any;
      *          otherwise, the character itself.
-     * @see     java.lang.Character#isTitleCase(char)
-     * @see     java.lang.Character#toLowerCase(char)
-     * @see     java.lang.Character#toUpperCase(char)
+     * @see     Character#isTitleCase(char)
+     * @see     Character#toLowerCase(char)
+     * @see     Character#toUpperCase(char)
      * @since   1.0.2
      */
     public static char toTitleCase(char ch) {
@@ -5580,9 +5748,9 @@
      * @param   codePoint   the character (Unicode code point) to be converted.
      * @return  the titlecase equivalent of the character, if any;
      *          otherwise, the character itself.
-     * @see     java.lang.Character#isTitleCase(int)
-     * @see     java.lang.Character#toLowerCase(int)
-     * @see     java.lang.Character#toUpperCase(int)
+     * @see     Character#isTitleCase(int)
+     * @see     Character#toLowerCase(int)
+     * @see     Character#toUpperCase(int)
      * @since   1.5
      */
     public static int toTitleCase(int codePoint) {
@@ -5624,8 +5792,8 @@
      * @param   radix   the radix.
      * @return  the numeric value represented by the character in the
      *          specified radix.
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Character#isDigit(char)
+     * @see     Character#forDigit(int, int)
+     * @see     Character#isDigit(char)
      */
     public static int digit(char ch, int radix) {
         return digit((int)ch, radix);
@@ -5661,8 +5829,8 @@
      * @param   radix   the radix.
      * @return  the numeric value represented by the character in the
      *          specified radix.
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Character#isDigit(int)
+     * @see     Character#forDigit(int, int)
+     * @see     Character#isDigit(int)
      * @since   1.5
      */
     public static int digit(int codePoint, int radix) {
@@ -5699,8 +5867,8 @@
      * @return  the numeric value of the character, as a nonnegative <code>int</code>
      *           value; -2 if the character has a numeric value that is not a
      *          nonnegative integer; -1 if the character has no numeric value.
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Character#isDigit(char)
+     * @see     Character#forDigit(int, int)
+     * @see     Character#isDigit(char)
      * @since   1.1
      */
     public static int getNumericValue(char ch) {
@@ -5732,8 +5900,8 @@
      * @return  the numeric value of the character, as a nonnegative <code>int</code>
      *          value; -2 if the character has a numeric value that is not a
      *          nonnegative integer; -1 if the character has no numeric value.
-     * @see     java.lang.Character#forDigit(int, int)
-     * @see     java.lang.Character#isDigit(int)
+     * @see     Character#forDigit(int, int)
+     * @see     Character#isDigit(int)
      * @since   1.5
      */
     public static int getNumericValue(int codePoint) {
@@ -5760,8 +5928,8 @@
      * @param      ch   the character to be tested.
      * @return     <code>true</code> if the character is ISO-LATIN-1 white
      *             space; <code>false</code> otherwise.
-     * @see        java.lang.Character#isSpaceChar(char)
-     * @see        java.lang.Character#isWhitespace(char)
+     * @see        Character#isSpaceChar(char)
+     * @see        Character#isWhitespace(char)
      * @deprecated Replaced by isWhitespace(char).
      */
     @Deprecated
@@ -5795,7 +5963,7 @@
      * @param   ch      the character to be tested.
      * @return  <code>true</code> if the character is a space character;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isWhitespace(char)
+     * @see     Character#isWhitespace(char)
      * @since   1.1
      */
     public static boolean isSpaceChar(char ch) {
@@ -5818,7 +5986,7 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is a space character;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isWhitespace(int)
+     * @see     Character#isWhitespace(int)
      * @since   1.5
      */
     public static boolean isSpaceChar(int codePoint) {
@@ -5856,7 +6024,7 @@
      * @param   ch the character to be tested.
      * @return  <code>true</code> if the character is a Java whitespace
      *          character; <code>false</code> otherwise.
-     * @see     java.lang.Character#isSpaceChar(char)
+     * @see     Character#isSpaceChar(char)
      * @since   1.1
      */
     public static boolean isWhitespace(char ch) {
@@ -5888,7 +6056,7 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is a Java whitespace
      *          character; <code>false</code> otherwise.
-     * @see     java.lang.Character#isSpaceChar(int)
+     * @see     Character#isSpaceChar(int)
      * @since   1.5
      */
     public static boolean isWhitespace(int codePoint) {
@@ -5911,8 +6079,8 @@
      * @return  <code>true</code> if the character is an ISO control character;
      *          <code>false</code> otherwise.
      *
-     * @see     java.lang.Character#isSpaceChar(char)
-     * @see     java.lang.Character#isWhitespace(char)
+     * @see     Character#isSpaceChar(char)
+     * @see     Character#isWhitespace(char)
      * @since   1.1
      */
     public static boolean isISOControl(char ch) {
@@ -5929,13 +6097,16 @@
      * @param   codePoint the character (Unicode code point) to be tested.
      * @return  <code>true</code> if the character is an ISO control character;
      *          <code>false</code> otherwise.
-     * @see     java.lang.Character#isSpaceChar(int)
-     * @see     java.lang.Character#isWhitespace(int)
+     * @see     Character#isSpaceChar(int)
+     * @see     Character#isWhitespace(int)
      * @since   1.5
      */
     public static boolean isISOControl(int codePoint) {
-        return (codePoint >= 0x0000 && codePoint <= 0x001F) ||
-            (codePoint >= 0x007F && codePoint <= 0x009F);
+        // Optimized form of:
+        //     (codePoint >= 0x00 && codePoint <= 0x1F) ||
+        //     (codePoint >= 0x7F && codePoint <= 0x9F);
+        return codePoint <= 0x9F &&
+            (codePoint >= 0x7F || (codePoint >>> 5 == 0));
     }
 
     /**
@@ -5949,36 +6120,36 @@
      * @param   ch      the character to be tested.
      * @return  a value of type <code>int</code> representing the
      *          character's general category.
-     * @see     java.lang.Character#COMBINING_SPACING_MARK
-     * @see     java.lang.Character#CONNECTOR_PUNCTUATION
-     * @see     java.lang.Character#CONTROL
-     * @see     java.lang.Character#CURRENCY_SYMBOL
-     * @see     java.lang.Character#DASH_PUNCTUATION
-     * @see     java.lang.Character#DECIMAL_DIGIT_NUMBER
-     * @see     java.lang.Character#ENCLOSING_MARK
-     * @see     java.lang.Character#END_PUNCTUATION
-     * @see     java.lang.Character#FINAL_QUOTE_PUNCTUATION
-     * @see     java.lang.Character#FORMAT
-     * @see     java.lang.Character#INITIAL_QUOTE_PUNCTUATION
-     * @see     java.lang.Character#LETTER_NUMBER
-     * @see     java.lang.Character#LINE_SEPARATOR
-     * @see     java.lang.Character#LOWERCASE_LETTER
-     * @see     java.lang.Character#MATH_SYMBOL
-     * @see     java.lang.Character#MODIFIER_LETTER
-     * @see     java.lang.Character#MODIFIER_SYMBOL
-     * @see     java.lang.Character#NON_SPACING_MARK
-     * @see     java.lang.Character#OTHER_LETTER
-     * @see     java.lang.Character#OTHER_NUMBER
-     * @see     java.lang.Character#OTHER_PUNCTUATION
-     * @see     java.lang.Character#OTHER_SYMBOL
-     * @see     java.lang.Character#PARAGRAPH_SEPARATOR
-     * @see     java.lang.Character#PRIVATE_USE
-     * @see     java.lang.Character#SPACE_SEPARATOR
-     * @see     java.lang.Character#START_PUNCTUATION
-     * @see     java.lang.Character#SURROGATE
-     * @see     java.lang.Character#TITLECASE_LETTER
-     * @see     java.lang.Character#UNASSIGNED
-     * @see     java.lang.Character#UPPERCASE_LETTER
+     * @see     Character#COMBINING_SPACING_MARK
+     * @see     Character#CONNECTOR_PUNCTUATION
+     * @see     Character#CONTROL
+     * @see     Character#CURRENCY_SYMBOL
+     * @see     Character#DASH_PUNCTUATION
+     * @see     Character#DECIMAL_DIGIT_NUMBER
+     * @see     Character#ENCLOSING_MARK
+     * @see     Character#END_PUNCTUATION
+     * @see     Character#FINAL_QUOTE_PUNCTUATION
+     * @see     Character#FORMAT
+     * @see     Character#INITIAL_QUOTE_PUNCTUATION
+     * @see     Character#LETTER_NUMBER
+     * @see     Character#LINE_SEPARATOR
+     * @see     Character#LOWERCASE_LETTER
+     * @see     Character#MATH_SYMBOL
+     * @see     Character#MODIFIER_LETTER
+     * @see     Character#MODIFIER_SYMBOL
+     * @see     Character#NON_SPACING_MARK
+     * @see     Character#OTHER_LETTER
+     * @see     Character#OTHER_NUMBER
+     * @see     Character#OTHER_PUNCTUATION
+     * @see     Character#OTHER_SYMBOL
+     * @see     Character#PARAGRAPH_SEPARATOR
+     * @see     Character#PRIVATE_USE
+     * @see     Character#SPACE_SEPARATOR
+     * @see     Character#START_PUNCTUATION
+     * @see     Character#SURROGATE
+     * @see     Character#TITLECASE_LETTER
+     * @see     Character#UNASSIGNED
+     * @see     Character#UPPERCASE_LETTER
      * @since   1.1
      */
     public static int getType(char ch) {
@@ -6047,9 +6218,9 @@
      * @param   radix   the radix.
      * @return  the <code>char</code> representation of the specified digit
      *          in the specified radix.
-     * @see     java.lang.Character#MIN_RADIX
-     * @see     java.lang.Character#MAX_RADIX
-     * @see     java.lang.Character#digit(char, int)
+     * @see     Character#MIN_RADIX
+     * @see     Character#MAX_RADIX
+     * @see     Character#digit(char, int)
      */
     public static char forDigit(int digit, int radix) {
         if ((digit >= radix) || (digit < 0)) {
@@ -6230,10 +6401,10 @@
      * @return  either the uppercase equivalent of the character, if
      *          any, or an error flag (<code>Character.ERROR</code>)
      *          that indicates that a 1:M <code>char</code> mapping exists.
-     * @see     java.lang.Character#isLowerCase(char)
-     * @see     java.lang.Character#isUpperCase(char)
-     * @see     java.lang.Character#toLowerCase(char)
-     * @see     java.lang.Character#toTitleCase(char)
+     * @see     Character#isLowerCase(char)
+     * @see     Character#isUpperCase(char)
+     * @see     Character#toLowerCase(char)
+     * @see     Character#toTitleCase(char)
      * @since 1.4
      */
     static int toUpperCaseEx(int codePoint) {
@@ -6254,8 +6425,7 @@
      */
     static char[] toUpperCaseCharArray(int codePoint) {
         // As of Unicode 4.0, 1:M uppercasings only happen in the BMP.
-        assert isValidCodePoint(codePoint) &&
-               !isSupplementaryCodePoint(codePoint);
+        assert isBmpCodePoint(codePoint);
         return CharacterData.of(codePoint).toUpperCaseCharArray(codePoint);
     }
 
--- a/jdk/src/share/classes/java/lang/String.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/lang/String.java	Wed Jul 05 17:17:57 2017 +0200
@@ -38,7 +38,6 @@
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
-
 /**
  * The <code>String</code> class represents character strings. All
  * string literals in Java programs, such as <code>"abc"</code>, are
@@ -99,6 +98,8 @@
  *
  * @author  Lee Boynton
  * @author  Arthur van Hoff
+ * @author  Martin Buchholz
+ * @author  Ulf Zibis
  * @see     java.lang.Object#toString()
  * @see     java.lang.StringBuffer
  * @see     java.lang.StringBuilder
@@ -273,32 +274,32 @@
             throw new StringIndexOutOfBoundsException(offset + count);
         }
 
+        final int end = offset + count;
+
         // Pass 1: Compute precise size of char[]
-        int n = 0;
-        for (int i = offset; i < offset + count; i++) {
+        int n = count;
+        for (int i = offset; i < end; i++) {
             int c = codePoints[i];
-            if (c >= Character.MIN_CODE_POINT &&
-                c <  Character.MIN_SUPPLEMENTARY_CODE_POINT)
-                n += 1;
-            else if (Character.isSupplementaryCodePoint(c))
-                n += 2;
+            if (Character.isBmpCodePoint(c))
+                continue;
+            else if (Character.isValidCodePoint(c))
+                n++;
             else throw new IllegalArgumentException(Integer.toString(c));
         }
 
         // Pass 2: Allocate and fill in char[]
-        char[] v = new char[n];
-        for (int i = offset, j = 0; i < offset + count; i++) {
+        final char[] v = new char[n];
+
+        for (int i = offset, j = 0; i < end; i++, j++) {
             int c = codePoints[i];
-            if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-                v[j++] = (char) c;
-            } else {
-                Character.toSurrogates(c, v, j);
-                j += 2;
-            }
+            if (Character.isBmpCodePoint(c))
+                v[j] = (char) c;
+            else
+                Character.toSurrogates(c, v, j++);
         }
 
         this.value  = v;
-        this.count  = v.length;
+        this.count  = n;
         this.offset = 0;
     }
 
@@ -1573,9 +1574,6 @@
      *          if the character does not occur.
      */
     public int indexOf(int ch, int fromIndex) {
-        int max = offset + count;
-        char v[] = value;
-
         if (fromIndex < 0) {
             fromIndex = 0;
         } else if (fromIndex >= count) {
@@ -1583,29 +1581,36 @@
             return -1;
         }
 
-        int i = offset + fromIndex;
         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
             // handle most cases here (ch is a BMP code point or a
             // negative value (invalid code point))
-            for (; i < max ; i++) {
-                if (v[i] == ch) {
+            final char[] value = this.value;
+            final int offset = this.offset;
+            final int max = offset + count;
+            for (int i = offset + fromIndex; i < max ; i++) {
+                if (value[i] == ch) {
                     return i - offset;
                 }
             }
             return -1;
+        } else {
+            return indexOfSupplementary(ch, fromIndex);
         }
+    }
 
-        if (ch <= Character.MAX_CODE_POINT) {
-            // handle supplementary characters here
-            char[] surrogates = Character.toChars(ch);
-            for (; i < max; i++) {
-                if (v[i] == surrogates[0]) {
-                    if (i + 1 == max) {
-                        break;
-                    }
-                    if (v[i+1] == surrogates[1]) {
-                        return i - offset;
-                    }
+    /**
+     * Handles (rare) calls of indexOf with a supplementary character.
+     */
+    private int indexOfSupplementary(int ch, int fromIndex) {
+        if (Character.isValidCodePoint(ch)) {
+            final char[] value = this.value;
+            final int offset = this.offset;
+            final char hi = Character.highSurrogate(ch);
+            final char lo = Character.lowSurrogate(ch);
+            final int max = offset + count - 1;
+            for (int i = offset + fromIndex; i < max; i++) {
+                if (value[i] == hi && value[i+1] == lo) {
+                    return i - offset;
                 }
             }
         }
@@ -1674,34 +1679,36 @@
      *          if the character does not occur before that point.
      */
     public int lastIndexOf(int ch, int fromIndex) {
-        int min = offset;
-        char v[] = value;
-
-        int i = offset + ((fromIndex >= count) ? count - 1 : fromIndex);
-
         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
             // handle most cases here (ch is a BMP code point or a
             // negative value (invalid code point))
-            for (; i >= min ; i--) {
-                if (v[i] == ch) {
+            final char[] value = this.value;
+            final int offset = this.offset;
+            int i = offset + Math.min(fromIndex, count - 1);
+            for (; i >= offset ; i--) {
+                if (value[i] == ch) {
                     return i - offset;
                 }
             }
             return -1;
+        } else {
+            return lastIndexOfSupplementary(ch, fromIndex);
         }
+    }
 
-        int max = offset + count;
-        if (ch <= Character.MAX_CODE_POINT) {
-            // handle supplementary characters here
-            char[] surrogates = Character.toChars(ch);
-            for (; i >= min; i--) {
-                if (v[i] == surrogates[0]) {
-                    if (i + 1 == max) {
-                        break;
-                    }
-                    if (v[i+1] == surrogates[1]) {
-                        return i - offset;
-                    }
+    /**
+     * Handles (rare) calls of lastIndexOf with a supplementary character.
+     */
+    private int lastIndexOfSupplementary(int ch, int fromIndex) {
+        if (Character.isValidCodePoint(ch)) {
+            final char[] value = this.value;
+            final int offset = this.offset;
+            char hi = Character.highSurrogate(ch);
+            char lo = Character.lowSurrogate(ch);
+            int i = offset + Math.min(fromIndex, count - 2);
+            for (; i >= offset; i--) {
+                if (value[i] == hi && value[i+1] == lo) {
+                    return i - offset;
                 }
             }
         }
@@ -1710,18 +1717,17 @@
 
     /**
      * Returns the index within this string of the first occurrence of the
-     * specified substring. The integer returned is the smallest value
-     * <i>k</i> such that:
+     * specified substring.
+     *
+     * <p>The returned index is the smallest value <i>k</i> for which:
      * <blockquote><pre>
      * this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
-     * is <code>true</code>.
+     * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
-     * @param   str   any string.
-     * @return  if the string argument occurs as a substring within this
-     *          object, then the index of the first character of the first
-     *          such substring is returned; if it does not occur as a
-     *          substring, <code>-1</code> is returned.
+     * @param   str   the substring to search for.
+     * @return  the index of the first occurrence of the specified substring,
+     *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str) {
         return indexOf(str, 0);
@@ -1729,17 +1735,19 @@
 
     /**
      * Returns the index within this string of the first occurrence of the
-     * specified substring, starting at the specified index.  The integer
-     * returned is the smallest value <tt>k</tt> for which:
+     * specified substring, starting at the specified index.
+     *
+     * <p>The returned index is the smallest value <i>k</i> for which:
      * <blockquote><pre>
-     *     k &gt;= Math.min(fromIndex, this.length()) && this.startsWith(str, k)
+     * <i>k</i> &gt;= fromIndex && this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
-     * If no such value of <i>k</i> exists, then -1 is returned.
+     * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
-     * @param   str         the substring for which to search.
+     * @param   str         the substring to search for.
      * @param   fromIndex   the index from which to start the search.
-     * @return  the index within this string of the first occurrence of the
-     *          specified substring, starting at the specified index.
+     * @return  the index of the first occurrence of the specified substring,
+     *          starting at the specified index,
+     *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
         return indexOf(value, offset, count,
@@ -1798,20 +1806,19 @@
     }
 
     /**
-     * Returns the index within this string of the rightmost occurrence
-     * of the specified substring.  The rightmost empty string "" is
-     * considered to occur at the index value <code>this.length()</code>.
-     * The returned index is the largest value <i>k</i> such that
+     * Returns the index within this string of the last occurrence of the
+     * specified substring.  The last occurrence of the empty string ""
+     * is considered to occur at the index value {@code this.length()}.
+     *
+     * <p>The returned index is the largest value <i>k</i> for which:
      * <blockquote><pre>
-     * this.startsWith(str, k)
+     * this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
-     * is true.
+     * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
      * @param   str   the substring to search for.
-     * @return  if the string argument occurs one or more times as a substring
-     *          within this object, then the index of the first character of
-     *          the last such substring is returned. If it does not occur as
-     *          a substring, <code>-1</code> is returned.
+     * @return  the index of the last occurrence of the specified substring,
+     *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str) {
         return lastIndexOf(str, count);
@@ -1820,16 +1827,18 @@
     /**
      * Returns the index within this string of the last occurrence of the
      * specified substring, searching backward starting at the specified index.
-     * The integer returned is the largest value <i>k</i> such that:
+     *
+     * <p>The returned index is the largest value <i>k</i> for which:
      * <blockquote><pre>
-     *     k &lt;= Math.min(fromIndex, this.length()) && this.startsWith(str, k)
+     * <i>k</i> &lt;= fromIndex && this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
-     * If no such value of <i>k</i> exists, then -1 is returned.
+     * If no such value of <i>k</i> exists, then {@code -1} is returned.
      *
      * @param   str         the substring to search for.
      * @param   fromIndex   the index to start the search from.
-     * @return  the index within this string of the last occurrence of the
-     *          specified substring.
+     * @return  the index of the last occurrence of the specified substring,
+     *          searching backward from the specified index,
+     *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
         return lastIndexOf(value, offset, count,
--- a/jdk/src/share/classes/java/lang/System.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/lang/System.java	Wed Jul 05 17:17:57 2017 +0200
@@ -69,7 +69,7 @@
      * corresponds to keyboard input or another input source specified by
      * the host environment or user.
      */
-    public final static InputStream in = nullInputStream();
+    public final static InputStream in = null;
 
     /**
      * The "standard" output stream. This stream is already
@@ -96,7 +96,7 @@
      * @see     java.io.PrintStream#println(java.lang.Object)
      * @see     java.io.PrintStream#println(java.lang.String)
      */
-    public final static PrintStream out = nullPrintStream();
+    public final static PrintStream out = null;
 
     /**
      * The "standard" error output stream. This stream is already
@@ -110,7 +110,7 @@
      * variable <code>out</code>, has been redirected to a file or other
      * destination that is typically not continuously monitored.
      */
-    public final static PrintStream err = nullPrintStream();
+    public final static PrintStream err = null;
 
     /* The security manager for the system.
      */
@@ -1093,26 +1093,6 @@
     public static native String mapLibraryName(String libname);
 
     /**
-     * The following two methods exist because in, out, and err must be
-     * initialized to null.  The compiler, however, cannot be permitted to
-     * inline access to them, since they are later set to more sensible values
-     * by initializeSystemClass().
-     */
-    private static InputStream nullInputStream() throws NullPointerException {
-        if (currentTimeMillis() > 0) {
-            return null;
-        }
-        throw new NullPointerException();
-    }
-
-    private static PrintStream nullPrintStream() throws NullPointerException {
-        if (currentTimeMillis() > 0) {
-            return null;
-        }
-        throw new NullPointerException();
-    }
-
-    /**
      * Initialize the system class.  Called after thread initialization.
      */
     private static void initializeSystemClass() {
--- a/jdk/src/share/classes/java/lang/Throwable.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/lang/Throwable.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,6 +25,7 @@
 
 package java.lang;
 import  java.io.*;
+import  java.util.*;
 
 /**
  * The <code>Throwable</code> class is the superclass of all errors and
@@ -102,7 +103,7 @@
  *         lowLevelOp();
  *     } catch (LowLevelException le) {
  *         throw (HighLevelException)
-                 new HighLevelException().initCause(le);  // Legacy constructor
+ *               new HighLevelException().initCause(le);  // Legacy constructor
  *     }
  * </pre>
  *
@@ -193,6 +194,24 @@
      */
 
     /**
+     * The list of suppressed exceptions, as returned by
+     * {@link #getSuppressedExceptions()}.
+     *
+     * @serial
+     * @since 1.7
+     */
+    private List<Throwable> suppressedExceptions = Collections.emptyList();
+
+    /** Message for trying to suppress a null exception. */
+    private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
+
+    /** Caption  for labeling causative exception stack traces */
+    private static final String CAUSE_CAPTION = "Caused by: ";
+
+    /** Caption for labeling suppressed exception stack traces */
+    private static final String SUPPRESSED_CAPTION = "Suppressed: ";
+
+    /**
      * Constructs a new throwable with <code>null</code> as its detail message.
      * The cause is not initialized, and may subsequently be initialized by a
      * call to {@link #initCause}.
@@ -469,6 +488,52 @@
      * class LowLevelException extends Exception {
      * }
      * </pre>
+     * As of release 7, the platform supports the notion of
+     * <i>suppressed exceptions</i> (in conjunction with automatic
+     * resource management blocks). Any exceptions that were
+     * suppressed in order to deliver an exception are printed out
+     * beneath the stack trace.  The format of this information
+     * depends on the implementation, but the following example may be
+     * regarded as typical:
+     *
+     * <pre>
+     * Exception in thread "main" java.lang.Exception: Something happened
+     *  at Foo.bar(Foo.java:10)
+     *  at Foo.main(Foo.java:5)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 0
+     *          at Resource.close(Resource.java:26)
+     *          at Foo.bar(Foo.java:9)
+     *          ... 1 more
+     * </pre>
+     * Note that the "... n more" notation is used on suppressed exceptions
+     * just at it is used on causes. Unlike causes, suppressed exceptions are
+     * indented beyond their "containing exceptions."
+     *
+     * <p>An exception can have both a cause and one or more suppressed
+     * exceptions:
+     * <pre>
+     * Exception in thread "main" java.lang.Exception: Main block
+     *  at Foo3.main(Foo3.java:7)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 2
+     *          at Resource.close(Resource.java:26)
+     *          at Foo3.main(Foo3.java:5)
+     *  Suppressed: Resource$CloseFailException: Resource ID = 1
+     *          at Resource.close(Resource.java:26)
+     *          at Foo3.main(Foo3.java:5)
+     * Caused by: java.lang.Exception: I did it
+     *  at Foo3.main(Foo3.java:8)
+     * </pre>
+     * Likewise, a suppressed exception can have a cause:
+     * <pre>
+     * Exception in thread "main" java.lang.Exception: Main block
+     *  at Foo4.main(Foo4.java:6)
+     *  Suppressed: Resource2$CloseFailException: Resource ID = 1
+     *          at Resource2.close(Resource2.java:20)
+     *          at Foo4.main(Foo4.java:5)
+     *  Caused by: java.lang.Exception: Rats, you caught me
+     *          at Resource2$CloseFailException.<init>(Resource2.java:45)
+     *          ... 2 more
+     * </pre>
      */
     public void printStackTrace() {
         printStackTrace(System.err);
@@ -480,44 +545,71 @@
      * @param s <code>PrintStream</code> to use for output
      */
     public void printStackTrace(PrintStream s) {
-        synchronized (s) {
+        printStackTrace(new WrappedPrintStream(s));
+    }
+
+    private void printStackTrace(PrintStreamOrWriter s) {
+        Set<Throwable> dejaVu = new HashSet<Throwable>();
+        dejaVu.add(this);
+
+        synchronized (s.lock()) {
+            // Print our stack trace
             s.println(this);
             StackTraceElement[] trace = getOurStackTrace();
-            for (int i=0; i < trace.length; i++)
-                s.println("\tat " + trace[i]);
+            for (StackTraceElement traceElement : trace)
+                s.println("\tat " + traceElement);
 
+            // Print suppressed exceptions, if any
+            for (Throwable se : suppressedExceptions)
+                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
+
+            // Print cause, if any
             Throwable ourCause = getCause();
             if (ourCause != null)
-                ourCause.printStackTraceAsCause(s, trace);
+                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
         }
     }
 
     /**
-     * Print our stack trace as a cause for the specified stack trace.
+     * Print our stack trace as an enclosed exception for the specified
+     * stack trace.
      */
-    private void printStackTraceAsCause(PrintStream s,
-                                        StackTraceElement[] causedTrace)
-    {
-        // assert Thread.holdsLock(s);
+    private void printEnclosedStackTrace(PrintStreamOrWriter s,
+                                         StackTraceElement[] enclosingTrace,
+                                         String caption,
+                                         String prefix,
+                                         Set<Throwable> dejaVu) {
+        assert Thread.holdsLock(s.lock());
+        if (dejaVu.contains(this)) {
+            s.println("\t[CIRCULAR REFERENCE:" + this + "]");
+        } else {
+            dejaVu.add(this);
+            // Compute number of frames in common between this and enclosing trace
+            StackTraceElement[] trace = getOurStackTrace();
+            int m = trace.length - 1;
+            int n = enclosingTrace.length - 1;
+            while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
+                m--; n--;
+            }
+            int framesInCommon = trace.length - 1 - m;
 
-        // Compute number of frames in common between this and caused
-        StackTraceElement[] trace = getOurStackTrace();
-        int m = trace.length-1, n = causedTrace.length-1;
-        while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
-            m--; n--;
+            // Print our stack trace
+            s.println(prefix + caption + this);
+            for (int i = 0; i <= m; i++)
+                s.println(prefix + "\tat " + trace[i]);
+            if (framesInCommon != 0)
+                s.println(prefix + "\t... " + framesInCommon + " more");
+
+            // Print suppressed exceptions, if any
+            for (Throwable se : suppressedExceptions)
+                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
+                                           prefix +"\t", dejaVu);
+
+            // Print cause, if any
+            Throwable ourCause = getCause();
+            if (ourCause != null)
+                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
         }
-        int framesInCommon = trace.length - 1 - m;
-
-        s.println("Caused by: " + this);
-        for (int i=0; i <= m; i++)
-            s.println("\tat " + trace[i]);
-        if (framesInCommon != 0)
-            s.println("\t... " + framesInCommon + " more");
-
-        // Recurse if we have a cause
-        Throwable ourCause = getCause();
-        if (ourCause != null)
-            ourCause.printStackTraceAsCause(s, trace);
     }
 
     /**
@@ -528,44 +620,51 @@
      * @since   JDK1.1
      */
     public void printStackTrace(PrintWriter s) {
-        synchronized (s) {
-            s.println(this);
-            StackTraceElement[] trace = getOurStackTrace();
-            for (int i=0; i < trace.length; i++)
-                s.println("\tat " + trace[i]);
-
-            Throwable ourCause = getCause();
-            if (ourCause != null)
-                ourCause.printStackTraceAsCause(s, trace);
-        }
+        printStackTrace(new WrappedPrintWriter(s));
     }
 
     /**
-     * Print our stack trace as a cause for the specified stack trace.
+     * Wrapper class for PrintStream and PrintWriter to enable a single
+     * implementation of printStackTrace.
      */
-    private void printStackTraceAsCause(PrintWriter s,
-                                        StackTraceElement[] causedTrace)
-    {
-        // assert Thread.holdsLock(s);
+    private abstract static class PrintStreamOrWriter {
+        /** Returns the object to be locked when using this StreamOrWriter */
+        abstract Object lock();
+
+        /** Prints the specified string as a line on this StreamOrWriter */
+        abstract void println(Object o);
+    }
 
-        // Compute number of frames in common between this and caused
-        StackTraceElement[] trace = getOurStackTrace();
-        int m = trace.length-1, n = causedTrace.length-1;
-        while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {
-            m--; n--;
+    private static class WrappedPrintStream extends PrintStreamOrWriter {
+        private final PrintStream printStream;
+
+        WrappedPrintStream(PrintStream printStream) {
+            this.printStream = printStream;
+        }
+
+        Object lock() {
+            return printStream;
         }
-        int framesInCommon = trace.length - 1 - m;
+
+        void println(Object o) {
+            printStream.println(o);
+        }
+    }
+
+    private static class WrappedPrintWriter extends PrintStreamOrWriter {
+        private final PrintWriter printWriter;
 
-        s.println("Caused by: " + this);
-        for (int i=0; i <= m; i++)
-            s.println("\tat " + trace[i]);
-        if (framesInCommon != 0)
-            s.println("\t... " + framesInCommon + " more");
+        WrappedPrintWriter(PrintWriter printWriter) {
+            this.printWriter = printWriter;
+        }
 
-        // Recurse if we have a cause
-        Throwable ourCause = getCause();
-        if (ourCause != null)
-            ourCause.printStackTraceAsCause(s, trace);
+        Object lock() {
+            return printWriter;
+        }
+
+        void println(Object o) {
+            printWriter.println(o);
+        }
     }
 
     /**
@@ -667,10 +766,60 @@
      */
     native StackTraceElement getStackTraceElement(int index);
 
-    private synchronized void writeObject(java.io.ObjectOutputStream s)
+    private void readObject(ObjectInputStream s)
+        throws IOException, ClassNotFoundException {
+        s.defaultReadObject();     // read in all fields
+        List<Throwable> suppressed = Collections.emptyList();
+        if (suppressedExceptions != null &&
+            !suppressedExceptions.isEmpty()) { // Copy Throwables to new list
+            suppressed = new ArrayList<Throwable>();
+            for(Throwable t : suppressedExceptions) {
+                if (t == null)
+                    throw new NullPointerException(NULL_CAUSE_MESSAGE);
+                suppressed.add(t);
+            }
+        }
+        suppressedExceptions = suppressed;
+    }
+
+    private synchronized void writeObject(ObjectOutputStream s)
         throws IOException
     {
         getOurStackTrace();  // Ensure that stackTrace field is initialized.
         s.defaultWriteObject();
     }
+
+    /**
+     * Adds the specified exception to the list of exceptions that
+     * were suppressed, typically by the automatic resource management
+     * statement, in order to deliver this exception.
+     *
+     * @param exception the exception to be added to the list of
+     *        suppressed exceptions
+     * @throws NullPointerException if {@code exception} is null
+     * @since 1.7
+     */
+    public synchronized void addSuppressedException(Throwable exception) {
+        if (exception == null)
+            throw new NullPointerException(NULL_CAUSE_MESSAGE);
+
+        if (suppressedExceptions.size() == 0)
+            suppressedExceptions = new ArrayList<Throwable>();
+        suppressedExceptions.add(exception);
+    }
+
+    private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
+
+    /**
+     * Returns an array containing all of the exceptions that were
+     * suppressed, typically by the automatic resource management
+     * statement, in order to deliver this exception.
+     *
+     * @return an array containing all of the exceptions that were
+     *         suppressed to deliver this exception.
+     * @since 1.7
+     */
+    public Throwable[] getSuppressedExceptions() {
+        return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
+    }
 }
--- a/jdk/src/share/classes/java/net/Inet6Address.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/net/Inet6Address.java	Wed Jul 05 17:17:57 2017 +0200
@@ -427,8 +427,9 @@
                     try {
                         scope_id = deriveNumericScope (scope_ifname);
                     } catch (UnknownHostException e) {
-                        // should not happen
-                        assert false;
+                        // typically should not happen, but it may be that
+                        // the machine being used for deserialization has
+                        // the same interface name but without IPv6 configured.
                     }
                 }
             } catch (SocketException e) {}
--- a/jdk/src/share/classes/java/nio/Bits.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/nio/Bits.java	Wed Jul 05 17:17:57 2017 +0200
@@ -41,25 +41,19 @@
     // -- Swapping --
 
     static short swap(short x) {
-        return (short)((x << 8) |
-                       ((char)x >>> 8));
+        return Short.reverseBytes(x);
     }
 
     static char swap(char x) {
-        return (char)((x << 8) |
-                      (x >>> 8));
+        return Character.reverseBytes(x);
     }
 
     static int swap(int x) {
-        return ((x << 24) |
-                ((x & 0x0000ff00) <<  8) |
-                ((x & 0x00ff0000) >>> 8) |
-                (x >>> 24));
+        return Integer.reverseBytes(x);
     }
 
     static long swap(long x) {
-        return (((long)swap((int)x) << 32) |
-                ((long)swap((int)(x >>> 32)) & 0xffffffffL));
+        return Long.reverseBytes(x);
     }
 
 
@@ -71,52 +65,52 @@
 
     static char getCharL(ByteBuffer bb, int bi) {
         return makeChar(bb._get(bi + 1),
-                        bb._get(bi + 0));
+                        bb._get(bi    ));
     }
 
     static char getCharL(long a) {
         return makeChar(_get(a + 1),
-                        _get(a + 0));
+                        _get(a    ));
     }
 
     static char getCharB(ByteBuffer bb, int bi) {
-        return makeChar(bb._get(bi + 0),
+        return makeChar(bb._get(bi    ),
                         bb._get(bi + 1));
     }
 
     static char getCharB(long a) {
-        return makeChar(_get(a + 0),
+        return makeChar(_get(a    ),
                         _get(a + 1));
     }
 
     static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {
-        return (bigEndian ? getCharB(bb, bi) : getCharL(bb, bi));
+        return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi);
     }
 
     static char getChar(long a, boolean bigEndian) {
-        return (bigEndian ? getCharB(a) : getCharL(a));
+        return bigEndian ? getCharB(a) : getCharL(a);
     }
 
     private static byte char1(char x) { return (byte)(x >> 8); }
-    private static byte char0(char x) { return (byte)(x >> 0); }
+    private static byte char0(char x) { return (byte)(x     ); }
 
     static void putCharL(ByteBuffer bb, int bi, char x) {
-        bb._put(bi + 0, char0(x));
+        bb._put(bi    , char0(x));
         bb._put(bi + 1, char1(x));
     }
 
     static void putCharL(long a, char x) {
-        _put(a + 0, char0(x));
+        _put(a    , char0(x));
         _put(a + 1, char1(x));
     }
 
     static void putCharB(ByteBuffer bb, int bi, char x) {
-        bb._put(bi + 0, char1(x));
+        bb._put(bi    , char1(x));
         bb._put(bi + 1, char0(x));
     }
 
     static void putCharB(long a, char x) {
-        _put(a + 0, char1(x));
+        _put(a    , char1(x));
         _put(a + 1, char0(x));
     }
 
@@ -143,52 +137,52 @@
 
     static short getShortL(ByteBuffer bb, int bi) {
         return makeShort(bb._get(bi + 1),
-                         bb._get(bi + 0));
+                         bb._get(bi    ));
     }
 
     static short getShortL(long a) {
         return makeShort(_get(a + 1),
-                         _get(a));
+                         _get(a    ));
     }
 
     static short getShortB(ByteBuffer bb, int bi) {
-        return makeShort(bb._get(bi + 0),
+        return makeShort(bb._get(bi    ),
                          bb._get(bi + 1));
     }
 
     static short getShortB(long a) {
-        return makeShort(_get(a),
+        return makeShort(_get(a    ),
                          _get(a + 1));
     }
 
     static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
-        return (bigEndian ? getShortB(bb, bi) : getShortL(bb, bi));
+        return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);
     }
 
     static short getShort(long a, boolean bigEndian) {
-        return (bigEndian ? getShortB(a) : getShortL(a));
+        return bigEndian ? getShortB(a) : getShortL(a);
     }
 
     private static byte short1(short x) { return (byte)(x >> 8); }
-    private static byte short0(short x) { return (byte)(x >> 0); }
+    private static byte short0(short x) { return (byte)(x     ); }
 
     static void putShortL(ByteBuffer bb, int bi, short x) {
-        bb._put(bi + 0, short0(x));
+        bb._put(bi    , short0(x));
         bb._put(bi + 1, short1(x));
     }
 
     static void putShortL(long a, short x) {
-        _put(a, short0(x));
+        _put(a    , short0(x));
         _put(a + 1, short1(x));
     }
 
     static void putShortB(ByteBuffer bb, int bi, short x) {
-        bb._put(bi + 0, short1(x));
+        bb._put(bi    , short1(x));
         bb._put(bi + 1, short0(x));
     }
 
     static void putShortB(long a, short x) {
-        _put(a, short1(x));
+        _put(a    , short1(x));
         _put(a + 1, short0(x));
     }
 
@@ -210,76 +204,76 @@
     // -- get/put int --
 
     static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
-        return (((b3 & 0xff) << 24) |
+        return (((b3       ) << 24) |
                 ((b2 & 0xff) << 16) |
                 ((b1 & 0xff) <<  8) |
-                ((b0 & 0xff) <<  0));
+                ((b0 & 0xff)      ));
     }
 
     static int getIntL(ByteBuffer bb, int bi) {
         return makeInt(bb._get(bi + 3),
                        bb._get(bi + 2),
                        bb._get(bi + 1),
-                       bb._get(bi + 0));
+                       bb._get(bi    ));
     }
 
     static int getIntL(long a) {
         return makeInt(_get(a + 3),
                        _get(a + 2),
                        _get(a + 1),
-                       _get(a + 0));
+                       _get(a    ));
     }
 
     static int getIntB(ByteBuffer bb, int bi) {
-        return makeInt(bb._get(bi + 0),
+        return makeInt(bb._get(bi    ),
                        bb._get(bi + 1),
                        bb._get(bi + 2),
                        bb._get(bi + 3));
     }
 
     static int getIntB(long a) {
-        return makeInt(_get(a + 0),
+        return makeInt(_get(a    ),
                        _get(a + 1),
                        _get(a + 2),
                        _get(a + 3));
     }
 
     static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {
-        return (bigEndian ? getIntB(bb, bi) : getIntL(bb, bi));
+        return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ;
     }
 
     static int getInt(long a, boolean bigEndian) {
-        return (bigEndian ? getIntB(a) : getIntL(a));
+        return bigEndian ? getIntB(a) : getIntL(a) ;
     }
 
     private static byte int3(int x) { return (byte)(x >> 24); }
     private static byte int2(int x) { return (byte)(x >> 16); }
     private static byte int1(int x) { return (byte)(x >>  8); }
-    private static byte int0(int x) { return (byte)(x >>  0); }
+    private static byte int0(int x) { return (byte)(x      ); }
 
     static void putIntL(ByteBuffer bb, int bi, int x) {
         bb._put(bi + 3, int3(x));
         bb._put(bi + 2, int2(x));
         bb._put(bi + 1, int1(x));
-        bb._put(bi + 0, int0(x));
+        bb._put(bi    , int0(x));
     }
 
     static void putIntL(long a, int x) {
         _put(a + 3, int3(x));
         _put(a + 2, int2(x));
         _put(a + 1, int1(x));
-        _put(a + 0, int0(x));
+        _put(a    , int0(x));
     }
 
     static void putIntB(ByteBuffer bb, int bi, int x) {
-        bb._put(bi + 0, int3(x));
+        bb._put(bi    , int3(x));
         bb._put(bi + 1, int2(x));
         bb._put(bi + 2, int1(x));
         bb._put(bi + 3, int0(x));
     }
 
     static void putIntB(long a, int x) {
-        _put(a + 0, int3(x));
+        _put(a    , int3(x));
         _put(a + 1, int2(x));
         _put(a + 2, int1(x));
         _put(a + 3, int0(x));
@@ -305,14 +299,14 @@
     static private long makeLong(byte b7, byte b6, byte b5, byte b4,
                                  byte b3, byte b2, byte b1, byte b0)
     {
-        return ((((long)b7 & 0xff) << 56) |
+        return ((((long)b7       ) << 56) |
                 (((long)b6 & 0xff) << 48) |
                 (((long)b5 & 0xff) << 40) |
                 (((long)b4 & 0xff) << 32) |
                 (((long)b3 & 0xff) << 24) |
                 (((long)b2 & 0xff) << 16) |
                 (((long)b1 & 0xff) <<  8) |
-                (((long)b0 & 0xff) <<  0));
+                (((long)b0 & 0xff)      ));
     }
 
     static long getLongL(ByteBuffer bb, int bi) {
@@ -323,7 +317,7 @@
                         bb._get(bi + 3),
                         bb._get(bi + 2),
                         bb._get(bi + 1),
-                        bb._get(bi + 0));
+                        bb._get(bi    ));
     }
 
     static long getLongL(long a) {
@@ -334,11 +328,11 @@
                         _get(a + 3),
                         _get(a + 2),
                         _get(a + 1),
-                        _get(a + 0));
+                        _get(a    ));
     }
 
     static long getLongB(ByteBuffer bb, int bi) {
-        return makeLong(bb._get(bi + 0),
+        return makeLong(bb._get(bi    ),
                         bb._get(bi + 1),
                         bb._get(bi + 2),
                         bb._get(bi + 3),
@@ -349,7 +343,7 @@
     }
 
     static long getLongB(long a) {
-        return makeLong(_get(a + 0),
+        return makeLong(_get(a    ),
                         _get(a + 1),
                         _get(a + 2),
                         _get(a + 3),
@@ -360,11 +354,11 @@
     }
 
     static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {
-        return (bigEndian ? getLongB(bb, bi) : getLongL(bb, bi));
+        return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi);
     }
 
     static long getLong(long a, boolean bigEndian) {
-        return (bigEndian ? getLongB(a) : getLongL(a));
+        return bigEndian ? getLongB(a) : getLongL(a);
     }
 
     private static byte long7(long x) { return (byte)(x >> 56); }
@@ -374,7 +368,7 @@
     private static byte long3(long x) { return (byte)(x >> 24); }
     private static byte long2(long x) { return (byte)(x >> 16); }
     private static byte long1(long x) { return (byte)(x >>  8); }
-    private static byte long0(long x) { return (byte)(x >>  0); }
+    private static byte long0(long x) { return (byte)(x      ); }
 
     static void putLongL(ByteBuffer bb, int bi, long x) {
         bb._put(bi + 7, long7(x));
@@ -384,7 +378,7 @@
         bb._put(bi + 3, long3(x));
         bb._put(bi + 2, long2(x));
         bb._put(bi + 1, long1(x));
-        bb._put(bi + 0, long0(x));
+        bb._put(bi    , long0(x));
     }
 
     static void putLongL(long a, long x) {
@@ -395,11 +389,11 @@
         _put(a + 3, long3(x));
         _put(a + 2, long2(x));
         _put(a + 1, long1(x));
-        _put(a + 0, long0(x));
+        _put(a    , long0(x));
     }
 
     static void putLongB(ByteBuffer bb, int bi, long x) {
-        bb._put(bi + 0, long7(x));
+        bb._put(bi    , long7(x));
         bb._put(bi + 1, long6(x));
         bb._put(bi + 2, long5(x));
         bb._put(bi + 3, long4(x));
@@ -410,7 +404,7 @@
     }
 
     static void putLongB(long a, long x) {
-        _put(a + 0, long7(x));
+        _put(a    , long7(x));
         _put(a + 1, long6(x));
         _put(a + 2, long5(x));
         _put(a + 3, long4(x));
@@ -454,11 +448,11 @@
     }
 
     static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {
-        return (bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi));
+        return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi);
     }
 
     static float getFloat(long a, boolean bigEndian) {
-        return (bigEndian ? getFloatB(a) : getFloatL(a));
+        return bigEndian ? getFloatB(a) : getFloatL(a);
     }
 
     static void putFloatL(ByteBuffer bb, int bi, float x) {
@@ -511,11 +505,11 @@
     }
 
     static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {
-        return (bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi));
+        return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi);
     }
 
     static double getDouble(long a, boolean bigEndian) {
-        return (bigEndian ? getDoubleB(a) : getDoubleL(a));
+        return bigEndian ? getDoubleB(a) : getDoubleL(a);
     }
 
     static void putDoubleL(ByteBuffer bb, int bi, double x) {
@@ -794,7 +788,7 @@
     static native void copyFromIntArray(Object src, long srcPos, long dstAddr,
                                         long length);
     static native void copyToIntArray(long srcAddr, Object dst, long dstPos,
-                                        long length);
+                                      long length);
 
     static native void copyFromLongArray(Object src, long srcPos, long dstAddr,
                                          long length);
--- a/jdk/src/share/classes/java/nio/channels/FileLock.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/nio/channels/FileLock.java	Wed Jul 05 17:17:57 2017 +0200
@@ -116,7 +116,7 @@
  * @since 1.4
  */
 
-public abstract class FileLock {
+public abstract class FileLock implements AutoCloseable {
 
     private final Channel channel;
     private final long position;
@@ -299,6 +299,17 @@
     public abstract void release() throws IOException;
 
     /**
+     * This method invokes the {@link #release} method. It was added
+     * to the class so that it could be used in conjunction with the
+     * automatic resource management block construct.
+     *
+     * @since 1.7
+     */
+    public final void close() throws IOException {
+        release();
+    }
+
+    /**
      * Returns a string describing the range, type, and validity of this lock.
      *
      * @return  A descriptive string
--- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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
@@ -27,7 +27,7 @@
 
 /**
  * This class implements the Dual-Pivot Quicksort algorithm by
- * Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. The algorithm
+ * Vladimir Yaroslavskiy, Jon Bentley, and Josh Bloch. The algorithm
  * offers O(n log(n)) performance on many data sets that cause other
  * quicksorts to degrade to quadratic performance, and is typically
  * faster than traditional (one-pivot) Quicksort implementations.
@@ -36,7 +36,8 @@
  * @author Jon Bentley
  * @author Josh Bloch
  *
- * @version 2009.11.29 m765.827.12i
+ * @version 2010.06.21 m765.827.12i:5\7
+ * @since 1.7
  */
 final class DualPivotQuicksort {
 
@@ -68,7 +69,7 @@
     private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
 
     /*
-     * Sorting methods for 7 primitive types.
+     * Sorting methods for seven primitive types.
      */
 
     /**
@@ -77,7 +78,7 @@
      * @param a the array to be sorted
      */
     public static void sort(int[] a) {
-        doSort(a, 0, a.length - 1);
+        sort(a, 0, a.length - 1, true);
     }
 
     /**
@@ -95,98 +96,132 @@
      */
     public static void sort(int[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        doSort(a, fromIndex, toIndex - 1);
+        sort(a, fromIndex, toIndex - 1, true);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in that the
-     * {@code right} index is inclusive, and it does no range checking
-     * on {@code left} or {@code right}.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
      */
-    private static void doSort(int[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                int ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
+    private static void sort(int[] a, int left, int right, boolean leftmost) {
+        int length = right - left + 1;
 
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void dualPivotQuicksort(int[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    int ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    int ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
+
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
         int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
 
-        // Sort these elements using a 5-element sorting network
-        int ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { int t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
 
-        if (ae1 > ae2) { int t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { int t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { int t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { int t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { int t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; }
-
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        if (a[e3] < a[e2]) { int t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { int t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { int t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        int pivot1 = ae2; a[e2] = a[left];
-        int pivot2 = ae4; a[e4] = a[right];
+        int pivot1 = a[e2];
+        int pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -194,16 +229,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 int ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -213,26 +246,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    int ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = pivot1;
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -240,20 +354,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                int ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                int ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -261,92 +374,33 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
                         a[k] = pivot1;
-                        a[great--] = ak;
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                int ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
@@ -355,7 +409,7 @@
      * @param a the array to be sorted
      */
     public static void sort(long[] a) {
-        doSort(a, 0, a.length - 1);
+        sort(a, 0, a.length - 1, true);
     }
 
     /**
@@ -373,98 +427,132 @@
      */
     public static void sort(long[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        doSort(a, fromIndex, toIndex - 1);
+        sort(a, fromIndex, toIndex - 1, true);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in that the
-     * {@code right} index is inclusive, and it does no range checking on
-     * {@code left} or {@code right}.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
      */
-    private static void doSort(long[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                long ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
+    private static void sort(long[] a, int left, int right, boolean leftmost) {
+        int length = right - left + 1;
 
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void dualPivotQuicksort(long[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    long ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    long ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
+
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
         int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
 
-        // Sort these elements using a 5-element sorting network
-        long ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { long t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
 
-        if (ae1 > ae2) { long t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { long t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { long t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { long t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { long t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; }
-
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        if (a[e3] < a[e2]) { long t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { long t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { long t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        long pivot1 = ae2; a[e2] = a[left];
-        long pivot2 = ae4; a[e4] = a[right];
+        long pivot1 = a[e2];
+        long pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -472,16 +560,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 long ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -491,26 +577,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    long ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = pivot1;
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -518,20 +685,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                long ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                long ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -539,92 +705,33 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
                         a[k] = pivot1;
-                        a[great--] = ak;
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                long ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
@@ -633,7 +740,11 @@
      * @param a the array to be sorted
      */
     public static void sort(short[] a) {
-        doSort(a, 0, a.length - 1);
+        if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            countingSort(a, 0, a.length - 1);
+        } else {
+            sort(a, 0, a.length - 1, true);
+        }
     }
 
     /**
@@ -651,115 +762,166 @@
      */
     public static void sort(short[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        doSort(a, fromIndex, toIndex - 1);
+
+        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            countingSort(a, fromIndex, toIndex - 1);
+        } else {
+            sort(a, fromIndex, toIndex - 1, true);
+        }
     }
 
     /** The number of distinct short values. */
     private static final int NUM_SHORT_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in that the
-     * {@code right} index is inclusive, and it does no range checking on
-     * {@code left} or {@code right}.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void doSort(short[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                short ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            // Use counting sort on huge arrays
-            int[] count = new int[NUM_SHORT_VALUES];
-
-            for (int i = left; i <= right; i++) {
-                count[a[i] - Short.MIN_VALUE]++;
-            }
-            for (int i = 0, k = left; i < count.length && k <= right; i++) {
-                short value = (short) (i + Short.MIN_VALUE);
-
-                for (int s = count[i]; s > 0; s--) {
-                    a[k++] = value;
-               }
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
+     * Sorts the specified range of the array by counting sort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void dualPivotQuicksort(short[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+    private static void countingSort(short[] a, int left, int right) {
+        int[] count = new int[NUM_SHORT_VALUES];
+
+        for (int i = left; i <= right; i++) {
+            count[a[i] - Short.MIN_VALUE]++;
+        }
+        for (int i = NUM_SHORT_VALUES - 1, k = right; k >= left; i--) {
+            while (count[i] == 0) {
+                i--;
+            }
+            short value = (short) (i + Short.MIN_VALUE);
+            int s = count[i];
 
-        // Sort these elements using a 5-element sorting network
-        short ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+            do {
+                a[k--] = value;
+            } while (--s > 0);
+        }
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
+     */
+    private static void sort(short[] a, int left, int right,boolean leftmost) {
+        int length = right - left + 1;
 
-        if (ae1 > ae2) { short t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { short t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { short t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { short t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { short t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; }
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    short ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    short ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
 
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
+        int e3 = (left + right) >>> 1; // The midpoint
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
+
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { short t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+        if (a[e3] < a[e2]) { short t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { short t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { short t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        short pivot1 = ae2; a[e2] = a[left];
-        short pivot2 = ae4; a[e4] = a[right];
+        short pivot1 = a[e2];
+        short pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -767,16 +929,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 short ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -786,26 +946,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    short ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = pivot1;
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -813,20 +1054,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                short ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                short ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -834,92 +1074,33 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
                         a[k] = pivot1;
-                        a[great--] = ak;
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                short ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
@@ -928,7 +1109,11 @@
      * @param a the array to be sorted
      */
     public static void sort(char[] a) {
-        doSort(a, 0, a.length - 1);
+        if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            countingSort(a, 0, a.length - 1);
+        } else {
+            sort(a, 0, a.length - 1, true);
+        }
     }
 
     /**
@@ -946,113 +1131,166 @@
      */
     public static void sort(char[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        doSort(a, fromIndex, toIndex - 1);
+
+        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+            countingSort(a, fromIndex, toIndex - 1);
+        } else {
+            sort(a, fromIndex, toIndex - 1, true);
+        }
     }
 
     /** The number of distinct char values. */
     private static final int NUM_CHAR_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in that the
-     * {@code right} index is inclusive, and it does no range checking on
-     * {@code left} or {@code right}.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void doSort(char[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                char ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
-            // Use counting sort on huge arrays
-            int[] count = new int[NUM_CHAR_VALUES];
-
-            for (int i = left; i <= right; i++) {
-                count[a[i]]++;
-            }
-            for (int i = 0, k = left; i < count.length && k <= right; i++) {
-                for (int s = count[i]; s > 0; s--) {
-                    a[k++] = (char) i;
-               }
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
+     * Sorts the specified range of the array by counting sort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void dualPivotQuicksort(char[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+    private static void countingSort(char[] a, int left, int right) {
+        int[] count = new int[NUM_CHAR_VALUES];
+
+        for (int i = left; i <= right; i++) {
+            count[a[i]]++;
+        }
+        for (int i = 0, k = left; k <= right; i++) {
+            while (count[i] == 0) {
+                i++;
+            }
+            char value = (char) i;
+            int s = count[i];
 
-        // Sort these elements using a 5-element sorting network
-        char ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+            do {
+                a[k++] = value;
+            } while (--s > 0);
+        }
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
+     */
+    private static void sort(char[] a, int left, int right, boolean leftmost) {
+        int length = right - left + 1;
 
-        if (ae1 > ae2) { char t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { char t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { char t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { char t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { char t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; }
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    char ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    char ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
 
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
+        int e3 = (left + right) >>> 1; // The midpoint
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
+
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { char t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+        if (a[e3] < a[e2]) { char t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { char t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { char t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        char pivot1 = ae2; a[e2] = a[left];
-        char pivot2 = ae4; a[e4] = a[right];
+        char pivot1 = a[e2];
+        char pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -1060,16 +1298,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 char ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -1079,26 +1315,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    char ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = pivot1;
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -1106,20 +1423,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                char ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                char ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -1127,92 +1443,33 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
                         a[k] = pivot1;
-                        a[great--] = ak;
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                char ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
@@ -1221,7 +1478,11 @@
      * @param a the array to be sorted
      */
     public static void sort(byte[] a) {
-        doSort(a, 0, a.length - 1);
+        if (a.length > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+            countingSort(a, 0, a.length - 1);
+        } else {
+            sort(a, 0, a.length - 1, true);
+        }
     }
 
     /**
@@ -1239,115 +1500,166 @@
      */
     public static void sort(byte[] a, int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
-        doSort(a, fromIndex, toIndex - 1);
+
+        if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+            countingSort(a, fromIndex, toIndex - 1);
+        } else {
+            sort(a, fromIndex, toIndex - 1, true);
+        }
     }
 
     /** The number of distinct byte values. */
     private static final int NUM_BYTE_VALUES = 1 << 8;
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in that the
-     * {@code right} index is inclusive, and it does no range checking on
-     * {@code left} or {@code right}.
-     *
-     * @param a the array to be sorted
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void doSort(byte[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                byte ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
-            // Use counting sort on huge arrays
-            int[] count = new int[NUM_BYTE_VALUES];
-
-            for (int i = left; i <= right; i++) {
-                count[a[i] - Byte.MIN_VALUE]++;
-            }
-            for (int i = 0, k = left; i < count.length && k <= right; i++) {
-                byte value = (byte) (i + Byte.MIN_VALUE);
-
-                for (int s = count[i]; s > 0; s--) {
-                    a[k++] = value;
-               }
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
-
-    /**
-     * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
+     * Sorts the specified range of the array by counting sort.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
      */
-    private static void dualPivotQuicksort(byte[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+    private static void countingSort(byte[] a, int left, int right) {
+        int[] count = new int[NUM_BYTE_VALUES];
+
+        for (int i = left; i <= right; i++) {
+            count[a[i] - Byte.MIN_VALUE]++;
+        }
+        for (int i = NUM_BYTE_VALUES - 1, k = right; k >= left; i--) {
+            while (count[i] == 0) {
+                i--;
+            }
+            byte value = (byte) (i + Byte.MIN_VALUE);
+            int s = count[i];
 
-        // Sort these elements using a 5-element sorting network
-        byte ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+            do {
+                a[k--] = value;
+            } while (--s > 0);
+        }
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
+     */
+    private static void sort(byte[] a, int left, int right, boolean leftmost) {
+        int length = right - left + 1;
 
-        if (ae1 > ae2) { byte t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { byte t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { byte t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { byte t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { byte t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; }
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    byte ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    byte ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
 
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
+        int e3 = (left + right) >>> 1; // The midpoint
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
+
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { byte t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+        if (a[e3] < a[e2]) { byte t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { byte t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { byte t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        byte pivot1 = ae2; a[e2] = a[left];
-        byte pivot2 = ae4; a[e4] = a[right];
+        byte pivot1 = a[e2];
+        byte pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -1355,16 +1667,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 byte ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -1374,26 +1684,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    byte ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = pivot1;
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -1401,20 +1792,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                byte ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                byte ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -1422,92 +1812,33 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
                         a[k] = pivot1;
-                        a[great--] = ak;
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                byte ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
@@ -1531,7 +1862,7 @@
      * Sorts the specified range of the array into ascending order. The range
      * to be sorted extends from the index {@code fromIndex}, inclusive, to
      * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty and the call is a no-op).
+     * the range to be sorted is empty (and the call is a no-op).
      *
      * <p>The {@code <} relation does not provide a total order on all float
      * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
@@ -1565,162 +1896,207 @@
      */
     private static void sortNegZeroAndNaN(float[] a, int left, int right) {
         /*
-         * Phase 1: Count negative zeros and move NaNs to end of array
+         * Phase 1: Move NaNs to the end of the array.
          */
-        final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
-        int numNegativeZeros = 0;
-        int n = right;
-
-        for (int k = left; k <= n; k++) {
+        while (left <= right && Float.isNaN(a[right])) {
+            right--;
+        }
+        for (int k = right - 1; k >= left; k--) {
             float ak = a[k];
-            if (ak == 0.0f && NEGATIVE_ZERO == Float.floatToIntBits(ak)) {
-                a[k] = 0.0f;
-                numNegativeZeros++;
-            } else if (ak != ak) { // i.e., ak is NaN
-                a[k--] = a[n];
-                a[n--] = Float.NaN;
+            if (ak != ak) { // a[k] is NaN
+                a[k] = a[right];
+                a[right] = ak;
+                right--;
             }
         }
 
         /*
-         * Phase 2: Sort everything except NaNs (which are already in place)
+         * Phase 2: Sort everything except NaNs (which are already in place).
          */
-        doSort(a, left, n);
+        sort(a, left, right, true);
 
         /*
-         * Phase 3: Turn positive zeros back into negative zeros as appropriate
+         * Phase 3: Place negative zeros before positive zeros.
          */
-        if (numNegativeZeros == 0) {
-            return;
-        }
-
-        // Find first zero element
-        int zeroIndex = findAnyZero(a, left, n);
-
-        for (int i = zeroIndex - 1; i >= left && a[i] == 0.0f; i--) {
-            zeroIndex = i;
-        }
+        int hi = right;
 
-        // Turn the right number of positive zeros back into negative zeros
-        for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
-            a[i] = -0.0f;
-        }
-    }
-
-    /**
-     * Returns the index of some zero element in the specified range via
-     * binary search. The range is assumed to be sorted, and must contain
-     * at least one zero.
-     *
-     * @param a the array to be searched
-     * @param low the index of the first element, inclusive, to be searched
-     * @param high the index of the last element, inclusive, to be searched
-     */
-    private static int findAnyZero(float[] a, int low, int high) {
-        while (true) {
-            int middle = (low + high) >>> 1;
+        /*
+         * Search first zero, or first positive, or last negative element.
+         */
+        while (left < hi) {
+            int middle = (left + hi) >>> 1;
             float middleValue = a[middle];
 
             if (middleValue < 0.0f) {
-                low = middle + 1;
-            } else if (middleValue > 0.0f) {
-                high = middle - 1;
-            } else { // middleValue == 0.0f
-                return middle;
+                left = middle + 1;
+            } else {
+                hi = middle;
+            }
+        }
+
+        /*
+         * Skip the last negative value (if any) or all leading negative zeros.
+         */
+        while (left <= right && Float.floatToRawIntBits(a[left]) < 0) {
+            left++;
+        }
+
+        /*
+         * Move negative zeros to the beginning of the sub-range.
+         *
+         * Partitioning:
+         *
+         * +---------------------------------------------------+
+         * |   < 0.0   |   -0.0   |    0.0    |  ?  ( >= 0.0 ) |
+         * +---------------------------------------------------+
+         *              ^          ^           ^
+         *              |          |           |
+         *             left        p           k
+         *
+         * Invariants:
+         *
+         *   all in (*,  left)  <  0.0
+         *   all in [left,  p) == -0.0
+         *   all in [p,     k) ==  0.0
+         *   all in [k, right] >=  0.0
+         *
+         * Pointer k is the first index of ?-part.
+         */
+        for (int k = left + 1, p = left; k <= right; k++) {
+            float ak = a[k];
+            if (ak != 0.0f) {
+                break;
+            }
+            if (Float.floatToRawIntBits(ak) < 0) { // ak is -0.0f
+                a[k] = 0.0f;
+                a[p++] = -0.0f;
             }
         }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in three ways:
-     * {@code right} index is inclusive, it does no range checking on
-     * {@code left} or {@code right}, and it does not handle negative
-     * zeros or NaNs in the array.
-     *
-     * @param a the array to be sorted, which must not contain -0.0f or NaN
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void doSort(float[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                float ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
-
-    /**
      * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
      */
-    private static void dualPivotQuicksort(float[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+    private static void sort(float[] a, int left, int right,boolean leftmost) {
+        int length = right - left + 1;
 
-        // Sort these elements using a 5-element sorting network
-        float ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    float ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    float ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
 
-        if (ae1 > ae2) { float t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { float t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { float t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { float t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { float t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; }
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
+        int e3 = (left + right) >>> 1; // The midpoint
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
 
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { float t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+        if (a[e3] < a[e2]) { float t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { float t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { float t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        float pivot1 = ae2; a[e2] = a[left];
-        float pivot2 = ae4; a[e4] = a[right];
+        float pivot1 = a[e2];
+        float pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -1728,16 +2104,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 float ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -1747,26 +2121,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    float ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = a[great];
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -1774,20 +2229,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                float ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                float ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -1795,92 +2249,33 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
-                        a[k] = pivot1;
-                        a[great--] = ak;
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
+                        a[k] = a[great];
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                float ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
@@ -1938,162 +2333,207 @@
      */
     private static void sortNegZeroAndNaN(double[] a, int left, int right) {
         /*
-         * Phase 1: Count negative zeros and move NaNs to end of array
+         * Phase 1: Move NaNs to the end of the array.
          */
-        final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
-        int numNegativeZeros = 0;
-        int n = right;
-
-        for (int k = left; k <= n; k++) {
+        while (left <= right && Double.isNaN(a[right])) {
+            right--;
+        }
+        for (int k = right - 1; k >= left; k--) {
             double ak = a[k];
-            if (ak == 0.0d && NEGATIVE_ZERO == Double.doubleToLongBits(ak)) {
-                a[k] = 0.0d;
-                numNegativeZeros++;
-            } else if (ak != ak) { // i.e., ak is NaN
-                a[k--] = a[n];
-                a[n--] = Double.NaN;
+            if (ak != ak) { // a[k] is NaN
+                a[k] = a[right];
+                a[right] = ak;
+                right--;
             }
         }
 
         /*
-         * Phase 2: Sort everything except NaNs (which are already in place)
+         * Phase 2: Sort everything except NaNs (which are already in place).
          */
-        doSort(a, left, n);
+        sort(a, left, right, true);
 
         /*
-         * Phase 3: Turn positive zeros back into negative zeros as appropriate
+         * Phase 3: Place negative zeros before positive zeros.
          */
-        if (numNegativeZeros == 0) {
-            return;
-        }
-
-        // Find first zero element
-        int zeroIndex = findAnyZero(a, left, n);
-
-        for (int i = zeroIndex - 1; i >= left && a[i] == 0.0d; i--) {
-            zeroIndex = i;
-        }
+        int hi = right;
 
-        // Turn the right number of positive zeros back into negative zeros
-        for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
-            a[i] = -0.0d;
-        }
-    }
-
-    /**
-     * Returns the index of some zero element in the specified range via
-     * binary search. The range is assumed to be sorted, and must contain
-     * at least one zero.
-     *
-     * @param a the array to be searched
-     * @param low the index of the first element, inclusive, to be searched
-     * @param high the index of the last element, inclusive, to be searched
-     */
-    private static int findAnyZero(double[] a, int low, int high) {
-        while (true) {
-            int middle = (low + high) >>> 1;
+        /*
+         * Search first zero, or first positive, or last negative element.
+         */
+        while (left < hi) {
+            int middle = (left + hi) >>> 1;
             double middleValue = a[middle];
 
             if (middleValue < 0.0d) {
-                low = middle + 1;
-            } else if (middleValue > 0.0d) {
-                high = middle - 1;
-            } else { // middleValue == 0.0d
-                return middle;
+                left = middle + 1;
+            } else {
+                hi = middle;
+            }
+        }
+
+        /*
+         * Skip the last negative value (if any) or all leading negative zeros.
+         */
+        while (left <= right && Double.doubleToRawLongBits(a[left]) < 0) {
+            left++;
+        }
+
+        /*
+         * Move negative zeros to the beginning of the sub-range.
+         *
+         * Partitioning:
+         *
+         * +---------------------------------------------------+
+         * |   < 0.0   |   -0.0   |    0.0    |  ?  ( >= 0.0 ) |
+         * +---------------------------------------------------+
+         *              ^          ^           ^
+         *              |          |           |
+         *             left        p           k
+         *
+         * Invariants:
+         *
+         *   all in (*,  left)  <  0.0
+         *   all in [left,  p) == -0.0
+         *   all in [p,     k) ==  0.0
+         *   all in [k, right] >=  0.0
+         *
+         * Pointer k is the first index of ?-part.
+         */
+        for (int k = left + 1, p = left; k <= right; k++) {
+            double ak = a[k];
+            if (ak != 0.0d) {
+                break;
+            }
+            if (Double.doubleToRawLongBits(ak) < 0) { // ak is -0.0d
+                a[k] = 0.0d;
+                a[p++] = -0.0d;
             }
         }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order. This
-     * method differs from the public {@code sort} method in three ways:
-     * {@code right} index is inclusive, it does no range checking on
-     * {@code left} or {@code right}, and it does not handle negative
-     * zeros or NaNs in the array.
-     *
-     * @param a the array to be sorted, which must not contain -0.0d and NaN
-     * @param left the index of the first element, inclusive, to be sorted
-     * @param right the index of the last element, inclusive, to be sorted
-     */
-    private static void doSort(double[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int i = left + 1; i <= right; i++) {
-                double ai = a[i];
-                int j;
-                for (j = i - 1; j >= left && ai < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ai;
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
-    }
-
-    /**
      * Sorts the specified range of the array into ascending order by the
-     * Dual-Pivot Quicksort algorithm.
+     * Dual-Pivot Quicksort algorithm. This method differs from the public
+     * {@code sort} method in that the {@code right} index is inclusive,
+     * it does no range checking on {@code left} or {@code right}, and has
+     * boolean flag whether insertion sort with sentinel is used or not.
      *
      * @param a the array to be sorted
      * @param left the index of the first element, inclusive, to be sorted
      * @param right the index of the last element, inclusive, to be sorted
+     * @param leftmost indicates if the part is the most left in the range
      */
-    private static void dualPivotQuicksort(double[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
+    private static void sort(double[] a, int left,int right,boolean leftmost) {
+        int length = right - left + 1;
 
-        // Sort these elements using a 5-element sorting network
-        double ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
+        // Use insertion sort on tiny arrays
+        if (length < INSERTION_SORT_THRESHOLD) {
+            if (!leftmost) {
+                /*
+                 * Every element in adjoining part plays the role
+                 * of sentinel, therefore this allows us to avoid
+                 * the j >= left check on each iteration.
+                 */
+                for (int j, i = left + 1; i <= right; i++) {
+                    double ai = a[i];
+                    for (j = i - 1; ai < a[j]; j--) {
+                        // assert j >= left;
+                        a[j + 1] = a[j];
+                    }
+                    a[j + 1] = ai;
+                }
+            } else {
+                /*
+                 * For case of leftmost part traditional (without a sentinel)
+                 * insertion sort, optimized for server JVM, is used.
+                 */
+                for (int i = left, j = i; i < right; j = ++i) {
+                    double ai = a[i + 1];
+                    while (ai < a[j]) {
+                        a[j + 1] = a[j];
+                        if (j-- == left) {
+                            break;
+                        }
+                    }
+                    a[j + 1] = ai;
+                }
+            }
+            return;
+        }
 
-        if (ae1 > ae2) { double t = ae1; ae1 = ae2; ae2 = t; }
-        if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; }
-        if (ae1 > ae3) { double t = ae1; ae1 = ae3; ae3 = t; }
-        if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae1 > ae4) { double t = ae1; ae1 = ae4; ae4 = t; }
-        if (ae3 > ae4) { double t = ae3; ae3 = ae4; ae4 = t; }
-        if (ae2 > ae5) { double t = ae2; ae2 = ae5; ae5 = t; }
-        if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; }
-        if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; }
+        // Inexpensive approximation of length / 7
+        int seventh = (length >>> 3) + (length >>> 6) + 1;
+
+        /*
+         * Sort five evenly spaced elements around (and including) the
+         * center element in the range. These elements will be used for
+         * pivot selection as described below. The choice for spacing
+         * these elements was empirically determined to work well on
+         * a wide variety of inputs.
+         */
+        int e3 = (left + right) >>> 1; // The midpoint
+        int e2 = e3 - seventh;
+        int e1 = e2 - seventh;
+        int e4 = e3 + seventh;
+        int e5 = e4 + seventh;
 
-        a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
+        // Sort these elements using insertion sort
+        if (a[e2] < a[e1]) { double t = a[e2]; a[e2] = a[e1]; a[e1] = t; }
+
+        if (a[e3] < a[e2]) { double t = a[e3]; a[e3] = a[e2]; a[e2] = t;
+            if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+        }
+        if (a[e4] < a[e3]) { double t = a[e4]; a[e4] = a[e3]; a[e3] = t;
+            if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+            }
+        }
+        if (a[e5] < a[e4]) { double t = a[e5]; a[e5] = a[e4]; a[e4] = t;
+            if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;
+                if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;
+                    if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }
+                }
+            }
+        }
 
         /*
          * Use the second and fourth of the five sorted elements as pivots.
          * These values are inexpensive approximations of the first and
          * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the elements to be sorted are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
          */
-        double pivot1 = ae2; a[e2] = a[left];
-        double pivot2 = ae4; a[e4] = a[right];
+        double pivot1 = a[e2];
+        double pivot2 = a[e4];
 
         // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
+        int less  = left;  // The index of the first element of center part
+        int great = right; // The index before the first element of right part
 
-        boolean pivotsDiffer = (pivot1 != pivot2);
+        if (pivot1 != pivot2) {
+            /*
+             * The first and the last elements to be sorted are moved to the
+             * locations formerly occupied by the pivots. When partitioning
+             * is complete, the pivots are swapped back into their final
+             * positions, and excluded from subsequent sorting.
+             */
+            a[e2] = a[left];
+            a[e4] = a[right];
 
-        if (pivotsDiffer) {
+            /*
+             * Skip elements, which are less or greater than pivot values.
+             */
+            while (a[++less] < pivot1);
+            while (a[--great] > pivot2);
+
             /*
              * Partitioning:
              *
-             *   left part         center part                    right part
-             * +------------------------------------------------------------+
-             * | < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2 |
-             * +------------------------------------------------------------+
-             *              ^                          ^       ^
-             *              |                          |       |
-             *             less                        k     great
+             *   left part           center part                   right part
+             * +--------------------------------------------------------------+
+             * |  < pivot1  |  pivot1 <= && <= pivot2  |    ?    |  > pivot2  |
+             * +--------------------------------------------------------------+
+             *               ^                          ^       ^
+             *               |                          |       |
+             *              less                        k     great
              *
              * Invariants:
              *
@@ -2101,16 +2541,14 @@
              *    pivot1 <= all in [less, k)     <= pivot2
              *              all in (great, right) > pivot2
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
             outer:
             for (int k = less; k <= great; k++) {
                 double ak = a[k];
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
                 } else if (ak > pivot2) { // Move a[k] to right part
                     while (a[great] > pivot2) {
@@ -2120,26 +2558,107 @@
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // pivot1 <= a[great] <= pivot2
                         a[k] = a[great];
-                        a[great--] = ak;
+                    }
+                    a[great] = ak;
+                    great--;
+                }
+            }
+
+            // Swap pivots into their final positions
+            a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+            a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+            // Sort left and right parts recursively, excluding known pivots
+            sort(a, left, less - 2, leftmost);
+            sort(a, great + 2, right, false);
+
+            /*
+             * If center part is too large (comprises > 5/7 of the array),
+             * swap internal pivot values to ends.
+             */
+            if (less < e1 && e5 < great) {
+                /*
+                 * Skip elements, which are equal to pivot values.
+                 */
+                while (a[less] == pivot1) {
+                    less++;
+                }
+                while (a[great] == pivot2) {
+                    great--;
+                }
+
+                /*
+                 * Partitioning:
+                 *
+                 *   left part         center part                  right part
+                 * +----------------------------------------------------------+
+                 * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
+                 * +----------------------------------------------------------+
+                 *              ^                        ^       ^
+                 *              |                        |       |
+                 *             less                      k     great
+                 *
+                 * Invariants:
+                 *
+                 *              all in (*,  less) == pivot1
+                 *     pivot1 < all in [less,  k)  < pivot2
+                 *              all in (great, *) == pivot2
+                 *
+                 * Pointer k is the first index of ?-part.
+                 */
+                outer:
+                for (int k = less; k <= great; k++) {
+                    double ak = a[k];
+                    if (ak == pivot1) { // Move a[k] to left part
+                        a[k] = a[less];
+                        a[less] = ak;
+                        less++;
+                    } else if (ak == pivot2) { // Move a[k] to right part
+                        while (a[great] == pivot2) {
+                            if (great-- == k) {
+                                break outer;
+                            }
+                        }
+                        if (a[great] == pivot1) {
+                            a[k] = a[less];
+                            /*
+                             * Even though a[great] equals to pivot1, the
+                             * assignment a[less] = pivot1 may be incorrect,
+                             * if a[great] and pivot1 are floating-point zeros
+                             * of different signs. Therefore in float and
+                             * double sorting methods we have to use more
+                             * accurate assignment a[less] = a[great].
+                             */
+                            a[less] = a[great];
+                            less++;
+                        } else { // pivot1 < a[great] < pivot2
+                            a[k] = a[great];
+                        }
+                        a[great] = ak;
+                        great--;
                     }
                 }
             }
+
+            // Sort center part recursively
+            sort(a, less, great, false);
+
         } else { // Pivots are equal
             /*
-             * Partition degenerates to the traditional 3-way,
-             * or "Dutch National Flag", partition:
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") schema:
              *
-             *   left part   center part            right part
-             * +----------------------------------------------+
-             * |  < pivot  |  == pivot  |    ?    |  > pivot  |
-             * +----------------------------------------------+
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
+             *   left part    center part              right part
+             * +-------------------------------------------------+
+             * |  < pivot  |   == pivot   |     ?    |  > pivot  |
+             * +-------------------------------------------------+
+             *              ^              ^        ^
+             *              |              |        |
+             *             less            k      great
              *
              * Invariants:
              *
@@ -2147,20 +2666,19 @@
              *   all in [less, k)     == pivot
              *   all in (great, right) > pivot
              *
-             * Pointer k is the first index of ?-part
+             * Pointer k is the first index of ?-part.
              */
-            for (int k = less; k <= great; k++) {
-                double ak = a[k];
-                if (ak == pivot1) {
+            for (int k = left; k <= great; k++) {
+                if (a[k] == pivot1) {
                     continue;
                 }
+                double ak = a[k];
+
                 if (ak < pivot1) { // Move a[k] to left part
-                    if (k != less) {
-                        a[k] = a[less];
-                        a[less] = ak;
-                    }
+                    a[k] = a[less];
+                    a[less] = ak;
                     less++;
-                } else { // (a[k] > pivot1) - Move a[k] to right part
+                } else { // a[k] > pivot1 - Move a[k] to right part
                     /*
                      * We know that pivot1 == a[e3] == pivot2. Thus, we know
                      * that great will still be >= k when the following loop
@@ -2168,102 +2686,43 @@
                      * In other words, a[e3] acts as a sentinel for great.
                      */
                     while (a[great] > pivot1) {
+                        // assert great > k;
                         great--;
                     }
                     if (a[great] < pivot1) {
                         a[k] = a[less];
-                        a[less++] = a[great];
-                        a[great--] = ak;
+                        a[less] = a[great];
+                        less++;
                     } else { // a[great] == pivot1
-                        a[k] = pivot1;
-                        a[great--] = ak;
+                        /*
+                         * Even though a[great] equals to pivot1, the
+                         * assignment a[k] = pivot1 may be incorrect,
+                         * if a[great] and pivot1 are floating-point
+                         * zeros of different signs. Therefore in float
+                         * and double sorting methods we have to use
+                         * more accurate assignment a[k] = a[great].
+                         */
+                        a[k] = a[great];
                     }
+                    a[great] = ak;
+                    great--;
                 }
             }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        doSort(a, left,   less - 2);
-        doSort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 2/3 of the array),
-         * swap internal pivot values to ends
-         */
-        if (less < e1 && great > e5) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
 
-            /*
-             * Partitioning:
-             *
-             *   left part       center part                   right part
-             * +----------------------------------------------------------+
-             * | == pivot1 |  pivot1 < && < pivot2  |    ?    | == pivot2 |
-             * +----------------------------------------------------------+
-             *              ^                        ^       ^
-             *              |                        |       |
-             *             less                      k     great
-             *
-             * Invariants:
-             *
-             *              all in (*, less)  == pivot1
-             *     pivot1 < all in [less, k)   < pivot2
-             *              all in (great, *) == pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            outer:
-            for (int k = less; k <= great; k++) {
-                double ak = a[k];
-                if (ak == pivot2) { // Move a[k] to right part
-                    while (a[great] == pivot2) {
-                        if (great-- == k) {
-                            break outer;
-                        }
-                    }
-                    if (a[great] == pivot1) {
-                        a[k] = a[less];
-                        a[less++] = pivot1;
-                    } else { // pivot1 < a[great] < pivot2
-                        a[k] = a[great];
-                    }
-                    a[great--] = pivot2;
-                } else if (ak == pivot1) { // Move a[k] to left part
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
+            // Sort left and right parts recursively
+            sort(a, left, less - 1, leftmost);
+            sort(a, great + 1, right, false);
         }
-
-        // Sort center part recursively, excluding known pivot values
-        doSort(a, less, great);
     }
 
     /**
-     * Checks that {@code fromIndex} and {@code toIndex} are in
-     * the range and throws an appropriate exception, if they aren't.
+     * Checks that {@code fromIndex} and {@code toIndex} are in the range,
+     * otherwise throws an appropriate exception.
      */
     private static void rangeCheck(int length, int fromIndex, int toIndex) {
         if (fromIndex > toIndex) {
             throw new IllegalArgumentException(
-                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+                "fromIndex: " + fromIndex + " > toIndex: " + toIndex);
         }
         if (fromIndex < 0) {
             throw new ArrayIndexOutOfBoundsException(fromIndex);
--- a/jdk/src/share/classes/java/util/Scanner.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/util/Scanner.java	Wed Jul 05 17:17:57 2017 +0200
@@ -343,7 +343,7 @@
  *
  * @since   1.5
  */
-public final class Scanner implements Iterator<String> {
+public final class Scanner implements Iterator<String>, Closeable {
 
     // Internal buffer used to hold input
     private CharBuffer buf;
--- a/jdk/src/share/classes/java/util/logging/LogManager.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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 java.io.*;
 import java.util.*;
 import java.security.*;
+import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
@@ -154,10 +155,10 @@
                          = new PropertyChangeSupport(LogManager.class);
     private final static Level defaultLevel = Level.INFO;
 
-    // Table of known loggers.  Maps names to Loggers.
-    private Hashtable<String,WeakReference<Logger>> loggers =
-        new Hashtable<String,WeakReference<Logger>>();
-    // Tree of known loggers
+    // Table of named Loggers that maps names to Loggers.
+    private Hashtable<String,LoggerWeakRef> namedLoggers =
+        new Hashtable<String,LoggerWeakRef>();
+    // Tree of named Loggers
     private LogNode root = new LogNode(null);
     private Logger rootLogger;
 
@@ -417,6 +418,121 @@
             }});
     }
 
+
+    // loggerRefQueue holds LoggerWeakRef objects for Logger objects
+    // that have been GC'ed.
+    private final ReferenceQueue<Logger> loggerRefQueue
+        = new ReferenceQueue<Logger>();
+
+    // Package-level inner class.
+    // Helper class for managing WeakReferences to Logger objects.
+    //
+    // LogManager.namedLoggers
+    //     - has weak references to all named Loggers
+    //     - namedLoggers keeps the LoggerWeakRef objects for the named
+    //       Loggers around until we can deal with the book keeping for
+    //       the named Logger that is being GC'ed.
+    // LogManager.LogNode.loggerRef
+    //     - has a weak reference to a named Logger
+    //     - the LogNode will also keep the LoggerWeakRef objects for
+    //       the named Loggers around; currently LogNodes never go away.
+    // Logger.kids
+    //     - has a weak reference to each direct child Logger; this
+    //       includes anonymous and named Loggers
+    //     - anonymous Loggers are always children of the rootLogger
+    //       which is a strong reference; rootLogger.kids keeps the
+    //       LoggerWeakRef objects for the anonymous Loggers around
+    //       until we can deal with the book keeping.
+    //
+    final class LoggerWeakRef extends WeakReference<Logger> {
+        private String                name;       // for namedLoggers cleanup
+        private LogNode               node;       // for loggerRef cleanup
+        private WeakReference<Logger> parentRef;  // for kids cleanup
+
+        LoggerWeakRef(Logger logger) {
+            super(logger, loggerRefQueue);
+
+            name = logger.getName();  // save for namedLoggers cleanup
+        }
+
+        // dispose of this LoggerWeakRef object
+        void dispose() {
+            if (node != null) {
+                // if we have a LogNode, then we were a named Logger
+                // so clear namedLoggers weak ref to us
+                manager.namedLoggers.remove(name);
+                name = null;  // clear our ref to the Logger's name
+
+                node.loggerRef = null;  // clear LogNode's weak ref to us
+                node = null;            // clear our ref to LogNode
+            }
+
+            if (parentRef != null) {
+                // this LoggerWeakRef has or had a parent Logger
+                Logger parent = parentRef.get();
+                if (parent != null) {
+                    // the parent Logger is still there so clear the
+                    // parent Logger's weak ref to us
+                    parent.removeChildLogger(this);
+                }
+                parentRef = null;  // clear our weak ref to the parent Logger
+            }
+        }
+
+        // set the node field to the specified value
+        void setNode(LogNode node) {
+            this.node = node;
+        }
+
+        // set the parentRef field to the specified value
+        void setParentRef(WeakReference<Logger> parentRef) {
+            this.parentRef = parentRef;
+        }
+    }
+
+    // Package-level method.
+    // Drain some Logger objects that have been GC'ed.
+    //
+    // drainLoggerRefQueueBounded() is called by addLogger() below
+    // and by Logger.getAnonymousLogger(String) so we'll drain up to
+    // MAX_ITERATIONS GC'ed Loggers for every Logger we add.
+    //
+    // On a WinXP VMware client, a MAX_ITERATIONS value of 400 gives
+    // us about a 50/50 mix in increased weak ref counts versus
+    // decreased weak ref counts in the AnonLoggerWeakRefLeak test.
+    // Here are stats for cleaning up sets of 400 anonymous Loggers:
+    //   - test duration 1 minute
+    //   - sample size of 125 sets of 400
+    //   - average: 1.99 ms
+    //   - minimum: 0.57 ms
+    //   - maximum: 25.3 ms
+    //
+    // The same config gives us a better decreased weak ref count
+    // than increased weak ref count in the LoggerWeakRefLeak test.
+    // Here are stats for cleaning up sets of 400 named Loggers:
+    //   - test duration 2 minutes
+    //   - sample size of 506 sets of 400
+    //   - average: 0.57 ms
+    //   - minimum: 0.02 ms
+    //   - maximum: 10.9 ms
+    //
+    private final static int MAX_ITERATIONS = 400;
+    final synchronized void drainLoggerRefQueueBounded() {
+        for (int i = 0; i < MAX_ITERATIONS; i++) {
+            if (loggerRefQueue == null) {
+                // haven't finished loading LogManager yet
+                break;
+            }
+
+            LoggerWeakRef ref = (LoggerWeakRef) loggerRefQueue.poll();
+            if (ref == null) {
+                break;
+            }
+            // a Logger object has been GC'ed so clean it up
+            ref.dispose();
+        }
+    }
+
     /**
      * Add a named logger.  This does nothing and returns false if a logger
      * with the same name is already registered.
@@ -439,13 +555,16 @@
             throw new NullPointerException();
         }
 
-        WeakReference<Logger> ref = loggers.get(name);
+        // cleanup some Loggers that have been GC'ed
+        drainLoggerRefQueueBounded();
+
+        LoggerWeakRef ref = namedLoggers.get(name);
         if (ref != null) {
             if (ref.get() == null) {
-                // Hashtable holds stale weak reference
-                // to a logger which has been GC-ed.
-                // Allow to register new one.
-                loggers.remove(name);
+                // It's possible that the Logger was GC'ed after the
+                // drainLoggerRefQueueBounded() call above so allow
+                // a new one to be registered.
+                namedLoggers.remove(name);
             } else {
                 // We already have a registered logger with the given name.
                 return false;
@@ -454,7 +573,8 @@
 
         // We're adding a new logger.
         // Note that we are creating a weak reference here.
-        loggers.put(name, new WeakReference<Logger>(logger));
+        ref = new LoggerWeakRef(logger);
+        namedLoggers.put(name, ref);
 
         // Apply any initial level defined for the new logger.
         Level level = getLevelProperty(name+".level", null);
@@ -469,11 +589,11 @@
 
         // Find the new node and its parent.
         LogNode node = findNode(name);
-        node.loggerRef = new WeakReference<Logger>(logger);
+        node.loggerRef = ref;
         Logger parent = null;
         LogNode nodep = node.parent;
         while (nodep != null) {
-            WeakReference<Logger> nodeRef = nodep.loggerRef;
+            LoggerWeakRef nodeRef = nodep.loggerRef;
             if (nodeRef != null) {
                 parent = nodeRef.get();
                 if (parent != null) {
@@ -489,6 +609,9 @@
         // Walk over the children and tell them we are their new parent.
         node.walkAndSetParent(logger);
 
+        // new LogNode is ready so tell the LoggerWeakRef about it
+        ref.setNode(node);
+
         return true;
     }
 
@@ -572,7 +695,7 @@
      * @return  matching logger or null if none is found
      */
     public synchronized Logger getLogger(String name) {
-        WeakReference<Logger> ref = loggers.get(name);
+        LoggerWeakRef ref = namedLoggers.get(name);
         if (ref == null) {
             return null;
         }
@@ -580,7 +703,7 @@
         if (logger == null) {
             // Hashtable holds stale weak reference
             // to a logger which has been GC-ed.
-            loggers.remove(name);
+            namedLoggers.remove(name);
         }
         return logger;
     }
@@ -594,7 +717,7 @@
      * @return  enumeration of logger name strings
      */
     public synchronized Enumeration<String> getLoggerNames() {
-        return loggers.keys();
+        return namedLoggers.keys();
     }
 
     /**
@@ -942,7 +1065,7 @@
     // Nested class to represent a node in our tree of named loggers.
     private static class LogNode {
         HashMap<String,LogNode> children;
-        WeakReference<Logger> loggerRef;
+        LoggerWeakRef loggerRef;
         LogNode parent;
 
         LogNode(LogNode parent) {
@@ -958,7 +1081,7 @@
             Iterator<LogNode> values = children.values().iterator();
             while (values.hasNext()) {
                 LogNode node = values.next();
-                WeakReference<Logger> ref = node.loggerRef;
+                LoggerWeakRef ref = node.loggerRef;
                 Logger logger = (ref == null) ? null : ref.get();
                 if (logger == null) {
                     node.walkAndSetParent(parent);
--- a/jdk/src/share/classes/java/util/logging/Logger.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -183,7 +183,7 @@
     // We keep weak references from parents to children, but strong
     // references from children to parents.
     private volatile Logger parent;    // our nearest parent.
-    private ArrayList<WeakReference<Logger>> kids;   // WeakReferences to loggers that have us as parent
+    private ArrayList<LogManager.LoggerWeakRef> kids;   // WeakReferences to loggers that have us as parent
     private volatile Level levelObject;
     private volatile int levelValue;  // current effective level value
 
@@ -366,13 +366,8 @@
      *
      * @return a newly created private Logger
      */
-    public static synchronized Logger getAnonymousLogger() {
-        LogManager manager = LogManager.getLogManager();
-        Logger result = new Logger(null, null);
-        result.anonymous = true;
-        Logger root = manager.getLogger("");
-        result.doSetParent(root);
-        return result;
+    public static Logger getAnonymousLogger() {
+        return getAnonymousLogger(null);
     }
 
     /**
@@ -401,6 +396,8 @@
      */
     public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
         LogManager manager = LogManager.getLogManager();
+        // cleanup some Loggers that have been GC'ed
+        manager.drainLoggerRefQueueBounded();
         Logger result = new Logger(null, resourceBundleName);
         result.anonymous = true;
         Logger root = manager.getLogger("");
@@ -1380,14 +1377,18 @@
         synchronized (treeLock) {
 
             // Remove ourself from any previous parent.
+            LogManager.LoggerWeakRef ref = null;
             if (parent != null) {
                 // assert parent.kids != null;
-                for (Iterator<WeakReference<Logger>> iter = parent.kids.iterator(); iter.hasNext(); ) {
-                    WeakReference<Logger> ref =  iter.next();
+                for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) {
+                    ref = iter.next();
                     Logger kid =  ref.get();
                     if (kid == this) {
+                        // ref is used down below to complete the reparenting
                         iter.remove();
                         break;
+                    } else {
+                        ref = null;
                     }
                 }
                 // We have now removed ourself from our parents' kids.
@@ -1396,9 +1397,14 @@
             // Set our new parent.
             parent = newParent;
             if (parent.kids == null) {
-                parent.kids = new ArrayList<WeakReference<Logger>>(2);
+                parent.kids = new ArrayList<LogManager.LoggerWeakRef>(2);
             }
-            parent.kids.add(new WeakReference<Logger>(this));
+            if (ref == null) {
+                // we didn't have a previous parent
+                ref = manager.new LoggerWeakRef(this);
+            }
+            ref.setParentRef(new WeakReference<Logger>(parent));
+            parent.kids.add(ref);
 
             // As a result of the reparenting, the effective level
             // may have changed for us and our children.
@@ -1407,6 +1413,21 @@
         }
     }
 
+    // Package-level method.
+    // Remove the weak reference for the specified child Logger from the
+    // kid list. We should only be called from LoggerWeakRef.dispose().
+    final void removeChildLogger(LogManager.LoggerWeakRef child) {
+        synchronized (treeLock) {
+            for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) {
+                LogManager.LoggerWeakRef ref = iter.next();
+                if (ref == child) {
+                    iter.remove();
+                    return;
+                }
+            }
+        }
+    }
+
     // Recalculate the effective level for this node and
     // recursively for our children.
 
@@ -1438,7 +1459,7 @@
         // Recursively update the level on each of our kids.
         if (kids != null) {
             for (int i = 0; i < kids.size(); i++) {
-                WeakReference<Logger> ref = kids.get(i);
+                LogManager.LoggerWeakRef ref = kids.get(i);
                 Logger kid =  ref.get();
                 if (kid != null) {
                     kid.updateEffectiveLevel();
--- a/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,6 +25,7 @@
 
 package javax.imageio.stream;
 
+import java.io.Closeable;
 import java.io.DataInput;
 import java.io.IOException;
 import java.nio.ByteOrder;
@@ -42,7 +43,7 @@
  * @see MemoryCacheImageInputStream
  *
  */
-public interface ImageInputStream extends DataInput {
+public interface ImageInputStream extends DataInput, Closeable {
 
     /**
      * Sets the desired byte order for future reads of data values
--- a/jdk/src/share/classes/javax/sound/midi/MidiDevice.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/MidiDevice.java	Wed Jul 05 17:17:57 2017 +0200
@@ -107,7 +107,7 @@
  * @author Florian Bomers
  */
 
-public interface MidiDevice {
+public interface MidiDevice extends AutoCloseable {
 
 
     /**
--- a/jdk/src/share/classes/javax/sound/midi/Receiver.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/Receiver.java	Wed Jul 05 17:17:57 2017 +0200
@@ -38,7 +38,7 @@
  *
  * @author Kara Kytle
  */
-public interface Receiver {
+public interface Receiver extends AutoCloseable {
 
 
     //$$fb 2002-04-12: fix for 4662090: Contradiction in Receiver specification
--- a/jdk/src/share/classes/javax/sound/midi/Transmitter.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/Transmitter.java	Wed Jul 05 17:17:57 2017 +0200
@@ -35,7 +35,7 @@
  *
  * @author Kara Kytle
  */
-public interface Transmitter {
+public interface Transmitter extends AutoCloseable {
 
 
     /**
--- a/jdk/src/share/classes/javax/sound/sampled/Line.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/sampled/Line.java	Wed Jul 05 17:17:57 2017 +0200
@@ -70,7 +70,7 @@
  * @see LineEvent
  * @since 1.3
  */
-public interface Line {
+public interface Line extends AutoCloseable {
 
     /**
      * Obtains the <code>Line.Info</code> object describing this
--- a/jdk/src/share/classes/javax/swing/JSplitPane.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JSplitPane.java	Wed Jul 05 17:17:57 2017 +0200
@@ -242,19 +242,19 @@
 
     /**
      * Creates a new <code>JSplitPane</code> configured to arrange the child
-     * components side-by-side horizontally with no continuous
-     * layout, using two buttons for the components.
+     * components side-by-side horizontally, using two buttons for the components.
      */
     public JSplitPane() {
-        this(JSplitPane.HORIZONTAL_SPLIT, false,
-            new JButton(UIManager.getString("SplitPane.leftButtonText")),
-            new JButton(UIManager.getString("SplitPane.rightButtonText")));
+        this(JSplitPane.HORIZONTAL_SPLIT,
+                UIManager.getBoolean("SplitPane.continuousLayout"),
+                new JButton(UIManager.getString("SplitPane.leftButtonText")),
+                new JButton(UIManager.getString("SplitPane.rightButtonText")));
     }
 
 
     /**
      * Creates a new <code>JSplitPane</code> configured with the
-     * specified orientation and no continuous layout.
+     * specified orientation.
      *
      * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
@@ -263,7 +263,8 @@
      */
     @ConstructorProperties({"orientation"})
     public JSplitPane(int newOrientation) {
-        this(newOrientation, false);
+        this(newOrientation,
+                UIManager.getBoolean("SplitPane.continuousLayout"));
     }
 
 
@@ -287,9 +288,7 @@
 
     /**
      * Creates a new <code>JSplitPane</code> with the specified
-     * orientation and
-     * with the specified components that do not do continuous
-     * redrawing.
+     * orientation and the specified components.
      *
      * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
      *                        <code>JSplitPane.VERTICAL_SPLIT</code>
@@ -307,7 +306,9 @@
     public JSplitPane(int newOrientation,
                       Component newLeftComponent,
                       Component newRightComponent){
-        this(newOrientation, false, newLeftComponent, newRightComponent);
+        this(newOrientation,
+                UIManager.getBoolean("SplitPane.continuousLayout"),
+                newLeftComponent, newRightComponent);
     }
 
 
--- a/jdk/src/share/classes/javax/swing/JTable.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JTable.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1048,7 +1048,7 @@
 
     /**
      * Returns the horizontal and vertical space between cells.
-     * The default spacing is (1, 1), which provides room to draw the grid.
+     * The default spacing is look and feel dependent.
      *
      * @return  the horizontal and vertical spacing between cells
      * @see     #setIntercellSpacing
@@ -1155,7 +1155,7 @@
 
     /**
      * Returns true if the table draws horizontal lines between cells, false if it
-     * doesn't. The default is true.
+     * doesn't. The default value is look and feel dependent.
      *
      * @return  true if the table draws horizontal lines between cells, false if it
      *          doesn't
@@ -1167,7 +1167,7 @@
 
     /**
      * Returns true if the table draws vertical lines between cells, false if it
-     * doesn't. The default is true.
+     * doesn't. The default value is look and feel dependent.
      *
      * @return  true if the table draws vertical lines between cells, false if it
      *          doesn't
--- a/jdk/src/share/classes/javax/swing/JTree.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JTree.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1986,20 +1986,17 @@
      *               true if all nodes in the path are expanded
      */
     public boolean isExpanded(TreePath path) {
+
         if(path == null)
             return false;
-
-        // Is this node expanded?
-        Boolean value = expandedState.get(path);
-
-        if(value == null || !value.booleanValue())
-            return false;
-
-        // It is, make sure its parent is also expanded.
-        TreePath        parentPath = path.getParentPath();
-
-        if(parentPath != null)
-            return isExpanded(parentPath);
+        Object  value;
+
+        do{
+            value = expandedState.get(path);
+            if(value == null || !((Boolean)value).booleanValue())
+                return false;
+        } while( (path=path.getParentPath())!=null );
+
         return true;
     }
 
--- a/jdk/src/share/classes/javax/swing/border/TitledBorder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/border/TitledBorder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,22 +24,20 @@
  */
 package javax.swing.border;
 
-import sun.swing.SwingUtilities2;
-
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
 import java.awt.Insets;
 import java.awt.Rectangle;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Point;
-import java.awt.Toolkit;
-import java.awt.Component;
-import java.awt.Dimension;
+import java.awt.geom.Path2D;
 import java.beans.ConstructorProperties;
-
 import javax.swing.JComponent;
+import javax.swing.JLabel;
 import javax.swing.UIManager;
+import javax.swing.plaf.basic.BasicHTML;
 
 /**
  * A class which implements an arbitrary border
@@ -73,40 +71,40 @@
 {
     protected String title;
     protected Border border;
-    protected int    titlePosition;
-    protected int    titleJustification;
-    protected Font   titleFont;
-    protected Color  titleColor;
+    protected int titlePosition;
+    protected int titleJustification;
+    protected Font titleFont;
+    protected Color titleColor;
 
-    private Point textLoc = new Point();
+    private final JLabel label;
 
     /**
      * Use the default vertical orientation for the title text.
      */
     static public final int     DEFAULT_POSITION        = 0;
     /** Position the title above the border's top line. */
-    static public final int     ABOVE_TOP       = 1;
+    static public final int     ABOVE_TOP               = 1;
     /** Position the title in the middle of the border's top line. */
-    static public final int     TOP             = 2;
+    static public final int     TOP                     = 2;
     /** Position the title below the border's top line. */
-    static public final int     BELOW_TOP       = 3;
+    static public final int     BELOW_TOP               = 3;
     /** Position the title above the border's bottom line. */
-    static public final int     ABOVE_BOTTOM    = 4;
+    static public final int     ABOVE_BOTTOM            = 4;
     /** Position the title in the middle of the border's bottom line. */
-    static public final int     BOTTOM          = 5;
+    static public final int     BOTTOM                  = 5;
     /** Position the title below the border's bottom line. */
-    static public final int     BELOW_BOTTOM    = 6;
+    static public final int     BELOW_BOTTOM            = 6;
 
     /**
      * Use the default justification for the title text.
      */
     static public final int     DEFAULT_JUSTIFICATION   = 0;
     /** Position title text at the left side of the border line. */
-    static public final int     LEFT    = 1;
+    static public final int     LEFT                    = 1;
     /** Position title text in the center of the border line. */
-    static public final int     CENTER  = 2;
+    static public final int     CENTER                  = 2;
     /** Position title text at the right side of the border line. */
-    static public final int     RIGHT   = 3;
+    static public final int     RIGHT                   = 3;
     /** Position title text at the left side of the border line
      *  for left to right orientation, at the right side of the
      *  border line for right to left orientation.
@@ -132,7 +130,7 @@
      *
      * @param title  the title the border should display
      */
-    public TitledBorder(String title)     {
+    public TitledBorder(String title) {
         this(null, title, LEADING, DEFAULT_POSITION, null, null);
     }
 
@@ -142,7 +140,7 @@
      *
      * @param border  the border
      */
-    public TitledBorder(Border border)       {
+    public TitledBorder(Border border) {
         this(border, "", LEADING, DEFAULT_POSITION, null, null);
     }
 
@@ -167,9 +165,9 @@
      * @param titlePosition the position for the title
      */
     public TitledBorder(Border border,
-                        String title,
-                        int titleJustification,
-                        int titlePosition)      {
+                         String title,
+                         int titleJustification,
+                         int titlePosition) {
         this(border, title, titleJustification,
                         titlePosition, null, null);
     }
@@ -185,10 +183,10 @@
      * @param titleFont the font for rendering the title
      */
     public TitledBorder(Border border,
-                        String title,
-                        int titleJustification,
-                        int titlePosition,
-                        Font titleFont) {
+                         String title,
+                         int titleJustification,
+                         int titlePosition,
+                         Font titleFont) {
         this(border, title, titleJustification,
                         titlePosition, titleFont, null);
     }
@@ -207,11 +205,11 @@
      */
     @ConstructorProperties({"border", "title", "titleJustification", "titlePosition", "titleFont", "titleColor"})
     public TitledBorder(Border border,
-                        String title,
-                        int titleJustification,
-                        int titlePosition,
-                        Font titleFont,
-                        Color titleColor)       {
+                         String title,
+                         int titleJustification,
+                         int titlePosition,
+                         Font titleFont,
+                         Color titleColor) {
         this.title = title;
         this.border = border;
         this.titleFont = titleFont;
@@ -219,6 +217,10 @@
 
         setTitleJustification(titleJustification);
         setTitlePosition(titlePosition);
+
+        this.label = new JLabel();
+        this.label.setOpaque(false);
+        this.label.putClientProperty(BasicHTML.propertyKey, null);
     }
 
     /**
@@ -232,178 +234,111 @@
      * @param height the height of the painted border
      */
     public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
-
-        Border border = getBorder();
-
-        if (getTitle() == null || getTitle().equals("")) {
-            if (border != null) {
-                border.paintBorder(c, g, x, y, width, height);
-            }
-            return;
-        }
-
-        Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING,
-                                             width - (EDGE_SPACING * 2),
-                                             height - (EDGE_SPACING * 2));
-        Font font = g.getFont();
-        Color color = g.getColor();
+        Border border = getBorderUI();
+        String title = getTitle();
+        if ((title != null) && !title.isEmpty()) {
+            int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
+            JLabel label = getLabel(c);
+            Dimension size = label.getPreferredSize();
+            Insets insets = (border != null)
+                    ? border.getBorderInsets(c)
+                    : new Insets(0, 0, 0, 0);
 
-        g.setFont(getFont(c));
-
-        JComponent jc = (c instanceof JComponent) ? (JComponent)c : null;
-        FontMetrics fm = SwingUtilities2.getFontMetrics(jc, g);
-        int         fontHeight = fm.getHeight();
-        int         descent = fm.getDescent();
-        int         ascent = fm.getAscent();
-        int         diff;
-        int         stringWidth = SwingUtilities2.stringWidth(jc, fm,
-                                                              getTitle());
-        Insets      insets;
-
-        if (border != null) {
-            insets = border.getBorderInsets(c);
-        } else {
-            insets = new Insets(0, 0, 0, 0);
-        }
+            int borderX = x + edge;
+            int borderY = y + edge;
+            int borderW = width - edge - edge;
+            int borderH = height - edge - edge;
 
-        int titlePos = getTitlePosition();
-        switch (titlePos) {
-            case ABOVE_TOP:
-                diff = ascent + descent + (Math.max(EDGE_SPACING,
-                                 TEXT_SPACING*2) - EDGE_SPACING);
-                grooveRect.y += diff;
-                grooveRect.height -= diff;
-                textLoc.y = grooveRect.y - (descent + TEXT_SPACING);
-                break;
-            case TOP:
-            case DEFAULT_POSITION:
-                diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - EDGE_SPACING);
-                grooveRect.y += diff;
-                grooveRect.height -= diff;
-                textLoc.y = (grooveRect.y - descent) +
-                (insets.top + ascent + descent)/2;
-                break;
-            case BELOW_TOP:
-                textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING;
-                break;
-            case ABOVE_BOTTOM:
-                textLoc.y = (grooveRect.y + grooveRect.height) -
-                (insets.bottom + descent + TEXT_SPACING);
-                break;
-            case BOTTOM:
-                grooveRect.height -= fontHeight/2;
-                textLoc.y = ((grooveRect.y + grooveRect.height) - descent) +
-                        ((ascent + descent) - insets.bottom)/2;
-                break;
-            case BELOW_BOTTOM:
-                grooveRect.height -= fontHeight;
-                textLoc.y = grooveRect.y + grooveRect.height + ascent +
-                        TEXT_SPACING;
-                break;
-        }
-
-        int justification = getTitleJustification();
-        if(isLeftToRight(c)) {
-            if(justification==LEADING ||
-               justification==DEFAULT_JUSTIFICATION) {
-                justification = LEFT;
-            }
-            else if(justification==TRAILING) {
-                justification = RIGHT;
-            }
-        }
-        else {
-            if(justification==LEADING ||
-               justification==DEFAULT_JUSTIFICATION) {
-                justification = RIGHT;
+            int labelY = y;
+            int labelH = size.height;
+            int position = getPosition();
+            switch (position) {
+                case ABOVE_TOP:
+                    insets.left = 0;
+                    insets.right = 0;
+                    borderY += labelH - edge;
+                    borderH -= labelH - edge;
+                    break;
+                case TOP:
+                    insets.top = edge + insets.top/2 - labelH/2;
+                    if (insets.top < edge) {
+                        borderY -= insets.top;
+                        borderH += insets.top;
+                    }
+                    else {
+                        labelY += insets.top;
+                    }
+                    break;
+                case BELOW_TOP:
+                    labelY += insets.top + edge;
+                    break;
+                case ABOVE_BOTTOM:
+                    labelY += height - labelH - insets.bottom - edge;
+                    break;
+                case BOTTOM:
+                    labelY += height - labelH;
+                    insets.bottom = edge + (insets.bottom - labelH) / 2;
+                    if (insets.bottom < edge) {
+                        borderH += insets.bottom;
+                    }
+                    else {
+                        labelY -= insets.bottom;
+                    }
+                    break;
+                case BELOW_BOTTOM:
+                    insets.left = 0;
+                    insets.right = 0;
+                    labelY += height - labelH;
+                    borderH -= labelH - edge;
+                    break;
             }
-            else if(justification==TRAILING) {
-                justification = LEFT;
-            }
-        }
-
-        switch (justification) {
-            case LEFT:
-                textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left;
-                break;
-            case RIGHT:
-                textLoc.x = (grooveRect.x + grooveRect.width) -
-                        (stringWidth + TEXT_INSET_H + insets.right);
-                break;
-            case CENTER:
-                textLoc.x = grooveRect.x +
-                        ((grooveRect.width - stringWidth) / 2);
-                break;
-        }
+            insets.left += edge + TEXT_INSET_H;
+            insets.right += edge + TEXT_INSET_H;
 
-        // If title is positioned in middle of border AND its fontsize
-        // is greater than the border's thickness, we'll need to paint
-        // the border in sections to leave space for the component's background
-        // to show through the title.
-        //
-        if (border != null) {
-            if (((titlePos == TOP || titlePos == DEFAULT_POSITION) &&
-                  (grooveRect.y > textLoc.y - ascent)) ||
-                 (titlePos == BOTTOM &&
-                  (grooveRect.y + grooveRect.height < textLoc.y + descent))) {
-
-                Rectangle clipRect = new Rectangle();
-
-                // save original clip
-                Rectangle saveClip = g.getClipBounds();
-
-                // paint strip left of text
-                clipRect.setBounds(saveClip);
-                if (computeIntersection(clipRect, x, y, textLoc.x-1-x, height)) {
-                    g.setClip(clipRect);
-                    border.paintBorder(c, g, grooveRect.x, grooveRect.y,
-                                  grooveRect.width, grooveRect.height);
-                }
+            int labelX = x;
+            int labelW = width - insets.left - insets.right;
+            if (labelW > size.width) {
+                labelW = size.width;
+            }
+            switch (getJustification(c)) {
+                case LEFT:
+                    labelX += insets.left;
+                    break;
+                case RIGHT:
+                    labelX += width - insets.right - labelW;
+                    break;
+                case CENTER:
+                    labelX += (width - labelW) / 2;
+                    break;
+            }
 
-                // paint strip right of text
-                clipRect.setBounds(saveClip);
-                if (computeIntersection(clipRect, textLoc.x+stringWidth+1, y,
-                               x+width-(textLoc.x+stringWidth+1), height)) {
-                    g.setClip(clipRect);
-                    border.paintBorder(c, g, grooveRect.x, grooveRect.y,
-                                  grooveRect.width, grooveRect.height);
+            if (border != null) {
+                if ((position != TOP) && (position != BOTTOM)) {
+                    border.paintBorder(c, g, borderX, borderY, borderW, borderH);
                 }
-
-                if (titlePos == TOP || titlePos == DEFAULT_POSITION) {
-                    // paint strip below text
-                    clipRect.setBounds(saveClip);
-                    if (computeIntersection(clipRect, textLoc.x-1, textLoc.y+descent,
-                                        stringWidth+2, y+height-textLoc.y-descent)) {
-                        g.setClip(clipRect);
-                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
-                                  grooveRect.width, grooveRect.height);
+                else {
+                    Graphics g2 = g.create();
+                    if (g2 instanceof Graphics2D) {
+                        Graphics2D g2d = (Graphics2D) g2;
+                        Path2D path = new Path2D.Float();
+                        path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false);
+                        path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false);
+                        path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY, borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false);
+                        path.append(new Rectangle(borderX, labelY + labelH, borderW, borderY - labelY + borderH - labelH), false);
+                        g2d.clip(path);
                     }
-
-                } else { // titlePos == BOTTOM
-                  // paint strip above text
-                    clipRect.setBounds(saveClip);
-                    if (computeIntersection(clipRect, textLoc.x-1, y,
-                          stringWidth+2, textLoc.y - ascent - y)) {
-                        g.setClip(clipRect);
-                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
-                                  grooveRect.width, grooveRect.height);
-                    }
+                    border.paintBorder(c, g2, borderX, borderY, borderW, borderH);
+                    g2.dispose();
                 }
-
-                // restore clip
-                g.setClip(saveClip);
-
-            } else {
-                border.paintBorder(c, g, grooveRect.x, grooveRect.y,
-                                  grooveRect.width, grooveRect.height);
             }
+            g.translate(labelX, labelY);
+            label.setSize(labelW, labelH);
+            label.paint(g);
+            g.translate(-labelX, -labelY);
         }
-
-        g.setColor(getTitleColor());
-        SwingUtilities2.drawString(jc, g, getTitle(), textLoc.x, textLoc.y);
-
-        g.setFont(font);
-        g.setColor(color);
+        else if (border != null) {
+            border.paintBorder(c, g, x, y, width, height);
+        }
     }
 
     /**
@@ -412,69 +347,54 @@
      * @param insets the object to be reinitialized
      */
     public Insets getBorderInsets(Component c, Insets insets) {
-        FontMetrics fm;
-        int         descent = 0;
-        int         ascent = 16;
-        int         height = 16;
-
-        Border border = getBorder();
-        if (border != null) {
-            if (border instanceof AbstractBorder) {
-                ((AbstractBorder)border).getBorderInsets(c, insets);
-            } else {
-                // Can't reuse border insets because the Border interface
-                // can't be enhanced.
-                Insets i = border.getBorderInsets(c);
-                insets.top = i.top;
-                insets.right = i.right;
-                insets.bottom = i.bottom;
-                insets.left = i.left;
-            }
-        } else {
-            insets.left = insets.top = insets.right = insets.bottom = 0;
+        Border border = getBorderUI();
+        if (border == null) {
+            insets.set(0, 0, 0, 0);
+        }
+        else if (border instanceof AbstractBorder) {
+            AbstractBorder ab = (AbstractBorder) border;
+            insets = ab.getBorderInsets(c, insets);
         }
-
-        insets.left += EDGE_SPACING + TEXT_SPACING;
-        insets.right += EDGE_SPACING + TEXT_SPACING;
-        insets.top += EDGE_SPACING + TEXT_SPACING;
-        insets.bottom += EDGE_SPACING + TEXT_SPACING;
-
-        if(c == null || getTitle() == null || getTitle().equals(""))    {
-            return insets;
+        else {
+            Insets i = border.getBorderInsets(c);
+            insets.set(i.top, i.left, i.bottom, i.right);
         }
+        String title = getTitle();
+        if ((title != null) && !title.isEmpty()) {
+            int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
+            JLabel label = getLabel(c);
+            Dimension size = label.getPreferredSize();
 
-        Font font = getFont(c);
-
-        fm = c.getFontMetrics(font);
-
-        if(fm != null) {
-           descent = fm.getDescent();
-           ascent = fm.getAscent();
-           height = fm.getHeight();
-        }
-
-        switch (getTitlePosition()) {
-          case ABOVE_TOP:
-              insets.top += ascent + descent
-                            + (Math.max(EDGE_SPACING, TEXT_SPACING*2)
-                            - EDGE_SPACING);
-              break;
-          case TOP:
-          case DEFAULT_POSITION:
-              insets.top += ascent + descent;
-              break;
-          case BELOW_TOP:
-              insets.top += ascent + descent + TEXT_SPACING;
-              break;
-          case ABOVE_BOTTOM:
-              insets.bottom += ascent + descent + TEXT_SPACING;
-              break;
-          case BOTTOM:
-              insets.bottom += ascent + descent;
-              break;
-          case BELOW_BOTTOM:
-              insets.bottom += height;
-              break;
+            switch (getPosition()) {
+                case ABOVE_TOP:
+                    insets.top += size.height - edge;
+                    break;
+                case TOP: {
+                    if (insets.top < size.height) {
+                        insets.top = size.height - edge;
+                    }
+                    break;
+                }
+                case BELOW_TOP:
+                    insets.top += size.height;
+                    break;
+                case ABOVE_BOTTOM:
+                    insets.bottom += size.height;
+                    break;
+                case BOTTOM: {
+                    if (insets.bottom < size.height) {
+                        insets.bottom = size.height - edge;
+                    }
+                    break;
+                }
+                case BELOW_BOTTOM:
+                    insets.bottom += size.height - edge;
+                    break;
+            }
+            insets.top += edge + TEXT_SPACING;
+            insets.left += edge + TEXT_SPACING;
+            insets.right += edge + TEXT_SPACING;
+            insets.bottom += edge + TEXT_SPACING;
         }
         return insets;
     }
@@ -492,41 +412,14 @@
     /**
      * Returns the border of the titled border.
      */
-    public Border getBorder()       {
-        Border b = border;
-        if (b == null)
-            b = UIManager.getBorder("TitledBorder.border");
-        return b;
+    public Border getBorder() {
+        return border;
     }
 
     /**
      * Returns the title-position of the titled border.
      */
     public int getTitlePosition() {
-        if (titlePosition == DEFAULT_POSITION) {
-            Object value = UIManager.get("TitledBorder.position");
-            if (value instanceof String) {
-                String s = (String)value;
-                if ("ABOVE_TOP".equalsIgnoreCase(s)) {
-                    return ABOVE_TOP;
-                } else if ("TOP".equalsIgnoreCase(s)) {
-                    return TOP;
-                } else if ("BELOW_TOP".equalsIgnoreCase(s)) {
-                    return BELOW_TOP;
-                } else if ("ABOVE_BOTTOM".equalsIgnoreCase(s)) {
-                    return ABOVE_BOTTOM;
-                } else if ("BOTTOM".equalsIgnoreCase(s)) {
-                    return BOTTOM;
-                } else if ("BELOW_BOTTOM".equalsIgnoreCase(s)) {
-                    return BELOW_BOTTOM;
-                }
-            } else if (value instanceof Integer) {
-                int i = (Integer)value;
-                if (i >= 0 && i <= 6) {
-                    return i;
-                }
-            }
-        }
         return titlePosition;
     }
 
@@ -539,20 +432,14 @@
      * Returns the title-font of the titled border.
      */
     public Font getTitleFont()      {
-        Font f = titleFont;
-        if (f == null)
-            f = UIManager.getFont("TitledBorder.font");
-        return f;
+        return titleFont;
     }
 
     /**
      * Returns the title-color of the titled border.
      */
     public Color getTitleColor()    {
-        Color c = titleColor;
-        if (c == null)
-            c = UIManager.getColor("TitledBorder.titleColor");
-        return c;
+        return titleColor;
     }
 
 
@@ -576,18 +463,18 @@
      */
     public void setTitlePosition(int titlePosition) {
         switch (titlePosition) {
-          case ABOVE_TOP:
-          case TOP:
-          case BELOW_TOP:
-          case ABOVE_BOTTOM:
-          case BOTTOM:
-          case BELOW_BOTTOM:
-          case DEFAULT_POSITION:
+            case ABOVE_TOP:
+            case TOP:
+            case BELOW_TOP:
+            case ABOVE_BOTTOM:
+            case BOTTOM:
+            case BELOW_BOTTOM:
+            case DEFAULT_POSITION:
                 this.titlePosition = titlePosition;
                 break;
-          default:
-            throw new IllegalArgumentException(titlePosition +
-                                        " is not a valid title position.");
+            default:
+                throw new IllegalArgumentException(titlePosition +
+                        " is not a valid title position.");
         }
     }
 
@@ -624,7 +511,7 @@
      * @param titleColor the color for the border title
      */
     public void setTitleColor(Color titleColor) {
-      this.titleColor = titleColor;
+        this.titleColor = titleColor;
     }
 
     /**
@@ -636,22 +523,18 @@
         Insets insets = getBorderInsets(c);
         Dimension minSize = new Dimension(insets.right+insets.left,
                                           insets.top+insets.bottom);
-        Font font = getFont(c);
-        FontMetrics fm = c.getFontMetrics(font);
-        JComponent jc = (c instanceof JComponent) ? (JComponent)c : null;
-        switch (getTitlePosition()) {
-          case ABOVE_TOP:
-          case BELOW_BOTTOM:
-              minSize.width = Math.max(SwingUtilities2.stringWidth(jc, fm,
-                                       getTitle()), minSize.width);
-              break;
-          case BELOW_TOP:
-          case ABOVE_BOTTOM:
-          case TOP:
-          case BOTTOM:
-          case DEFAULT_POSITION:
-          default:
-              minSize.width += SwingUtilities2.stringWidth(jc, fm, getTitle());
+        String title = getTitle();
+        if ((title != null) && !title.isEmpty()) {
+            JLabel label = getLabel(c);
+            Dimension size = label.getPreferredSize();
+
+            int position = getPosition();
+            if ((position != ABOVE_TOP) && (position != BELOW_BOTTOM)) {
+                minSize.width += size.width;
+            }
+            else if (minSize.width < size.width) {
+                minSize.width += size.width;
+            }
         }
         return minSize;
     }
@@ -674,48 +557,36 @@
         if (height < 0) {
             throw new IllegalArgumentException("Height must be >= 0");
         }
+        Border border = getBorderUI();
         String title = getTitle();
-        if (title != null && !"".equals(title)) {
-            Font font = getFont(c);
-            Border border2 = getBorder();
-            Insets borderInsets;
-            if (border2 != null) {
-                borderInsets = border2.getBorderInsets(c);
-            }
-            else {
-                borderInsets = new Insets(0, 0, 0, 0);
-            }
-            FontMetrics fm = c.getFontMetrics(font);
-            int fontHeight = fm.getHeight();
-            int descent = fm.getDescent();
-            int ascent = fm.getAscent();
-            int y = EDGE_SPACING;
-            int h = height - EDGE_SPACING * 2;
-            int diff;
-            switch (getTitlePosition()) {
-            case ABOVE_TOP:
-                diff = ascent + descent + (Math.max(EDGE_SPACING,
-                                                    TEXT_SPACING * 2) -
-                                           EDGE_SPACING);
-                return y + diff - (descent + TEXT_SPACING);
-            case TOP:
-            case DEFAULT_POSITION:
-                diff = Math.max(0, ((ascent/2) + TEXT_SPACING) -
-                                EDGE_SPACING);
-                return (y + diff - descent) +
-                    (borderInsets.top + ascent + descent)/2;
-            case BELOW_TOP:
-                return y + borderInsets.top + ascent + TEXT_SPACING;
-            case ABOVE_BOTTOM:
-                return (y + h) - (borderInsets.bottom + descent +
-                                  TEXT_SPACING);
-            case BOTTOM:
-                h -= fontHeight / 2;
-                return ((y + h) - descent) +
-                        ((ascent + descent) - borderInsets.bottom)/2;
-            case BELOW_BOTTOM:
-                h -= fontHeight;
-                return y + h + ascent + TEXT_SPACING;
+        if ((title != null) && !title.isEmpty()) {
+            int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING;
+            JLabel label = getLabel(c);
+            Dimension size = label.getPreferredSize();
+            Insets insets = (border != null)
+                    ? border.getBorderInsets(c)
+                    : new Insets(0, 0, 0, 0);
+
+            int baseline = label.getBaseline(size.width, size.height);
+            switch (getPosition()) {
+                case ABOVE_TOP:
+                    return baseline;
+                case TOP:
+                    insets.top = edge + (insets.top - size.height) / 2;
+                    return (insets.top < edge)
+                            ? baseline
+                            : baseline + insets.top;
+                case BELOW_TOP:
+                    return baseline + insets.top + edge;
+                case ABOVE_BOTTOM:
+                    return baseline + height - size.height - insets.bottom - edge;
+                case BOTTOM:
+                    insets.bottom = edge + (insets.bottom - size.height) / 2;
+                    return (insets.bottom < edge)
+                            ? baseline + height - size.height
+                            : baseline + height - size.height + insets.bottom;
+                case BELOW_BOTTOM:
+                    return baseline + height - size.height;
             }
         }
         return -1;
@@ -732,44 +603,111 @@
     public Component.BaselineResizeBehavior getBaselineResizeBehavior(
             Component c) {
         super.getBaselineResizeBehavior(c);
-        switch(getTitlePosition()) {
-        case TitledBorder.ABOVE_TOP:
-        case TitledBorder.TOP:
-        case TitledBorder.DEFAULT_POSITION:
-        case TitledBorder.BELOW_TOP:
-            return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
-        case TitledBorder.ABOVE_BOTTOM:
-        case TitledBorder.BOTTOM:
-        case TitledBorder.BELOW_BOTTOM:
-            return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT;
+        switch (getPosition()) {
+            case TitledBorder.ABOVE_TOP:
+            case TitledBorder.TOP:
+            case TitledBorder.BELOW_TOP:
+                return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
+            case TitledBorder.ABOVE_BOTTOM:
+            case TitledBorder.BOTTOM:
+            case TitledBorder.BELOW_BOTTOM:
+                return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT;
         }
         return Component.BaselineResizeBehavior.OTHER;
     }
 
+    private Border getBorderUI() {
+        Border border = getBorder();
+        return border != null
+                ? border
+                : UIManager.getBorder("TitledBorder.border");
+    }
+
+    private int getPosition() {
+        int position = getTitlePosition();
+        if (position != DEFAULT_POSITION) {
+            return position;
+        }
+        Object value = UIManager.get("TitledBorder.position");
+        if (value instanceof Integer) {
+            int i = (Integer) value;
+            if ((0 < i) && (i <= 6)) {
+                return i;
+            }
+        }
+        else if (value instanceof String) {
+            String s = (String) value;
+            if (s.equalsIgnoreCase("ABOVE_TOP")) {
+                return ABOVE_TOP;
+            }
+            if (s.equalsIgnoreCase("TOP")) {
+                return TOP;
+            }
+            if (s.equalsIgnoreCase("BELOW_TOP")) {
+                return BELOW_TOP;
+            }
+            if (s.equalsIgnoreCase("ABOVE_BOTTOM")) {
+                return ABOVE_BOTTOM;
+            }
+            if (s.equalsIgnoreCase("BOTTOM")) {
+                return BOTTOM;
+            }
+            if (s.equalsIgnoreCase("BELOW_BOTTOM")) {
+                return BELOW_BOTTOM;
+            }
+        }
+        return TOP;
+    }
+
+    private int getJustification(Component c) {
+        int justification = getTitleJustification();
+        if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) {
+            return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT;
+        }
+        if (justification == TRAILING) {
+            return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT;
+        }
+        return justification;
+    }
+
     protected Font getFont(Component c) {
-        Font font;
-        if ((font = getTitleFont()) != null) {
+        Font font = getTitleFont();
+        if (font != null) {
+            return font;
+        }
+        font = UIManager.getFont("TitledBorder.font");
+        if (font != null) {
             return font;
-        } else if (c != null && (font = c.getFont()) != null) {
-            return font;
+        }
+        if (c != null) {
+            font = c.getFont();
+            if (font != null) {
+                return font;
+            }
         }
         return new Font(Font.DIALOG, Font.PLAIN, 12);
     }
 
-    private static boolean computeIntersection(Rectangle dest,
-                                               int rx, int ry, int rw, int rh) {
-        int x1 = Math.max(rx, dest.x);
-        int x2 = Math.min(rx + rw, dest.x + dest.width);
-        int y1 = Math.max(ry, dest.y);
-        int y2 = Math.min(ry + rh, dest.y + dest.height);
-        dest.x = x1;
-        dest.y = y1;
-        dest.width = x2 - x1;
-        dest.height = y2 - y1;
+    private Color getColor(Component c) {
+        Color color = getTitleColor();
+        if (color != null) {
+            return color;
+        }
+        color = UIManager.getColor("TitledBorder.titleColor");
+        if (color != null) {
+            return color;
+        }
+        return (c != null)
+                ? c.getForeground()
+                : null;
+    }
 
-        if (dest.width <= 0 || dest.height <= 0) {
-            return false;
-        }
-        return true;
+    private JLabel getLabel(Component c) {
+        this.label.setText(getTitle());
+        this.label.setFont(getFont(c));
+        this.label.setForeground(getColor(c));
+        this.label.setComponentOrientation(c.getComponentOrientation());
+        this.label.setEnabled(c.isEnabled());
+        return this.label;
     }
 }
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java	Wed Jul 05 17:17:57 2017 +0200
@@ -195,9 +195,8 @@
         }
 
         ButtonModel model = b.getModel();
+        model.setPressed(false);
         model.setArmed(false);
-        model.setPressed(false);
-
         b.repaint();
     }
 
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java	Wed Jul 05 17:17:57 2017 +0200
@@ -876,7 +876,7 @@
             String name = getName();
             if (TOGGLE_SORT_ORDER == name) {
                 JTable table = th.getTable();
-                RowSorter sorter = table.getRowSorter();
+                RowSorter sorter = table == null ? null : table.getRowSorter();
                 if (sorter != null) {
                     int columnIndex = ui.getSelectedColumnIndex();
                     columnIndex = table.convertColumnIndexToModel(
--- a/jdk/src/share/classes/javax/swing/plaf/nimbus/skin.laf	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/skin.laf	Wed Jul 05 17:17:57 2017 +0200
@@ -21276,6 +21276,7 @@
                <uiProperty name="centerOneTouchButtons" type="BOOLEAN" value="true"/>
                <uiProperty name="oneTouchButtonOffset" type="INT" value="30"/>
                <uiProperty name="oneTouchExpandable" type="BOOLEAN" value="false"/>
+               <uiProperty name="continuousLayout" type="BOOLEAN" value="true"/>
             </uiproperties>
          </style>
          <backgroundStates>
--- a/jdk/src/share/classes/sun/awt/PlatformFont.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/PlatformFont.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,10 +25,10 @@
 
 package sun.awt;
 
-import java.awt.GraphicsEnvironment;
 import java.awt.peer.FontPeer;
 import java.util.Locale;
 import java.util.Vector;
+import sun.font.SunFontManager;
 import sun.java2d.FontSupport;
 import java.nio.CharBuffer;
 import java.nio.ByteBuffer;
@@ -57,9 +57,9 @@
     protected static String osVersion;
 
     public PlatformFont(String name, int style){
-        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        if (ge instanceof FontSupport) {
-            fontConfig = ((FontSupport)ge).getFontConfiguration();
+        SunFontManager sfm = SunFontManager.getInstance();
+        if (sfm instanceof FontSupport) {
+            fontConfig = ((FontSupport)sfm).getFontConfiguration();
         }
         if (fontConfig == null) {
             return;
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java	Wed Jul 05 17:17:57 2017 +0200
@@ -39,6 +39,7 @@
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import sun.util.logging.PlatformLogger;
 import sun.misc.SoftCache;
@@ -592,7 +593,7 @@
         }
         PostEventQueue postEventQueue =
             (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
-        if(postEventQueue != null) {
+        if (postEventQueue != null) {
             postEventQueue.postEvent(event);
         }
     }
@@ -610,16 +611,29 @@
         postEvent(targetToAppContext(e.getSource()), pe);
     }
 
+    private static final Lock flushLock = new ReentrantLock();
+    private static boolean isFlushingPendingEvents = false;
+
     /*
      * Flush any pending events which haven't been posted to the AWT
      * EventQueue yet.
      */
     public static void flushPendingEvents()  {
-        AppContext appContext = AppContext.getAppContext();
-        PostEventQueue postEventQueue =
-            (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
-        if(postEventQueue != null) {
-            postEventQueue.flush();
+        flushLock.lock();
+        try {
+            // Don't call flushPendingEvents() recursively
+            if (!isFlushingPendingEvents) {
+                isFlushingPendingEvents = true;
+                AppContext appContext = AppContext.getAppContext();
+                PostEventQueue postEventQueue =
+                    (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
+                if (postEventQueue != null) {
+                    postEventQueue.flush();
+                }
+            }
+        } finally {
+            isFlushingPendingEvents = false;
+            flushLock.unlock();
         }
     }
 
@@ -1930,6 +1944,25 @@
         return (Window)comp;
     }
 
+    /**
+     * Returns the value of the system property indicated by the specified key.
+     */
+    public static String getSystemProperty(final String key) {
+        return (String)AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    return System.getProperty(key);
+                }
+            });
+    }
+
+    /**
+     * Returns the boolean value of the system property indicated by the specified key.
+     */
+    protected static Boolean getBooleanSystemProperty(String key) {
+        return Boolean.valueOf(AccessController.
+                   doPrivileged(new GetBooleanAction(key)));
+    }
+
     private static Boolean sunAwtDisableMixing = null;
 
     /**
@@ -1938,9 +1971,7 @@
      */
     public synchronized static boolean getSunAwtDisableMixing() {
         if (sunAwtDisableMixing == null) {
-            sunAwtDisableMixing = Boolean.valueOf(
-                    AccessController.doPrivileged(
-                        new GetBooleanAction("sun.awt.disableMixing")));
+            sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing");
         }
         return sunAwtDisableMixing.booleanValue();
     }
@@ -2079,12 +2110,14 @@
         eventQueue = eq;
     }
 
-    public boolean noEvents() {
+    public synchronized boolean noEvents() {
         return queueHead == null;
     }
 
     /*
-     * Continually post pending AWTEvents to the Java EventQueue.
+     * Continually post pending AWTEvents to the Java EventQueue. The method
+     * is synchronized to ensure the flush is completed before a new event
+     * can be posted to this queue.
      */
     public synchronized void flush() {
         EventQueueItem tempQueue = queueHead;
--- a/jdk/src/share/classes/sun/font/FontUtilities.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/font/FontUtilities.java	Wed Jul 05 17:17:57 2017 +0200
@@ -60,6 +60,10 @@
 
     static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf";
 
+    private static boolean debugFonts = false;
+    private static PlatformLogger logger = null;
+    private static boolean logging;
+
     // This static initializer block figures out the OS constants.
     static {
 
@@ -115,6 +119,25 @@
                 File lucidaFile = new File(jreFontDirName + File.separator
                                            + LUCIDA_FILE_NAME);
                 isOpenJDK = !lucidaFile.exists();
+
+                String debugLevel =
+                    System.getProperty("sun.java2d.debugfonts");
+
+                if (debugLevel != null && !debugLevel.equals("false")) {
+                    debugFonts = true;
+                    logger = PlatformLogger.getLogger("sun.java2d");
+                    if (debugLevel.equals("warning")) {
+                        logger.setLevel(PlatformLogger.WARNING);
+                    } else if (debugLevel.equals("severe")) {
+                        logger.setLevel(PlatformLogger.SEVERE);
+                    }
+                }
+
+                if (debugFonts) {
+                    logger = PlatformLogger.getLogger("sun.java2d");
+                    logging = logger.isEnabled();
+                }
+
                 return null;
             }
         });
@@ -140,32 +163,6 @@
      */
     public static final int MAX_LAYOUT_CHARCODE = 0x206F;
 
-    private static boolean debugFonts = false;
-    private static PlatformLogger logger = null;
-    private static boolean logging;
-
-    static {
-
-        String debugLevel =
-            System.getProperty("sun.java2d.debugfonts");
-
-        if (debugLevel != null && !debugLevel.equals("false")) {
-            debugFonts = true;
-            logger = PlatformLogger.getLogger("sun.java2d");
-            if (debugLevel.equals("warning")) {
-                logger.setLevel(PlatformLogger.WARNING);
-            } else if (debugLevel.equals("severe")) {
-                logger.setLevel(PlatformLogger.SEVERE);
-            }
-        }
-
-        if (debugFonts) {
-            logger = PlatformLogger.getLogger("sun.java2d");
-            logging = logger.isEnabled();
-        }
-
-    }
-
     /**
      * Calls the private getFont2D() method in java.awt.Font objects.
      *
--- a/jdk/src/share/classes/sun/io/CharToByteDBCS_ASCII.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/io/CharToByteDBCS_ASCII.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,7 +24,6 @@
  */
 package sun.io;
 
-import sun.nio.cs.Surrogate;
 import sun.nio.cs.ext.DoubleByte;
 import static sun.nio.cs.CharsetMapping.*;
 
--- a/jdk/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,7 +24,6 @@
  */
 package sun.io;
 
-import sun.nio.cs.Surrogate;
 import sun.nio.cs.ext.DoubleByte;
 import static sun.nio.cs.CharsetMapping.*;
 
--- a/jdk/src/share/classes/sun/java2d/HeadlessGraphicsEnvironment.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/java2d/HeadlessGraphicsEnvironment.java	Wed Jul 05 17:17:57 2017 +0200
@@ -59,17 +59,12 @@
  * Headless decorator implementation of a SunGraphicsEnvironment
  */
 
-public class HeadlessGraphicsEnvironment extends GraphicsEnvironment
-    implements FontSupport {
+public class HeadlessGraphicsEnvironment extends GraphicsEnvironment {
 
     private GraphicsEnvironment ge;
-    private FontSupport fontSupport;
 
     public HeadlessGraphicsEnvironment(GraphicsEnvironment ge) {
         this.ge = ge;
-        if (ge instanceof FontSupport) {
-            fontSupport = (FontSupport)ge;
-        }
     }
 
     public GraphicsDevice[] getScreenDevices()
@@ -101,13 +96,6 @@
     public String[] getAvailableFontFamilyNames(Locale l) {
         return ge.getAvailableFontFamilyNames(l); }
 
-    public FontConfiguration getFontConfiguration() {
-        if (fontSupport != null) {
-            return fontSupport.getFontConfiguration();
-        }
-        return null;
-    }
-
     /* Used by FontManager : internal API */
     public GraphicsEnvironment getSunGraphicsEnvironment() {
         return ge;
--- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, 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
@@ -208,7 +208,7 @@
         Method method = null;
         try {
             method = clazz.getMethod("main", String[].class);
-        } catch (Exception e) {
+        } catch (NoSuchMethodException nsme) {
             ostream.println(getLocalizedMessage("java.launcher.cls.error4",
                     classname));
             throw new RuntimeException("Main method not found in " + classname);
@@ -225,8 +225,7 @@
             throw new RuntimeException("Main method is not static in class " +
                     classname);
         }
-        Class<?> rType = method.getReturnType();
-        if (!rType.isPrimitive() || !rType.getName().equals("void")) {
+        if (method.getReturnType() != java.lang.Void.TYPE) {
             ostream.println(getLocalizedMessage("java.launcher.cls.error3",
                     classname));
             throw new RuntimeException("Main method must return a value" +
--- a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java	Wed Jul 05 17:17:57 2017 +0200
@@ -52,14 +52,16 @@
     boolean http10 = false;
 
     /* for formatting the Date: header */
-    static TimeZone tz;
-    static DateFormat df;
-    static {
-        String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
-        tz = TimeZone.getTimeZone ("GMT");
-        df = new SimpleDateFormat (pattern, Locale.US);
-        df.setTimeZone (tz);
-    }
+    private static final String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
+    private static final TimeZone gmtTZ = TimeZone.getTimeZone("GMT");
+    private static final ThreadLocal<DateFormat> dateFormat =
+         new ThreadLocal<DateFormat>() {
+             @Override protected DateFormat initialValue() {
+                 DateFormat df = new SimpleDateFormat(pattern, Locale.US);
+                 df.setTimeZone(gmtTZ);
+                 return df;
+         }
+     };
 
     private static final String HEAD = "HEAD";
 
@@ -206,7 +208,7 @@
         PlaceholderOutputStream o = getPlaceholderResponseBody();
         tmpout.write (bytes(statusLine, 0), 0, statusLine.length());
         boolean noContentToSend = false; // assume there is content
-        rspHdrs.set ("Date", df.format (new Date()));
+        rspHdrs.set ("Date", dateFormat.get().format (new Date()));
 
         /* check for response type that is not allowed to send a body */
 
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Wed Jul 05 17:17:57 2017 +0200
@@ -2331,7 +2331,7 @@
      * closed the connection to the web server.
      */
     private void disconnectWeb() throws IOException {
-        if (usingProxy()) {
+        if (usingProxy() && http.isKeepingAlive()) {
             responseCode = -1;
             // clean up, particularly, skip the content part
             // of a 401 error response
--- a/jdk/src/share/classes/sun/nio/cs/Surrogate.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/Surrogate.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -34,8 +34,9 @@
  * Utility class for dealing with surrogates.
  *
  * @author Mark Reinhold
+ * @author Martin Buchholz
+ * @author Ulf Zibis
  */
-
 public class Surrogate {
 
     private Surrogate() { }
@@ -75,16 +76,9 @@
     }
 
     /**
-     * Tells whether or not the given UCS-4 character is in the Basic
-     * Multilingual Plane, and can be represented using a single char.
-     */
-    public static boolean isBMPCodePoint(int uc) {
-        return uc >> 16 == 0;
-    }
-
-    /**
      * Tells whether or not the given UCS-4 character must be represented as a
      * surrogate pair in UTF-16.
+     * Use of {@link Character#isSupplementaryCodePoint} is generally preferred.
      */
     public static boolean neededFor(int uc) {
         return Character.isSupplementaryCodePoint(uc);
@@ -92,24 +86,25 @@
 
     /**
      * Returns the high UTF-16 surrogate for the given supplementary UCS-4 character.
+     * Use of {@link Character#highSurrogate} is generally preferred.
      */
     public static char high(int uc) {
         assert Character.isSupplementaryCodePoint(uc);
-        return (char)((uc >> 10)
-                      + (Character.MIN_HIGH_SURROGATE
-                         - (Character.MIN_SUPPLEMENTARY_CODE_POINT >> 10)));
+        return Character.highSurrogate(uc);
     }
 
     /**
      * Returns the low UTF-16 surrogate for the given supplementary UCS-4 character.
+     * Use of {@link Character#lowSurrogate} is generally preferred.
      */
     public static char low(int uc) {
         assert Character.isSupplementaryCodePoint(uc);
-        return (char)((uc & 0x3ff) + Character.MIN_LOW_SURROGATE);
+        return Character.lowSurrogate(uc);
     }
 
     /**
      * Converts the given surrogate pair into a 32-bit UCS-4 character.
+     * Use of {@link Character#toCodePoint} is generally preferred.
      */
     public static int toUCS4(char c, char d) {
         assert Character.isHighSurrogate(c) && Character.isLowSurrogate(d);
@@ -290,8 +285,9 @@
          *           error() will return a descriptive result object
          */
         public int generate(int uc, int len, CharBuffer dst) {
-            if (Surrogate.isBMPCodePoint(uc)) {
-                if (Surrogate.is(uc)) {
+            if (Character.isBmpCodePoint(uc)) {
+                char c = (char) uc;
+                if (Character.isSurrogate(c)) {
                     error = CoderResult.malformedForLength(len);
                     return -1;
                 }
@@ -299,16 +295,16 @@
                     error = CoderResult.OVERFLOW;
                     return -1;
                 }
-                dst.put((char)uc);
+                dst.put(c);
                 error = null;
                 return 1;
-            } else if (Character.isSupplementaryCodePoint(uc)) {
+            } else if (Character.isValidCodePoint(uc)) {
                 if (dst.remaining() < 2) {
                     error = CoderResult.OVERFLOW;
                     return -1;
                 }
-                dst.put(Surrogate.high(uc));
-                dst.put(Surrogate.low(uc));
+                dst.put(Character.highSurrogate(uc));
+                dst.put(Character.lowSurrogate(uc));
                 error = null;
                 return 2;
             } else {
@@ -334,8 +330,9 @@
          *           error() will return a descriptive result object
          */
         public int generate(int uc, int len, char[] da, int dp, int dl) {
-            if (Surrogate.isBMPCodePoint(uc)) {
-                if (Surrogate.is(uc)) {
+            if (Character.isBmpCodePoint(uc)) {
+                char c = (char) uc;
+                if (Character.isSurrogate(c)) {
                     error = CoderResult.malformedForLength(len);
                     return -1;
                 }
@@ -343,16 +340,16 @@
                     error = CoderResult.OVERFLOW;
                     return -1;
                 }
-                da[dp] = (char)uc;
+                da[dp] = c;
                 error = null;
                 return 1;
-            } else if (Character.isSupplementaryCodePoint(uc)) {
+            } else if (Character.isValidCodePoint(uc)) {
                 if (dl - dp < 2) {
                     error = CoderResult.OVERFLOW;
                     return -1;
                 }
-                da[dp] = Surrogate.high(uc);
-                da[dp + 1] = Surrogate.low(uc);
+                da[dp] = Character.highSurrogate(uc);
+                da[dp + 1] = Character.lowSurrogate(uc);
                 error = null;
                 return 2;
             } else {
--- a/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -86,22 +86,21 @@
                         src.position(mark);
                     }
                 }
-                while (src.remaining() > 3) {
+                while (src.remaining() >= 4) {
                     cp = getCP(src);
-                    if (cp < 0 || cp > Surrogate.UCS4_MAX) {
-                        return CoderResult.malformedForLength(4);
-                    }
-                    if (cp < Surrogate.UCS4_MIN) {
+                    if (Character.isBmpCodePoint(cp)) {
                         if (!dst.hasRemaining())
                             return CoderResult.OVERFLOW;
                         mark += 4;
-                        dst.put((char)cp);
-                    } else {
+                        dst.put((char) cp);
+                    } else if (Character.isValidCodePoint(cp)) {
                         if (dst.remaining() < 2)
                             return CoderResult.OVERFLOW;
                         mark += 4;
-                        dst.put(Surrogate.high(cp));
-                        dst.put(Surrogate.low(cp));
+                        dst.put(Character.highSurrogate(cp));
+                        dst.put(Character.lowSurrogate(cp));
+                    } else {
+                        return CoderResult.malformedForLength(4);
                     }
                 }
                 return CoderResult.UNDERFLOW;
@@ -154,7 +153,12 @@
             try {
                 while (src.hasRemaining()) {
                     char c = src.get();
-                    if (Character.isHighSurrogate(c)) {
+                    if (!Character.isSurrogate(c)) {
+                        if (dst.remaining() < 4)
+                            return CoderResult.OVERFLOW;
+                        mark++;
+                        put(c, dst);
+                    } else if (Character.isHighSurrogate(c)) {
                         if (!src.hasRemaining())
                             return CoderResult.UNDERFLOW;
                         char low = src.get();
@@ -162,17 +166,13 @@
                             if (dst.remaining() < 4)
                                 return CoderResult.OVERFLOW;
                             mark += 2;
-                            put(Surrogate.toUCS4(c, low), dst);
+                            put(Character.toCodePoint(c, low), dst);
                         } else {
                             return CoderResult.malformedForLength(1);
                         }
-                    } else if (Character.isLowSurrogate(c)) {
+                    } else {
+                        // assert Character.isLowSurrogate(c);
                         return CoderResult.malformedForLength(1);
-                    } else {
-                        if (dst.remaining() < 4)
-                            return CoderResult.OVERFLOW;
-                        mark++;
-                        put(c, dst);
                     }
                 }
                 return CoderResult.UNDERFLOW;
--- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Wed Jul 05 17:17:57 2017 +0200
@@ -102,7 +102,7 @@
         //  [F1..F3] [80..BF] [80..BF] [80..BF]
         //  [F4]     [80..8F] [80..BF] [80..BF]
         //  only check 80-be range here, the [0xf0,0x80...] and [0xf4,0x90-...]
-        //  will be checked by Surrogate.neededFor(uc)
+        //  will be checked by Character.isSupplementaryCodePoint(uc)
         private static boolean isMalformed4(int b2, int b3, int b4) {
             return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
                    (b4 & 0xc0) != 0x80;
@@ -207,15 +207,15 @@
 
             // ASCII only loop
             while (dp < dlASCII && sa[sp] >= 0)
-                da[dp++] = (char)sa[sp++];
+                da[dp++] = (char) sa[sp++];
 
             while (sp < sl) {
                 int b1 = sa[sp];
-                if (b1  >= 0) {
+                if (b1 >= 0) {
                     // 1 byte, 7 bits: 0xxxxxxx
                     if (dp >= dl)
                         return xflow(src, sp, sl, dst, dp, 1);
-                    da[dp++] = (char)b1;
+                    da[dp++] = (char) b1;
                     sp++;
                 } else if ((b1 >> 5) == -2) {
                     // 2 bytes, 11 bits: 110xxxxx 10xxxxxx
@@ -224,7 +224,10 @@
                     int b2 = sa[sp + 1];
                     if (isMalformed2(b1, b2))
                         return malformed(src, sp, dst, dp, 2);
-                    da[dp++] = (char) (((b1 << 6) ^ b2) ^ 0x0f80);
+                    da[dp++] = (char) (((b1 << 6) ^ b2)
+                                       ^
+                                       (((byte) 0xC0 << 6) ^
+                                        ((byte) 0x80 << 0)));
                     sp += 2;
                 } else if ((b1 >> 4) == -2) {
                     // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
@@ -234,7 +237,13 @@
                     int b3 = sa[sp + 2];
                     if (isMalformed3(b1, b2, b3))
                         return malformed(src, sp, dst, dp, 3);
-                    da[dp++] = (char) (((b1 << 12) ^ (b2 << 6) ^ b3) ^ 0x1f80);
+                    da[dp++] = (char)
+                        ((b1 << 12) ^
+                         (b2 <<  6) ^
+                         (b3 ^
+                          (((byte) 0xE0 << 12) ^
+                           ((byte) 0x80 <<  6) ^
+                           ((byte) 0x80 <<  0))));
                     sp += 3;
                 } else if ((b1 >> 3) == -2) {
                     // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
@@ -243,16 +252,21 @@
                     int b2 = sa[sp + 1];
                     int b3 = sa[sp + 2];
                     int b4 = sa[sp + 3];
-                    int uc = ((b1 & 0x07) << 18) |
-                             ((b2 & 0x3f) << 12) |
-                             ((b3 & 0x3f) << 06) |
-                             (b4 & 0x3f);
+                    int uc = ((b1 << 18) ^
+                              (b2 << 12) ^
+                              (b3 <<  6) ^
+                              (b4 ^
+                               (((byte) 0xF0 << 18) ^
+                                ((byte) 0x80 << 12) ^
+                                ((byte) 0x80 <<  6) ^
+                                ((byte) 0x80 <<  0))));
                     if (isMalformed4(b2, b3, b4) ||
-                        !Surrogate.neededFor(uc)) {
+                        // shortest form check
+                        !Character.isSupplementaryCodePoint(uc)) {
                         return malformed(src, sp, dst, dp, 4);
                     }
-                    da[dp++] = Surrogate.high(uc);
-                    da[dp++] = Surrogate.low(uc);
+                    da[dp++] = Character.highSurrogate(uc);
+                    da[dp++] = Character.lowSurrogate(uc);
                     sp += 4;
                 } else
                     return malformed(src, sp, dst, dp, 1);
@@ -270,8 +284,8 @@
                 if (b1 >= 0) {
                     // 1 byte, 7 bits: 0xxxxxxx
                     if (dst.remaining() < 1)
-                        return xflow(src, mark, 1);  //overflow
-                    dst.put((char)b1);
+                        return xflow(src, mark, 1); // overflow
+                    dst.put((char) b1);
                     mark++;
                 } else if ((b1 >> 5) == -2) {
                     // 2 bytes, 11 bits: 110xxxxx 10xxxxxx
@@ -280,7 +294,10 @@
                     int b2 = src.get();
                     if (isMalformed2(b1, b2))
                         return malformed(src, mark, 2);
-                    dst.put((char) (((b1 << 6) ^ b2) ^ 0x0f80));
+                    dst.put((char) (((b1 << 6) ^ b2)
+                                    ^
+                                    (((byte) 0xC0 << 6) ^
+                                     ((byte) 0x80 << 0))));
                     mark += 2;
                 } else if ((b1 >> 4) == -2) {
                     // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
@@ -290,7 +307,13 @@
                     int b3 = src.get();
                     if (isMalformed3(b1, b2, b3))
                         return malformed(src, mark, 3);
-                    dst.put((char) (((b1 << 12) ^ (b2 << 6) ^ b3) ^ 0x1f80));
+                    dst.put((char)
+                            ((b1 << 12) ^
+                             (b2 <<  6) ^
+                             (b3 ^
+                              (((byte) 0xE0 << 12) ^
+                               ((byte) 0x80 <<  6) ^
+                               ((byte) 0x80 <<  0)))));
                     mark += 3;
                 } else if ((b1 >> 3) == -2) {
                     // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
@@ -299,16 +322,21 @@
                     int b2 = src.get();
                     int b3 = src.get();
                     int b4 = src.get();
-                    int uc = ((b1 & 0x07) << 18) |
-                             ((b2 & 0x3f) << 12) |
-                             ((b3 & 0x3f) << 06) |
-                             (b4 & 0x3f);
+                    int uc = ((b1 << 18) ^
+                              (b2 << 12) ^
+                              (b3 <<  6) ^
+                              (b4 ^
+                               (((byte) 0xF0 << 18) ^
+                                ((byte) 0x80 << 12) ^
+                                ((byte) 0x80 <<  6) ^
+                                ((byte) 0x80 <<  0))));
                     if (isMalformed4(b2, b3, b4) ||
-                        !Surrogate.neededFor(uc)) { // shortest form check
+                        // shortest form check
+                        !Character.isSupplementaryCodePoint(uc)) {
                         return malformed(src, mark, 4);
                     }
-                    dst.put(Surrogate.high(uc));
-                    dst.put(Surrogate.low(uc));
+                    dst.put(Character.highSurrogate(uc));
+                    dst.put(Character.lowSurrogate(uc));
                     mark += 4;
                 } else {
                     return malformed(src, mark, 1);
@@ -366,7 +394,7 @@
             int dl = dst.arrayOffset() + dst.limit();
             int dlASCII = dp + Math.min(sl - sp, dl - dp);
 
-            //ASCII only loop
+            // ASCII only loop
             while (dp < dlASCII && sa[sp] < '\u0080')
                 da[dp++] = (byte) sa[sp++];
             while (sp < sl) {
@@ -380,7 +408,7 @@
                     // 2 bytes, 11 bits
                     if (dl - dp < 2)
                         return overflow(src, sp, dst, dp);
-                    da[dp++] = (byte)(0xc0 | ((c >> 06)));
+                    da[dp++] = (byte)(0xc0 | (c >> 6));
                     da[dp++] = (byte)(0x80 | (c & 0x3f));
                 } else if (Character.isSurrogate(c)) {
                     // Have a surrogate pair
@@ -395,7 +423,7 @@
                         return overflow(src, sp, dst, dp);
                     da[dp++] = (byte)(0xf0 | ((uc >> 18)));
                     da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
-                    da[dp++] = (byte)(0x80 | ((uc >> 06) & 0x3f));
+                    da[dp++] = (byte)(0x80 | ((uc >>  6) & 0x3f));
                     da[dp++] = (byte)(0x80 | (uc & 0x3f));
                     sp++;  // 2 chars
                 } else {
@@ -403,7 +431,7 @@
                     if (dl - dp < 3)
                         return overflow(src, sp, dst, dp);
                     da[dp++] = (byte)(0xe0 | ((c >> 12)));
-                    da[dp++] = (byte)(0x80 | ((c >> 06) & 0x3f));
+                    da[dp++] = (byte)(0x80 | ((c >>  6) & 0x3f));
                     da[dp++] = (byte)(0x80 | (c & 0x3f));
                 }
                 sp++;
@@ -427,7 +455,7 @@
                     // 2 bytes, 11 bits
                     if (dst.remaining() < 2)
                         return overflow(src, mark);
-                    dst.put((byte)(0xc0 | ((c >> 06))));
+                    dst.put((byte)(0xc0 | (c >> 6)));
                     dst.put((byte)(0x80 | (c & 0x3f)));
                 } else if (Character.isSurrogate(c)) {
                     // Have a surrogate pair
@@ -442,15 +470,15 @@
                         return overflow(src, mark);
                     dst.put((byte)(0xf0 | ((uc >> 18))));
                     dst.put((byte)(0x80 | ((uc >> 12) & 0x3f)));
-                    dst.put((byte)(0x80 | ((uc >> 06) & 0x3f)));
+                    dst.put((byte)(0x80 | ((uc >>  6) & 0x3f)));
                     dst.put((byte)(0x80 | (uc & 0x3f)));
-                    mark++;  //2 chars
+                    mark++;  // 2 chars
                 } else {
                     // 3 bytes, 16 bits
                     if (dst.remaining() < 3)
                         return overflow(src, mark);
                     dst.put((byte)(0xe0 | ((c >> 12))));
-                    dst.put((byte)(0x80 | ((c >> 06) & 0x3f)));
+                    dst.put((byte)(0x80 | ((c >>  6) & 0x3f)));
                     dst.put((byte)(0x80 | (c & 0x3f)));
                 }
                 mark++;
--- a/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -93,8 +93,8 @@
                 if (dst.remaining() < 4)
                     return CoderResult.OVERFLOW;
                 mark += 2;
-                put(Surrogate.high(d), dst);
-                put(Surrogate.low(d), dst);
+                put(Character.highSurrogate(d), dst);
+                put(Character.lowSurrogate(d), dst);
             }
             return CoderResult.UNDERFLOW;
         } finally {
--- a/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java	Wed Jul 05 17:17:57 2017 +0200
@@ -34,7 +34,6 @@
 import java.nio.charset.CoderResult;
 import java.util.Arrays;
 import sun.nio.cs.HistoricallyNamedCharset;
-import sun.nio.cs.Surrogate;
 import static sun.nio.cs.CharsetMapping.*;
 
 public class EUC_TW extends Charset implements HistoricallyNamedCharset
@@ -159,8 +158,8 @@
                 c1[0] = c;
                 return c1;
             } else {
-                c2[0] = Surrogate.high(0x20000 + c);
-                c2[1] = Surrogate.low(0x20000 + c);
+                c2[0] = Character.highSurrogate(0x20000 + c);
+                c2[1] = Character.lowSurrogate(0x20000 + c);
                 return c2;
             }
         }
@@ -441,7 +440,7 @@
         }
 
         static int encode(char hi, char low, byte[] bb) {
-            int c = Surrogate.toUCS4(hi, low);
+            int c = Character.toCodePoint(hi, low);
             if ((c & 0xf0000) != 0x20000)
                 return -1;
             c -= 0x20000;
--- a/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java	Wed Jul 05 17:17:57 2017 +0200
@@ -12628,7 +12628,7 @@
                     if (Character.isSurrogate(c)) {
                         if ((condensedKey=sgp.parse(c, sa, sp, sl)) < 0)
                             return sgp.error();
-                        // Surogate.toUCS4 looks like
+                        // Character.toCodePoint looks like
                         // (((high & 0x3ff) << 10) | (low & 0x3ff)) + 0x10000;
                         // so we add (0x2e248 - 0x10000) to get the "key".
                         condensedKey += 0x1E248;
--- a/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java	Wed Jul 05 17:17:57 2017 +0200
@@ -36,7 +36,6 @@
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
 import sun.nio.cs.HistoricallyNamedCharset;
-import sun.nio.cs.Surrogate;
 
 public class IBM33722
     extends Charset
--- a/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java	Wed Jul 05 17:17:57 2017 +0200
@@ -36,7 +36,6 @@
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
 import sun.nio.cs.HistoricallyNamedCharset;
-import sun.nio.cs.Surrogate;
 
 public class IBM964
     extends Charset
--- a/jdk/src/share/classes/sun/security/krb5/Credentials.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -33,9 +33,7 @@
 
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.ccache.CredentialsCache;
-import sun.security.krb5.internal.ktab.*;
 import sun.security.krb5.internal.crypto.EType;
-import java.io.File;
 import java.io.IOException;
 import java.util.Date;
 import java.net.InetAddress;
@@ -506,59 +504,6 @@
         return result;
     }
 
-
-    /**
-     * Gets service credential from key table. The credential is used to
-     * decrypt the received client message
-     * and authenticate the client by verifying the client's credential.
-     *
-     * @param serviceName the name of service, using format component@realm
-     * @param keyTabFile the file of key table.
-     * @return a <code>KrbCreds</code> object.
-     */
-    public static Credentials getServiceCreds(String serviceName,
-                                              File keyTabFile) {
-        EncryptionKey k = null;
-        PrincipalName service = null;
-        Credentials result = null;
-        try {
-            service = new PrincipalName(serviceName);
-            if (service.getRealm() == null) {
-                String realm = Config.getInstance().getDefaultRealm();
-                if (realm == null) {
-                    return null;
-                } else {
-                    service.setRealm(realm);
-                }
-            }
-        } catch (RealmException e) {
-            if (DEBUG) {
-                e.printStackTrace();
-            }
-            return null;
-        } catch (KrbException e) {
-            if (DEBUG) {
-                e.printStackTrace();
-            }
-            return null;
-        }
-        KeyTab kt;
-        if (keyTabFile == null) {
-            kt = KeyTab.getInstance();
-        } else {
-            kt = KeyTab.getInstance(keyTabFile);
-        }
-        if ((kt != null) && (kt.findServiceEntry(service))) {
-            k = kt.readServiceKey(service);
-            result = new Credentials(null, service, null, null, null,
-                                     null, null, null, null, null);
-            result.serviceKey = k;
-        }
-        return result;
-    }
-
-
-
     /**
      * Acquires credentials for a specified service using initial credential.
      * When the service has a different realm
--- a/jdk/src/share/classes/sun/security/krb5/EncryptedData.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptedData.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -336,38 +336,29 @@
     }
 
     /**
-     * Reset data stream after decryption, remove redundant bytes.
+     * Reset asn.1 data stream after decryption, remove redundant bytes.
      * @param data the decrypted data from decrypt().
-     * @param encoded true if the encrypted data is ASN1 encoded data,
-     * false if the encrypted data is not ASN1 encoded data.
      * @return the reset byte array which holds exactly one asn1 datum
      * including its tag and length.
      *
      */
-    public byte[] reset(byte[] data, boolean encoded) {
+    public byte[] reset(byte[] data) {
         byte[]  bytes = null;
-        // if it is encoded data, we use length field to
+        // for asn.1 encoded data, we use length field to
         // determine the data length and remove redundant paddings.
-        if (encoded) {
-            if ((data[1] & 0xFF) < 128) {
-                bytes = new byte[data[1] + 2];
-                System.arraycopy(data, 0, bytes, 0, data[1] + 2);
-            } else
-                if ((data[1] & 0xFF) > 128) {
-                    int len = data[1] & (byte)0x7F;
-                    int result = 0;
-                    for (int i = 0; i < len; i++) {
-                        result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1));
-                    }
-                    bytes = new byte[result + len + 2];
-                    System.arraycopy(data, 0, bytes, 0, result + len + 2);
+        if ((data[1] & 0xFF) < 128) {
+            bytes = new byte[data[1] + 2];
+            System.arraycopy(data, 0, bytes, 0, data[1] + 2);
+        } else {
+            if ((data[1] & 0xFF) > 128) {
+                int len = data[1] & (byte)0x7F;
+                int result = 0;
+                for (int i = 0; i < len; i++) {
+                    result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1));
                 }
-        } else {
-            // if it is not encoded, which happens in GSS tokens,
-            // we remove padding data according to padding pattern.
-            bytes = new byte[data.length - data[data.length - 1]];
-            System.arraycopy(data, 0, bytes, 0,
-                             data.length - data[data.length - 1]);
+                bytes = new byte[result + len + 2];
+                System.arraycopy(data, 0, bytes, 0, result + len + 2);
+            }
         }
         return bytes;
     }
--- a/jdk/src/share/classes/sun/security/krb5/KrbApRep.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApRep.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -130,7 +130,7 @@
 
         byte[] temp = rep.encPart.decrypt(tgs_creds.key,
             KeyUsage.KU_ENC_AP_REP_PART);
-        byte[] enc_ap_rep_part = rep.encPart.reset(temp, true);
+        byte[] enc_ap_rep_part = rep.encPart.reset(temp);
 
         encoding = new DerValue(enc_ap_rep_part);
         encPart = new EncAPRepPart(encoding);
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -279,14 +279,14 @@
 
         byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey,
             KeyUsage.KU_TICKET);
-        byte[] temp = apReqMessg.ticket.encPart.reset(bytes, true);
+        byte[] temp = apReqMessg.ticket.encPart.reset(bytes);
         EncTicketPart enc_ticketPart = new EncTicketPart(temp);
 
         checkPermittedEType(enc_ticketPart.key.getEType());
 
         byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key,
             KeyUsage.KU_AP_REQ_AUTHENTICATOR);
-        byte[] temp2 = apReqMessg.authenticator.reset(bytes2, true);
+        byte[] temp2 = apReqMessg.authenticator.reset(bytes2);
         authenticator = new Authenticator(temp2);
         ctime = authenticator.ctime;
         cusec = authenticator.cusec;
--- a/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -95,7 +95,7 @@
 
         byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey,
             KeyUsage.KU_ENC_AS_REP_PART);
-        byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes, true);
+        byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes);
 
         encoding = new DerValue(enc_as_rep_part);
         EncASRepPart enc_part = new EncASRepPart(encoding);
--- a/jdk/src/share/classes/sun/security/krb5/KrbCred.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbCred.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -130,7 +130,7 @@
 
         byte[] temp = credMessg.encPart.decrypt(key,
             KeyUsage.KU_ENC_KRB_CRED_PART);
-        byte[] plainText = credMessg.encPart.reset(temp, true);
+        byte[] plainText = credMessg.encPart.reset(temp);
         DerValue encoding = new DerValue(plainText);
         EncKrbCredPart encPart = new EncKrbCredPart(encoding);
 
--- a/jdk/src/share/classes/sun/security/krb5/KrbPriv.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbPriv.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -31,7 +31,6 @@
 
 package sun.security.krb5;
 
-import sun.security.krb5.EncryptionKey;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.*;
 import sun.security.util.*;
@@ -159,7 +158,7 @@
 
                                byte[] bytes = krb_priv.encPart.decrypt(key,
                                    KeyUsage.KU_ENC_KRB_PRIV_PART);
-                               byte[] temp = krb_priv.encPart.reset(bytes, true);
+                               byte[] temp = krb_priv.encPart.reset(bytes);
                                DerValue ref = new DerValue(temp);
                                EncKrbPrivPart enc_part = new EncKrbPrivPart(ref);
 
--- a/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -79,7 +79,7 @@
             tgsReq.usedSubkey() ? KeyUsage.KU_ENC_TGS_REP_PART_SUBKEY :
             KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
 
-        byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes, true);
+        byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes);
         ref = new DerValue(enc_tgs_rep_part);
         EncTGSRepPart enc_part = new EncTGSRepPart(ref);
         rep.ticket.sname.setRealm(rep.ticket.realm);
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Wed Jul 05 17:17:57 2017 +0200
@@ -185,20 +185,20 @@
     // is set to false.
 
     private static final int[] BUILTIN_ETYPES = new int[] {
-        EncryptedData.ETYPE_DES_CBC_MD5,
-        EncryptedData.ETYPE_DES_CBC_CRC,
+        EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
+        EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+        EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
         EncryptedData.ETYPE_ARCFOUR_HMAC,
-        EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
-        EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
-        EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
+        EncryptedData.ETYPE_DES_CBC_CRC,
+        EncryptedData.ETYPE_DES_CBC_MD5,
     };
 
     private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
-        EncryptedData.ETYPE_DES_CBC_MD5,
-        EncryptedData.ETYPE_DES_CBC_CRC,
+        EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+        EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
         EncryptedData.ETYPE_ARCFOUR_HMAC,
-        EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
-        EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+        EncryptedData.ETYPE_DES_CBC_CRC,
+        EncryptedData.ETYPE_DES_CBC_MD5,
     };
 
 
@@ -217,8 +217,8 @@
             result = BUILTIN_ETYPES;
         }
         if (!ALLOW_WEAK_CRYPTO) {
-            // The first 2 etypes are now weak ones
-            return Arrays.copyOfRange(result, 2, result.length);
+            // The last 2 etypes are now weak ones
+            return Arrays.copyOfRange(result, 0, result.length - 2);
         }
         return result;
     }
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, 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
@@ -228,37 +228,6 @@
     }
 
     /**
-     * Reads the service key from the keytab file.
-     * @param service the PrincipalName of the requested service.
-     * @return the last service key in the keytab with the highest kvno
-     */
-    public EncryptionKey readServiceKey(PrincipalName service) {
-        KeyTabEntry entry = null;
-        EncryptionKey key = null;
-        if (entries != null) {
-            // Find latest entry for this service that has an etype
-            // that has been configured for use
-            for (int i = entries.size()-1; i >= 0; i--) {
-                entry = entries.elementAt(i);
-                if (entry.service.match(service)) {
-                    if (EType.isSupported(entry.keyType)) {
-                        if (key == null ||
-                                entry.keyVersion > key.getKeyVersionNumber()) {
-                            key = new EncryptionKey(entry.keyblock,
-                                             entry.keyType,
-                                             new Integer(entry.keyVersion));
-                        }
-                    } else if (DEBUG) {
-                        System.out.println("Found unsupported keytype (" +
-                            entry.keyType + ") for " + service);
-                    }
-                }
-            }
-        }
-        return key;
-    }
-
-    /**
      * Reads all keys for a service from the keytab file that have
      * etypes that have been configured for use. If there are multiple
      * keys with same etype, the one with the highest kvno is returned.
@@ -309,7 +278,7 @@
         Arrays.sort(retVal, new Comparator<EncryptionKey>() {
             @Override
             public int compare(EncryptionKey o1, EncryptionKey o2) {
-                if (etypes != null && etypes != EType.getBuiltInDefaults()) {
+                if (etypes != null) {
                     int o1EType = o1.getEType();
                     int o2EType = o2.getEType();
                     if (o1EType != o2EType) {
@@ -320,6 +289,9 @@
                                 return 1;
                             }
                         }
+                        // Neither o1EType nor o2EType in default_tkt_enctypes,
+                        // therefore won't be used in AS-REQ. We do not care
+                        // about their order, use kvno is OK.
                     }
                 }
                 return o2.getKeyVersionNumber().intValue()
--- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, 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
@@ -180,24 +180,15 @@
         String alias;
     };
 
-    private static class KeyId {
-        byte[] keyId;
-
-        KeyId(byte[] keyId) {
+    // A certificate with its PKCS #9 attributes
+    private static class CertEntry {
+        final X509Certificate cert;
+        final byte[] keyId;
+        final String alias;
+        CertEntry(X509Certificate cert, byte[] keyId, String alias) {
+            this.cert = cert;
             this.keyId = keyId;
-        }
-        public int hashCode() {
-            int hash = 0;
-
-            for (int i = 0; i < keyId.length; i++)
-                hash += keyId[i];
-            return hash;
-        }
-        public boolean equals(Object obj) {
-            if (!(obj instanceof KeyId))
-                return false;
-            KeyId that = (KeyId)obj;
-            return (Arrays.equals(this.keyId, that.keyId));
+            this.alias = alias;
         }
     }
 
@@ -209,7 +200,9 @@
                                 new Hashtable<String, KeyEntry>();
 
     private ArrayList<KeyEntry> keyList = new ArrayList<KeyEntry>();
-    private LinkedHashMap<Object, X509Certificate> certs = new LinkedHashMap<Object, X509Certificate>();
+    private LinkedHashMap<X500Principal, X509Certificate> certsMap =
+            new LinkedHashMap<X500Principal, X509Certificate>();
+    private ArrayList<CertEntry> certEntries = new ArrayList<CertEntry>();
 
     /**
      * Returns the key associated with the given alias, using the given
@@ -472,6 +465,15 @@
         KeyEntry entry = new KeyEntry();
         entry.date = new Date();
 
+        try {
+            // set the keyId to current date
+            entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8");
+        } catch (UnsupportedEncodingException ex) {
+            // Won't happen
+        }
+        // set the alias
+        entry.alias = alias.toLowerCase();
+
         entry.protectedPrivKey = key.clone();
         if (chain != null) {
            entry.chain = chain.clone();
@@ -1027,10 +1029,9 @@
                 // All Certs should have a unique friendlyName.
                 // This change is made to meet NSS requirements.
                 byte[] bagAttrs = null;
-                String friendlyName = cert.getSubjectX500Principal().getName();
                 if (i == 0) {
                     // Only End-Entity Cert should have a localKeyId.
-                    bagAttrs = getBagAttributes(friendlyName, entry.keyId);
+                    bagAttrs = getBagAttributes(entry.alias, entry.keyId);
                 } else {
                     // Trusted root CA certs and Intermediate CA certs do not
                     // need to have a localKeyId, and hence localKeyId is null
@@ -1038,7 +1039,8 @@
                     // NSS pkcs12 library requires trusted CA certs in the
                     // certificate chain to have unique or null localKeyID.
                     // However, IE/OpenSSL do not impose this restriction.
-                    bagAttrs = getBagAttributes(friendlyName, null);
+                    bagAttrs = getBagAttributes(
+                            cert.getSubjectX500Principal().getName(), null);
                 }
                 if (bagAttrs != null) {
                     safeBag.write(bagAttrs);
@@ -1333,24 +1335,49 @@
             if (entry.keyId != null) {
                 ArrayList<X509Certificate> chain =
                                 new ArrayList<X509Certificate>();
-                X509Certificate cert = certs.get(new KeyId(entry.keyId));
+                X509Certificate cert = findMatchedCertificate(entry);
                 while (cert != null) {
                     chain.add(cert);
                     X500Principal issuerDN = cert.getIssuerX500Principal();
                     if (issuerDN.equals(cert.getSubjectX500Principal())) {
                         break;
                     }
-                    cert = certs.get(issuerDN);
+                    cert = certsMap.get(issuerDN);
                 }
                 /* Update existing KeyEntry in entries table */
                 if (chain.size() > 0)
                     entry.chain = chain.toArray(new Certificate[chain.size()]);
             }
         }
-        certs.clear();
+        certEntries.clear();
+        certsMap.clear();
         keyList.clear();
     }
 
+    /**
+     * Locates a matched CertEntry from certEntries, and returns its cert.
+     * @param entry the KeyEntry to match
+     * @return a certificate, null if not found
+     */
+    private X509Certificate findMatchedCertificate(KeyEntry entry) {
+        CertEntry keyIdMatch = null;
+        CertEntry aliasMatch = null;
+        for (CertEntry ce: certEntries) {
+            if (Arrays.equals(entry.keyId, ce.keyId)) {
+                keyIdMatch = ce;
+                if (entry.alias.equalsIgnoreCase(ce.alias)) {
+                    // Full match!
+                    return ce.cert;
+                }
+            } else if (entry.alias.equalsIgnoreCase(ce.alias)) {
+                aliasMatch = ce;
+            }
+        }
+        // keyId match first, for compatibility
+        if (keyIdMatch != null) return keyIdMatch.cert;
+        else if (aliasMatch != null) return aliasMatch.cert;
+        else return null;
+    }
 
     private void loadSafeContents(DerInputStream stream, char[] password)
         throws IOException, NoSuchAlgorithmException, CertificateException
@@ -1491,19 +1518,12 @@
                         keyId = "01".getBytes("UTF8");
                     }
                 }
-                if (keyId != null) {
-                    KeyId keyid = new KeyId(keyId);
-                    if (!certs.containsKey(keyid))
-                        certs.put(keyid, cert);
-                }
-                if (alias != null) {
-                    if (!certs.containsKey(alias))
-                        certs.put(alias, cert);
-                }
+                certEntries.add(new CertEntry(cert, keyId, alias));
                 X500Principal subjectDN = cert.getSubjectX500Principal();
                 if (subjectDN != null) {
-                    if (!certs.containsKey(subjectDN))
-                        certs.put(subjectDN, cert);
+                    if (!certsMap.containsKey(subjectDN)) {
+                        certsMap.put(subjectDN, cert);
+                    }
                 }
             }
         }
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java	Wed Jul 05 17:17:57 2017 +0200
@@ -212,7 +212,7 @@
             byte[] bytes = encPart.decrypt(secretKey, KeyUsage.KU_TICKET);
 
             // Reset data stream after decryption, remove redundant bytes
-            byte[] temp = encPart.reset(bytes, true);
+            byte[] temp = encPart.reset(bytes);
             EncTicketPart encTicketPart = new EncTicketPart(temp);
 
             // Record the Kerberos Principals
--- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, 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
@@ -27,7 +27,7 @@
 
 import java.io.*;
 import java.security.*;
-import java.security.interfaces.*;
+import java.util.Arrays;
 
 import javax.net.ssl.*;
 
@@ -128,8 +128,8 @@
                "are not supported for TLS Kerberos cipher suites");
         }
 
-         // Decrypt premaster secret
-         try {
+        // Decrypt premaster secret
+        try {
             EncryptedData data = new EncryptedData(sessionKey.getEType(),
                         null /* optional kvno */, encrypted);
 
@@ -141,8 +141,25 @@
                  }
             }
 
-            // Reset data stream after decryption, remove redundant bytes
-            preMaster =  data.reset(temp, false);
+            // Remove padding bytes after decryption. Only DES and DES3 have
+            // paddings and we don't support DES3 in TLS (see above)
+
+            if (temp.length == 52 &&
+                    data.getEType() == EncryptedData.ETYPE_DES_CBC_CRC) {
+                // For des-cbc-crc, 4 paddings. Value can be 0x04 or 0x00.
+                if (paddingByteIs(temp, 52, (byte)4) ||
+                        paddingByteIs(temp, 52, (byte)0)) {
+                    temp = Arrays.copyOf(temp, 48);
+                }
+            } else if (temp.length == 56 &&
+                    data.getEType() == EncryptedData.ETYPE_DES_CBC_MD5) {
+                // For des-cbc-md5, 8 paddings with 0x08, or no padding
+                if (paddingByteIs(temp, 56, (byte)8)) {
+                    temp = Arrays.copyOf(temp, 48);
+                }
+            }
+
+            preMaster = temp;
 
             protocolVersion = ProtocolVersion.valueOf(preMaster[0],
                  preMaster[1]);
@@ -191,6 +208,19 @@
         }
     }
 
+    /**
+     * Checks if all paddings of data are b
+     * @param data the block with padding
+     * @param len length of data, >= 48
+     * @param b expected padding byte
+     */
+    private static boolean paddingByteIs(byte[] data, int len, byte b) {
+        for (int i=48; i<len; i++) {
+            if (data[i] != b) return false;
+        }
+        return true;
+    }
+
     /*
      * Used by server to generate premaster secret in case of
      * problem decoding ticket.
--- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java	Wed Jul 05 17:17:57 2017 +0200
@@ -438,8 +438,12 @@
         // c may be null here.
         String clipString = "...";
         availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString);
+        if (availTextWidth <= 0) {
+            //can not fit any characters
+            return clipString;
+        }
+
         boolean needsTextLayout;
-
         synchronized (charsBufferLock) {
             int stringLength = syncCharsBuffer(string);
             needsTextLayout =
--- a/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/share/native/sun/awt/image/BufImgSurfaceData.c	Wed Jul 05 17:17:57 2017 +0200
@@ -111,6 +111,10 @@
 {
     BufImgSDOps *bisdo =
         (BufImgSDOps*)SurfaceData_InitOps(env, bisd, sizeof(BufImgSDOps));
+    if (bisdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+        return;
+    }
     bisdo->sdOps.Lock = BufImg_Lock;
     bisdo->sdOps.GetRasInfo = BufImg_GetRasInfo;
     bisdo->sdOps.Release = BufImg_Release;
--- a/jdk/src/solaris/bin/java_md.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/bin/java_md.c	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, 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
@@ -183,13 +183,9 @@
 }
 
 void
-CreateExecutionEnvironment(int *_argcp,
-                           char ***_argvp,
-                           char jrepath[],
-                           jint so_jrepath,
-                           char jvmpath[],
-                           jint so_jvmpath,
-                           char **original_argv) {
+CreateExecutionEnvironment(int *pargc, char ***pargv,
+                           char jrepath[], jint so_jrepath,
+                           char jvmpath[], jint so_jvmpath) {
   /*
    * First, determine if we are running the desired data model.  If we
    * are running the desired data model, all the error messages
@@ -200,18 +196,17 @@
    * os/processor combination has dual mode capabilities.
    */
 
-    int original_argc = *_argcp;
     jboolean jvmpathExists;
 
     /* Compute/set the name of the executable */
-    SetExecname(*_argvp);
+    SetExecname(*pargv);
 
     /* Check data model flags, and exec process, if needed */
     {
       char *arch        = (char *)GetArch(); /* like sparc or sparcv9 */
       char * jvmtype    = NULL;
-      int argc          = *_argcp;
-      char **argv       = original_argv;
+      int  argc         = *pargc;
+      char **argv       = *pargv;
 
       int running       = CURRENT_DATA_MODEL;
 
@@ -233,7 +228,7 @@
       { /* open new scope to declare local variables */
         int i;
 
-        newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
+        newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*));
         newargv[newargc++] = argv[0];
 
         /* scan for data model arguments and remove from argument list;
@@ -293,7 +288,11 @@
         }
 
         jvmpath[0] = '\0';
-        jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
+        jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE);
+        if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+            JLI_ReportErrorMessage(CFG_ERROR9);
+            exit(4);
+        }
 
         if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
           JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
@@ -309,7 +308,9 @@
         if (running != wanted) {
           /* Find out where the JRE is that we will be using. */
           if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) {
-            goto EndDataModelSpeculate;
+            /* give up and let other code report error message */
+            JLI_ReportErrorMessage(JRE_ERROR2, wanted);
+            exit(1);
           }
 
           /*
@@ -317,16 +318,21 @@
            * selection options.
            */
           if (ReadKnownVMs(jrepath, GetArchPath(wanted), JNI_TRUE) < 1) {
-            goto EndDataModelSpeculate;
+            /* give up and let other code report error message */
+            JLI_ReportErrorMessage(JRE_ERROR2, wanted);
+            exit(1);
           }
           jvmpath[0] = '\0';
-          jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
+          jvmtype = CheckJvmType(pargc, pargv, JNI_TRUE);
+          if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+            JLI_ReportErrorMessage(CFG_ERROR9);
+            exit(4);
+          }
+
           /* exec child can do error checking on the existence of the path */
           jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted));
 
         }
-      EndDataModelSpeculate: /* give up and let other code report error message */
-        ;
 #else
         JLI_ReportErrorMessage(JRE_ERROR2, wanted);
         exit(1);
@@ -398,9 +404,9 @@
     struct stat s;
 
     if (JLI_StrChr(jvmtype, '/')) {
-        sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype);
     } else {
-        sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
     }
 
     JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
@@ -424,26 +430,24 @@
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
-        sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
+        JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
         if (access(libjava, F_OK) == 0) {
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
 
         /* Does the app ship a private JRE in <apphome>/jre directory? */
-        sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
+        JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch);
         if (access(libjava, F_OK) == 0) {
             JLI_StrCat(path, "/jre");
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
     }
 
     if (!speculative)
       JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
-
- found:
-    JLI_TraceLauncher("JRE path is %s\n", path);
-    return JNI_TRUE;
 }
 
 jboolean
@@ -463,14 +467,18 @@
       int location;
 
       fp = fopen(jvmpath, "r");
-      if(fp == NULL)
-        goto error;
+      if (fp == NULL) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+      }
 
       /* read in elf header */
       count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
       fclose(fp);
-      if(count < 1)
-        goto error;
+      if (count < 1) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+      }
 
       /*
        * Check for running a server vm (compiled with -xarch=v8plus)
@@ -481,41 +489,42 @@
        * does not have to be checked for in binaries with an LP64 data
        * model.
        */
-      if(elf_head.e_machine == EM_SPARC32PLUS) {
+      if (elf_head.e_machine == EM_SPARC32PLUS) {
         char buf[257];  /* recommended buffer size from sysinfo man
                            page */
         long length;
         char* location;
 
         length = sysinfo(SI_ISALIST, buf, 257);
-        if(length > 0) {
-          location = JLI_StrStr(buf, "sparcv8plus ");
-          if(location == NULL) {
+        if (length > 0) {
+            location = JLI_StrStr(buf, "sparcv8plus ");
+          if (location == NULL) {
             JLI_ReportErrorMessage(JVM_ERROR3);
             return JNI_FALSE;
           }
         }
       }
 #endif
-      JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
-      goto error;
+        JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
     }
 
     ifn->CreateJavaVM = (CreateJavaVM_t)
-      dlsym(libjvm, "JNI_CreateJavaVM");
-    if (ifn->CreateJavaVM == NULL)
-        goto error;
+        dlsym(libjvm, "JNI_CreateJavaVM");
+    if (ifn->CreateJavaVM == NULL) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+    }
 
     ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
         dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
-    if (ifn->GetDefaultJavaVMInitArgs == NULL)
-      goto error;
+    if (ifn->GetDefaultJavaVMInitArgs == NULL) {
+        JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
+        return JNI_FALSE;
+    }
 
     return JNI_TRUE;
-
-error:
-    JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
-    return JNI_FALSE;
 }
 
 /*
@@ -575,7 +584,7 @@
     char name[PATH_MAX + 2], *real;
 
     if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1)  > PATH_MAX) return 0;
-    sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
+    JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd);
     if (!ProgramExists(name)) return 0;
     real = JLI_MemAlloc(PATH_MAX + 2);
     if (!realpath(name, real))
@@ -622,7 +631,7 @@
         else {
             /* relative path element */
             char dir[2*PATH_MAX];
-            sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
+            JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
                     FILE_SEPARATOR, s);
             result = Resolve(dir, program);
         }
@@ -746,7 +755,7 @@
     if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX)
         return (0);     /* Silently reject "impossibly" long paths */
 
-    sprintf(buffer, "%s/%s/bin/java", path, dir);
+    JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir);
     return ((access(buffer, X_OK) == 0) ? 1 : 0);
 }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1053,10 +1053,28 @@
         return peer;
     }
 
+    private static Boolean sunAwtDisableGtkFileDialogs = null;
+
+    /**
+     * Returns the value of "sun.awt.disableGtkFileDialogs" property. Default
+     * value is {@code false}.
+     */
+    public synchronized static boolean getSunAwtDisableGtkFileDialogs() {
+        if (sunAwtDisableGtkFileDialogs == null) {
+            sunAwtDisableGtkFileDialogs =
+                getBooleanSystemProperty("sun.awt.disableGtkFileDialogs");
+        }
+        return sunAwtDisableGtkFileDialogs.booleanValue();
+    }
+
     public FileDialogPeer createFileDialog(FileDialog target) {
+        FileDialogPeer peer = null;
         // The current GtkFileChooser is available from GTK+ 2.4
-        FileDialogPeer peer = checkGtkVersion(2, 4, 0) ? new GtkFileDialogPeer(
-                target) : new XFileDialogPeer(target);
+        if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) {
+            peer = new GtkFileDialogPeer(target);
+        } else {
+            peer = new XFileDialogPeer(target);
+        }
         targetCreatedPeer(target, peer);
         return peer;
     }
@@ -1201,14 +1219,6 @@
         }
     }
 
-    static String getSystemProperty(final String name) {
-        return (String)AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    return System.getProperty(name);
-                }
-            });
-    }
-
     public PrintJob getPrintJob(final Frame frame, final String doctitle,
                                 final Properties props) {
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java	Wed Jul 05 17:17:57 2017 +0200
@@ -778,8 +778,8 @@
                                                           x, y,
                                                           xbe.get_x_root(),
                                                           xbe.get_y_root(),
-                                                          clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
-                                                          3,button==4 ?  -1 : 1);
+                                                          1,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
+                                                          3,button==4 ?  -1*clickCount : 1*clickCount);
                 postEventToEventQueue(mwe);
             }
         }
--- a/jdk/src/solaris/demo/jni/Poller/Poller.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/demo/jni/Poller/Poller.c	Wed Jul 05 17:17:57 2017 +0200
@@ -160,10 +160,10 @@
   return -1;
 }
 
-#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" ## str)
-#define STATE_EXCEPTION(str)  throwIllegalStateException(env, "Poller:" ## str)
+#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" str)
+#define STATE_EXCEPTION(str)  throwIllegalStateException(env, "Poller:" str)
 #define INTERRUPT_EXCEPTION(str) throwInterruptedIOException(env, \
-                                                             "Poller:" ## str)
+                                                             "Poller:" str)
 jint addfd(JNIEnv *, ioevent_t *, jint, jshort);
 jint removefd(JNIEnv *, ioevent_t *, jint);
 
--- a/jdk/src/solaris/native/java/net/NetworkInterface.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/native/java/net/NetworkInterface.c	Wed Jul 05 17:17:57 2017 +0200
@@ -23,6 +23,7 @@
  * questions.
  */
 
+
 #include <errno.h>
 #include <strings.h>
 #include <netinet/in.h>
@@ -33,23 +34,23 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
+
 #ifdef __solaris__
 #include <sys/dlpi.h>
 #include <fcntl.h>
 #include <stropts.h>
+#include <sys/sockio.h>
 #endif
+
 #ifdef __linux__
 #include <sys/ioctl.h>
 #include <bits/ioctls.h>
 #include <linux/sockios.h>
 #include <sys/utsname.h>
 #include <stdio.h>
-#else
-#include <sys/sockio.h>
 #endif
 
 #ifdef __linux__
-#define ifr_index ifr_ifindex
 #define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
 #endif
 
@@ -108,20 +109,41 @@
 static jfieldID ni_ib4broadcastID;
 static jfieldID ni_ib4maskID;
 
+/** Private methods declarations **/
 static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
+static int     getFlags0(JNIEnv *env, jstring  ifname);
 
-static netif *enumInterfaces(JNIEnv *env);
-static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs);
+static netif  *enumInterfaces(JNIEnv *env);
+static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
+
 #ifdef AF_INET6
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs);
+static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
 #endif
 
-static netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index,
-                    int family, struct sockaddr *new_addrP, int new_addrlen,
-                    short prefix);
-static void freeif(netif *ifs);
-static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname);
-static short getSubnet(JNIEnv *env, const char *ifname);
+static netif  *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
+static void    freeif(netif *ifs);
+
+static int     openSocket(JNIEnv *env, int proto);
+static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
+
+
+static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
+static short   getSubnet(JNIEnv *env, int sock, const char *ifname);
+static int     getIndex(int sock, const char *ifname);
+
+static int     getFlags(JNIEnv *env, int sock, const char *ifname);
+static int     getMacAddress(JNIEnv *env, int sock,  const char* ifname, const struct in_addr* addr, unsigned char *buf);
+static int     getMTU(JNIEnv *env, int sock, const char *ifname);
+
+
+
+#ifdef __solaris__
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
+static int    getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
+#endif
+
+
+/******************* Java entry points *****************************/
 
 /*
  * Class:     java_net_NetworkInterface
@@ -172,7 +194,7 @@
 
     netif *ifs, *curr;
     jboolean isCopy;
-    const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+    const char* name_utf;
     jobject obj = NULL;
 
     ifs = enumInterfaces(env);
@@ -180,6 +202,8 @@
         return NULL;
     }
 
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
     /*
      * Search the list of interface based on name
      */
@@ -253,12 +277,13 @@
     (JNIEnv *env, jclass cls, jobject iaObj) {
 
     netif *ifs, *curr;
+
 #ifdef AF_INET6
-    int family = (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4?
-        AF_INET : AF_INET6;
+    int family = (  (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4 ) ? AF_INET : AF_INET6;
 #else
-    int family = AF_INET;
+    int family =  AF_INET;
 #endif
+
     jobject obj = NULL;
     jboolean match = JNI_FALSE;
 
@@ -390,18 +415,169 @@
     return netIFArr;
 }
 
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    isUp0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    isP2P0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return (ret & IFF_POINTOPOINT) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    isLoopback0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return (ret & IFF_LOOPBACK) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    supportsMulticast0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
+    int ret = getFlags0(env, name);
+    return (ret & IFF_MULTICAST) ? JNI_TRUE :  JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    getMacAddr0
+ * Signature: ([bLjava/lang/String;I)[b
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
+    jint addr;
+    jbyte caddr[4];
+    struct in_addr iaddr;
+    jbyteArray ret = NULL;
+    unsigned char mac[16];
+    int len;
+    int sock;
+    jboolean isCopy;
+    const char* name_utf;
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+       (*env)->ReleaseStringUTFChars(env, name, name_utf);
+       return JNI_FALSE;
+    }
+
+
+    if (!IS_NULL(addrArray)) {
+       (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+       addr = ((caddr[0]<<24) & 0xff000000);
+       addr |= ((caddr[1] <<16) & 0xff0000);
+       addr |= ((caddr[2] <<8) & 0xff00);
+       addr |= (caddr[3] & 0xff);
+       iaddr.s_addr = htonl(addr);
+       len = getMacAddress(env, sock, name_utf, &iaddr, mac);
+    } else {
+       len = getMacAddress(env, sock, name_utf,NULL, mac);
+    }
+    if (len > 0) {
+       ret = (*env)->NewByteArray(env, len);
+       if (IS_NULL(ret)) {
+          /* we may have memory to free at the end of this */
+          goto fexit;
+       }
+       (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
+    }
+ fexit:
+   /* release the UTF string and interface list */
+   (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+   close(sock);
+   return ret;
+}
+
+/*
+ * Class:       java_net_NetworkInterface
+ * Method:      getMTU0
+ * Signature:   ([bLjava/lang/String;I)I
+ */
+
+JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
+    jboolean isCopy;
+    int ret = -1;
+    int sock;
+    const char* name_utf;
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+       (*env)->ReleaseStringUTFChars(env, name, name_utf);
+       return JNI_FALSE;
+    }
+
+    ret = getMTU(env, sock, name_utf);
+
+    (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+    close(sock);
+    return ret;
+}
+
+/*** Private methods definitions ****/
+
+static int getFlags0(JNIEnv *env, jstring name) {
+    jboolean isCopy;
+    int ret, sock;
+    const char* name_utf;
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
+        (*env)->ReleaseStringUTFChars(env, name, name_utf);
+         return -1;
+    }
+
+    name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+    ret = getFlags(env, sock, name_utf);
+
+    close(sock);
+    (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+    if (ret < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
+        return -1;
+    }
+
+    return ret;
+}
+
+
+
+
 /*
  * Create a NetworkInterface object, populate the name and index, and
  * populate the InetAddress array based on the IP addresses for this
  * interface.
  */
-jobject createNetworkInterface(JNIEnv *env, netif *ifs)
-{
+jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
     jobject netifObj;
     jobject name;
     jobjectArray addrArr;
     jobjectArray bindArr;
     jobjectArray childArr;
+    netaddr *addrs;
     jint addr_index, addr_count, bind_index;
     jint child_count, child_index;
     netaddr *addrP;
@@ -441,7 +617,7 @@
 
     bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
     if (bindArr == NULL) {
-      return NULL;
+       return NULL;
     }
     addrP = ifs->addr;
     addr_index = 0;
@@ -453,23 +629,22 @@
         if (addrP->family == AF_INET) {
             iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
             if (iaObj) {
-                 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
-                     htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
+                 (*env)->SetIntField(env, iaObj, ni_iaaddressID, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
             }
             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
             if (ibObj) {
-              (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
-              if (addrP->brdcast) {
-                jobject ia2Obj = NULL;
-                ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
-                if (ia2Obj) {
-                  (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
-                                      htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
-                  (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
-                  (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
-                }
-              }
-              (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+                 (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+                 if (addrP->brdcast) {
+                    jobject ia2Obj = NULL;
+                    ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+                    if (ia2Obj) {
+                       (*env)->SetIntField(env, ia2Obj, ni_iaaddressID,
+                                                               htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
+                       (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
+                       (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+                    }
+                 }
+                 (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
             }
         }
 
@@ -483,14 +658,10 @@
                     return NULL;
                 }
                 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
-                    (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
-#ifdef __linux__
-                if (!kernelIsV22()) {
-                    scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
-                }
-#else
+                                                                        (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
+
                 scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
-#endif
+
                 if (scope != 0) { /* zero is default value, no need to set */
                     (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
                     (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
@@ -500,9 +671,9 @@
             }
             ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
             if (ibObj) {
-              (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
-              (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
-              (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+                (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+                (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+                (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
             }
         }
 #endif
@@ -521,13 +692,13 @@
     child_count = 0;
     childP = ifs->childs;
     while (childP) {
-      child_count++;
-      childP = childP->next;
+        child_count++;
+        childP = childP->next;
     }
 
     childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
     if (childArr == NULL) {
-      return NULL;
+        return NULL;
     }
 
     /*
@@ -539,7 +710,7 @@
     while(childP) {
       tmp = createNetworkInterface(env, childP);
       if (tmp == NULL) {
-        return NULL;
+         return NULL;
       }
       (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
       (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
@@ -558,294 +729,56 @@
  */
 static netif *enumInterfaces(JNIEnv *env) {
     netif *ifs;
+    int sock;
 
     /*
      * Enumerate IPv4 addresses
      */
-    ifs = enumIPv4Interfaces(env, NULL);
-    if (ifs == NULL) {
-        if ((*env)->ExceptionOccurred(env)) {
-            return NULL;
-        }
+
+    sock = openSocket(env, AF_INET);
+    if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+        return NULL;
     }
 
+    ifs = enumIPv4Interfaces(env, sock, NULL);
+    close(sock);
+
+    if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
+        return NULL;
+    }
+
+    /* return partial list if exception occure in the middle of process ???*/
+
     /*
      * If IPv6 is available then enumerate IPv6 addresses.
      */
 #ifdef AF_INET6
-    if (ipv6_available()) {
-        ifs = enumIPv6Interfaces(env, ifs);
+        sock =  openSocket(env, AF_INET6);
+        if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+            freeif(ifs);
+            return NULL;
+        }
+
+        ifs = enumIPv6Interfaces(env, sock, ifs);
+        close(sock);
 
         if ((*env)->ExceptionOccurred(env)) {
             freeif(ifs);
             return NULL;
         }
-    }
 #endif
 
     return ifs;
 }
 
-
-/*
- * Enumerates and returns all IPv4 interfaces
- */
-static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs) {
-    int sock;
-    struct ifconf ifc;
-    struct ifreq *ifreqP;
-    char *buf;
-    int numifs;
-    unsigned i;
-    unsigned bufsize;
-
-    sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        /*
-         * If EPROTONOSUPPORT is returned it means we don't have
-         * IPv4 support so don't throw an exception.
-         */
-        if (errno != EPROTONOSUPPORT) {
-            NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                             "Socket creation failed");
-        }
-        return ifs;
-    }
-
-#ifdef __linux__
-    /* need to do a dummy SIOCGIFCONF to determine the buffer size.
-     * SIOCGIFCOUNT doesn't work
-     */
-    ifc.ifc_buf = NULL;
-    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGIFCONF failed");
-        close(sock);
-        return ifs;
-    }
-    bufsize = ifc.ifc_len;
-#else
-    if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGIFNUM failed");
-        close(sock);
-        return ifs;
-    }
-    bufsize = numifs * sizeof (struct ifreq);
-#endif /* __linux__ */
-
-    buf = (char *)malloc(bufsize);
-    if (!buf) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        (void) close(sock);
-        return ifs;
-    }
-    ifc.ifc_len = bufsize;
-    ifc.ifc_buf = buf;
-    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGIFCONF failed");
-        (void) close(sock);
-        (void) free(buf);
-        return ifs;
-    }
-
-    /*
-     * Iterate through each interface
-     */
-    ifreqP = ifc.ifc_req;
-    for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
-        int index;
-        struct ifreq if2;
-
-        memset((char *)&if2, 0, sizeof(if2));
-        strcpy(if2.ifr_name, ifreqP->ifr_name);
-
-        /*
-         * Try to get the interface index
-         * (Not supported on Solaris 2.6 or 7)
-         */
-        if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) >= 0) {
-            index = if2.ifr_index;
-        } else {
-            index = -1;
-        }
-
-        /*
-         * Add to the list
-         */
-        ifs = addif(env, ifs, ifreqP->ifr_name, index, AF_INET,
-                    (struct sockaddr *)&(ifreqP->ifr_addr),
-                    sizeof(struct sockaddr_in), 0);
-
-        /*
-         * If an exception occurred then free the list
-         */
-        if ((*env)->ExceptionOccurred(env)) {
-            close(sock);
-            free(buf);
-            freeif(ifs);
-            return NULL;
-        }
-    }
-
-    /*
-     * Free socket and buffer
-     */
-    close(sock);
-    free(buf);
-    return ifs;
-}
-
-
-#if defined(__solaris__) && defined(AF_INET6)
-/*
- * Enumerates and returns all IPv6 interfaces on Solaris
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
-    int sock;
-    struct lifconf ifc;
-    struct lifreq *ifr;
-    int n;
-    char *buf;
-    struct lifnum numifs;
-    unsigned bufsize;
-
-    sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "Failed to create IPv6 socket");
-        return ifs;
-    }
-
-    /*
-     * Get the interface count
-     */
-    numifs.lifn_family = AF_UNSPEC;
-    numifs.lifn_flags = 0;
-    if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGLIFNUM failed");
-        close(sock);
-        return ifs;
-    }
-
-    /*
-     *  Enumerate the interface configurations
-     */
-    bufsize = numifs.lifn_count * sizeof (struct lifreq);
-    buf = (char *)malloc(bufsize);
-    if (!buf) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        (void) close(sock);
-        return ifs;
-    }
-    ifc.lifc_family = AF_UNSPEC;
-    ifc.lifc_flags = 0;
-    ifc.lifc_len = bufsize;
-    ifc.lifc_buf = buf;
-    if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                         "ioctl SIOCGLIFCONF failed");
-        close(sock);
-        free(buf);
-        return ifs;
-    }
-
-    /*
-     * Iterate through each interface
-     */
-    ifr = ifc.lifc_req;
-    for (n=0; n<numifs.lifn_count; n++, ifr++) {
-        int index = -1;
-        struct lifreq if2;
-
-        /*
-         * Ignore non-IPv6 addresses
-         */
-        if (ifr->lifr_addr.ss_family != AF_INET6) {
-            continue;
-        }
-
-        /*
-         * Get the index
-         */
-        memset((char *)&if2, 0, sizeof(if2));
-        strcpy(if2.lifr_name, ifr->lifr_name);
-        if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) >= 0) {
-            struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
-            index = if2.lifr_index;
-            s6->sin6_scope_id = index;
-        }
-
-        /* add to the list */
-        ifs = addif(env, ifs, ifr->lifr_name, index, AF_INET6,
-                    (struct sockaddr *)&(ifr->lifr_addr),
-                    sizeof(struct sockaddr_in6), (short) ifr->lifr_addrlen);
-
-        /*
-         * If an exception occurred we return
-         */
-        if ((*env)->ExceptionOccurred(env)) {
-            close(sock);
-            free(buf);
-            return ifs;
-        }
-
-    }
-
-    close(sock);
-    free(buf);
-    return ifs;
-
-}
-#endif
-
-
-#if defined(__linux__) && defined(AF_INET6)
-/*
- * Enumerates and returns all IPv6 interfaces on Linux
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) {
-    FILE *f;
-    char addr6[40], devname[20];
-    char addr6p[8][5];
-    int plen, scope, dad_status, if_idx;
-    uint8_t ipv6addr[16];
-
-    if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
-        while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
-                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
-                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
-                  &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
-            struct sockaddr_in6 addr;
-
-            sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
-                    addr6p[0], addr6p[1], addr6p[2], addr6p[3],
-                    addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
-            inet_pton(AF_INET6, addr6, ipv6addr);
-
-            memset(&addr, 0, sizeof(struct sockaddr_in6));
-            memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
-            addr.sin6_scope_id = if_idx;
-
-            ifs = addif(env, ifs, devname, if_idx, AF_INET6,
-                        (struct sockaddr *)&addr,
-                        sizeof(struct sockaddr_in6), plen);
-
-            /*
-             * If an exception occurred then return the list as is.
-             */
-            if ((*env)->ExceptionOccurred(env)) {
-                fclose(f);
-                return ifs;
-            }
-        }
-        fclose(f);
-    }
-    return ifs;
-}
-#endif
+#define CHECKED_MALLOC3(_pointer,_type,_size) \
+       do{ \
+        _pointer = (_type)malloc( _size ); \
+        if (_pointer == NULL) { \
+            JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); \
+            return ifs; /* return untouched list */ \
+        } \
+       } while(0)
 
 
 /*
@@ -853,52 +786,43 @@
  */
 void freeif(netif *ifs) {
     netif *currif = ifs;
+    netif *child = NULL;
 
     while (currif != NULL) {
         netaddr *addrP = currif->addr;
         while (addrP != NULL) {
             netaddr *next = addrP->next;
-            if (addrP->addr != NULL)
-                free(addrP->addr);
-            if (addrP->brdcast != NULL)
-                free(addrP->brdcast);
             free(addrP);
             addrP = next;
-        }
-
-        free(currif->name);
+         }
 
-        /*
-         * Don't forget to free the sub-interfaces.
-         */
-        if (currif->childs != NULL) {
-          freeif(currif->childs);
-        }
+            /*
+            * Don't forget to free the sub-interfaces.
+            */
+          if (currif->childs != NULL) {
+                freeif(currif->childs);
+          }
 
-        ifs = currif->next;
-        free(currif);
-        currif = ifs;
+          ifs = currif->next;
+          free(currif);
+          currif = ifs;
     }
 }
 
-/*
- * Add an interface to the list. If known interface just link
- * a new netaddr onto the list. If new interface create new
- * netif structure.
- */
-netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, int family,
-             struct sockaddr *new_addrP, int new_addrlen, short prefix) {
-  netif *currif = ifs, *parent;
+netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix) {
+    netif *currif = ifs, *parent;
     netaddr *addrP;
-#ifdef LIFNAMSIZ
-    char name[LIFNAMSIZ];
-    char vname[LIFNAMSIZ];
-#else
-    char name[IFNAMSIZ];
-    char vname[IFNAMSIZ];
-#endif
-    char *unit;
+
+    #ifdef __solaris__
+    char name[LIFNAMSIZ],  vname[LIFNAMSIZ];
+    #else
+    char name[IFNAMSIZ],  vname[IFNAMSIZ];
+    #endif
+
+    char  *name_colonP;
+    int mask;
     int isVirtual = 0;
+    int addr_size;
 
     /*
      * If the interface name is a logical interface then we
@@ -908,107 +832,63 @@
      * logical interfaces.
      */
     strcpy(name, if_name);
+    *vname = 0;
 
     /*
      * Create and populate the netaddr node. If allocation fails
      * return an un-updated list.
      */
-    addrP = (netaddr *)malloc(sizeof(netaddr));
-    if (addrP) {
-        addrP->addr = (struct sockaddr *)malloc(new_addrlen);
-        if (addrP->addr == NULL) {
-            free(addrP);
-            addrP = NULL;
-        }
-    }
-    if (addrP == NULL) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        return ifs; /* return untouched list */
-    }
-    memcpy(addrP->addr, new_addrP, new_addrlen);
+    /*Allocate for addr and brdcast at once*/
+
+#ifdef AF_INET6
+    addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+#else
+    addr_size = sizeof(struct sockaddr_in);
+#endif
+
+    CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
+    addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
+    memcpy(addrP->addr, ifr_addrP, addr_size);
+
     addrP->family = family;
-
     addrP->brdcast = NULL;
     addrP->mask = prefix;
+    addrP->next = 0;
     if (family == AF_INET) {
       /*
        * Deal with brodcast addr & subnet mask
        */
-      addrP->brdcast = getBroadcast(env, name);
-      if (addrP->brdcast) {
-        addrP->mask = getSubnet(env, name);
-      }
-    }
+       struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
+       addrP->brdcast = getBroadcast(env, sock, name,  brdcast_to );
 
-    vname[0] = 0;
-    unit = strchr(name, ':');
-    if (unit != NULL) {
+       if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) {
+           addrP->mask = mask;
+       }
+     }
+
+    /**
+     * Deal with virtual interface with colon notaion e.g. eth0:1
+     */
+    name_colonP = strchr(name, ':');
+    if (name_colonP != NULL) {
       /**
        * This is a virtual interface. If we are able to access the parent
        * we need to create a new entry if it doesn't exist yet *and* update
        * the 'parent' interface with the new records.
        */
-      struct ifreq if2;
-      int sock;
-      int len;
-
-      sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-      if (sock < 0) {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "Socket creation failed");
-        return ifs; /* return untouched list */
-      }
-
-      len = unit - name;
-      if (len > 0) {
-        // temporarily use vname to hold the parent name of the interface
-        // instead of creating another buffer.
-        memcpy(&vname, name, len);
-        vname[len] = '\0';
-
-        memset((char *) &if2, 0, sizeof(if2));
-        strcpy(if2.ifr_name, vname);
-
-        if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
-           // Got access to parent, so create it if necessary.
-           strcpy(vname, name);
-           *unit = '\0';
-        } else {
-#if defined(__solaris__) && defined(AF_INET6)
-          struct   lifreq lifr;
-          memset((char *) &lifr, 0, sizeof(lifr));
-          strcpy(lifr.lifr_name, vname);
-
-          /* Try with an IPv6 socket in case the interface has only IPv6
-           * addresses assigned to it */
-          close(sock);
-          sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-
-          if (sock < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                         "Socket creation failed");
-            return ifs; /* return untouched list */
-          }
-
-          if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
-            // Got access to parent, so create it if necessary.
-            strcpy(vname, name);
-            *unit = '\0';
-          } else {
+        *name_colonP = 0;
+        if (getFlags(env,sock,name) < 0) {
             // failed to access parent interface do not create parent.
             // We are a virtual interface with no parent.
             isVirtual = 1;
-            vname[0] = 0;
-          }
-#else
-          // failed to access parent interface do not create parent.
-          // We are a virtual interface with no parent.
-          isVirtual = 1;
-          vname[0] = 0;
-#endif
+            *name_colonP = ':';
         }
-      }
-      close(sock);
+        else{
+           // Got access to parent, so create it if necessary.
+           // Save original name to vname and truncate name by ':'
+            memcpy(vname, name, sizeof(vname) );
+            vname[name_colonP - name] = ':';
+        }
     }
 
     /*
@@ -1028,24 +908,15 @@
      * insert it onto the list.
      */
     if (currif == NULL) {
-        currif = (netif *)malloc(sizeof(netif));
-        if (currif) {
-            currif->name = strdup(name);
-            if (currif->name == NULL) {
-                free(currif);
-                currif = NULL;
-            }
-        }
-        if (currif == NULL) {
-            JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-            return ifs;
-        }
-        currif->index = index;
-        currif->addr = NULL;
-        currif->childs = NULL;
-        currif->virtual = isVirtual;
-        currif->next = ifs;
-        ifs = currif;
+         CHECKED_MALLOC3(currif, netif *, sizeof(netif)+IFNAMSIZ );
+         currif->name = (char *) currif+sizeof(netif);
+         strcpy(currif->name, name);
+         currif->index = getIndex(sock, name);
+         currif->addr = NULL;
+         currif->childs = NULL;
+         currif->virtual = isVirtual;
+         currif->next = ifs;
+         ifs = currif;
     }
 
     /*
@@ -1060,161 +931,251 @@
      * Let's deal with the virtual interface now.
      */
     if (vname[0]) {
-      netaddr *tmpaddr;
+        netaddr *tmpaddr;
 
-      currif = parent->childs;
+        currif = parent->childs;
 
-      while (currif != NULL) {
-        if (strcmp(vname, currif->name) == 0) {
-          break;
-        }
-        currif = currif->next;
-      }
-      if (currif == NULL) {
-        currif = (netif *)malloc(sizeof(netif));
-        if (currif) {
-          currif->name = strdup(vname);
-          if (currif->name == NULL) {
-            free(currif);
-            currif = NULL;
-          }
-        }
-        if (currif == NULL) {
-          JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-          return ifs;
+        while (currif != NULL) {
+            if (strcmp(vname, currif->name) == 0) {
+                break;
+            }
+            currif = currif->next;
         }
-        currif->index = index;
-        currif->addr = NULL;
-        /* Need to duplicate the addr entry? */
-        currif->virtual = 1;
-        currif->childs = NULL;
-        currif->next = parent->childs;
-        parent->childs = currif;
-      }
+
+        if (currif == NULL) {
+            CHECKED_MALLOC3(currif, netif *, sizeof(netif)+ IFNAMSIZ );
+            currif->name = (char *) currif + sizeof(netif);
+            strcpy(currif->name, vname);
+            currif->index = getIndex(sock, vname);
+            currif->addr = NULL;
+           /* Need to duplicate the addr entry? */
+            currif->virtual = 1;
+            currif->childs = NULL;
+            currif->next = parent->childs;
+            parent->childs = currif;
+        }
 
-      tmpaddr = (netaddr *) malloc(sizeof(netaddr));
-      if (tmpaddr == NULL) {
-        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
-        return ifs;
-      }
-      memcpy(tmpaddr, addrP, sizeof(netaddr));
-      /**
-       * Let's duplicate the address and broadcast address structures
-       * if there are any.
-       */
-      if (addrP->addr != NULL) {
-        tmpaddr->addr = malloc(new_addrlen);
-        if (tmpaddr->addr != NULL)
-          memcpy(tmpaddr->addr, addrP->addr, new_addrlen);
-      }
-      if (addrP->brdcast != NULL) {
-        tmpaddr->brdcast = malloc(new_addrlen);
-        if (tmpaddr->brdcast != NULL)
-          memcpy(tmpaddr->brdcast, addrP->brdcast, new_addrlen);
-      }
-      tmpaddr->next = currif->addr;
-      currif->addr = tmpaddr;
+        CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
+        memcpy(tmpaddr, addrP, sizeof(netaddr));
+        if (addrP->addr != NULL) {
+            tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
+            memcpy(tmpaddr->addr, addrP->addr, addr_size);
+        }
+
+        if (addrP->brdcast != NULL) {
+            tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
+            memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
+        }
+
+        tmpaddr->next = currif->addr;
+        currif->addr = tmpaddr;
     }
 
     return ifs;
 }
 
-/**
- * Get flags from a NetworkInterface.
+/* Open socket for further ioct calls
+ * proto is AF_INET/AF_INET6
  */
-static short getFlags(JNIEnv *env, jstring name) {
-  int sock;
-  struct ifreq if2;
-  jboolean isCopy;
-  const char* name_utf;
-  short ret = -1;
+static int  openSocket(JNIEnv *env, int proto){
+    int sock;
+
+    if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
+        /*
+         * If EPROTONOSUPPORT is returned it means we don't have
+         * support  for this proto so don't throw an exception.
+         */
+        if (errno != EPROTONOSUPPORT) {
+            NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
+        }
+        return -1;
+    }
 
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return -1;
-  }
+    return sock;
+}
+
+
+/** Linux **/
+#ifdef __linux__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    int sock;
+    struct ifreq if2;
 
-  name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, name_utf);
+     if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+         if (errno == EPROTONOSUPPORT){
+              if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+                 return -1;
+              }
+         }
+         else{ // errno is not NOSUPPORT
+             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+             return -1;
+         }
+   }
+
+     /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
+        of address of an interface */
+
+       return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    return openSocket(env,AF_INET);
+}
+#endif
 
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
-    ret = if2.ifr_flags;
-  } else {
-#if defined(__solaris__) && defined(AF_INET6)
-    /* Try with an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
-    struct lifreq lifr;
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    struct ifconf ifc;
+    struct ifreq *ifreqP;
+    char *buf;
+    int numifs;
+    unsigned i;
+
 
-    close(sock);
-    sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+    /* need to do a dummy SIOCGIFCONF to determine the buffer size.
+     * SIOCGIFCOUNT doesn't work
+     */
+    ifc.ifc_buf = NULL;
+    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+        return ifs;
+    }
 
-    if (sock < 0) {
-      (*env)->ReleaseStringUTFChars(env, name, name_utf);
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                  "Socket creation failed");
-      return -1;
+    CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
+
+    ifc.ifc_buf = buf;
+    if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+        (void) free(buf);
+        return ifs;
     }
 
-    memset((caddr_t)&lifr, 0, sizeof(lifr));
-    strcpy((caddr_t)&(lifr.lifr_name), name_utf);
+    /*
+     * Iterate through each interface
+     */
+    ifreqP = ifc.ifc_req;
+    for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
+        /*
+         * Add to the list
+         */
+        ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
 
-    if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
-      ret = lifr.lifr_flags;
-    } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "IOCTL failed");
+        /*
+         * If an exception occurred then free the list
+         */
+        if ((*env)->ExceptionOccurred(env)) {
+            free(buf);
+            freeif(ifs);
+            return NULL;
+        }
     }
-#else
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "IOCTL failed");
+
+    /*
+     * Free socket and buffer
+     */
+    free(buf);
+    return ifs;
+}
+
+
+/*
+ * Enumerates and returns all IPv6 interfaces on Linux
+ */
+
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    FILE *f;
+    char addr6[40], devname[20];
+    char addr6p[8][5];
+    int plen, scope, dad_status, if_idx;
+    uint8_t ipv6addr[16];
+
+    if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
+        while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+                         addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+                         &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
+
+            struct netif *ifs_ptr = NULL;
+            struct netif *last_ptr = NULL;
+            struct sockaddr_in6 addr;
+
+            sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+                           addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+            inet_pton(AF_INET6, addr6, ipv6addr);
+
+            memset(&addr, 0, sizeof(struct sockaddr_in6));
+            memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
+
+            addr.sin6_scope_id = if_idx;
+
+            ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
+
+
+            /*
+             * If an exception occurred then return the list as is.
+             */
+            if ((*env)->ExceptionOccurred(env)) {
+                fclose(f);
+                return ifs;
+            }
+       }
+       fclose(f);
+    }
+    return ifs;
+}
 #endif
-  }
-  close(sock);
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
 
-  return ret;
+static int getIndex(int sock, const char *name){
+     /*
+      * Try to get the interface index
+      * (Not supported on Solaris 2.6 or 7)
+      */
+    struct ifreq if2;
+    strcpy(if2.ifr_name, name);
+
+    if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
+        return -1;
+    }
+
+    return if2.ifr_ifindex;
 }
 
 /**
  * Returns the IPv4 broadcast address of a named interface, if it exists.
  * Returns 0 if it doesn't have one.
  */
-static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname) {
-  int sock;
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
   struct sockaddr *ret = NULL;
   struct ifreq if2;
-  short flag = 0;
-
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return ret;
-  }
 
   memset((char *) &if2, 0, sizeof(if2));
   strcpy(if2.ifr_name, ifname);
+
   /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
-    flag = if2.ifr_flags;
-  } else {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "IOCTL failed");
+  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
+      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGIFFLAGS failed");
+      return ret;
   }
-  if (flag & IFF_BROADCAST) {
-    /* It does, let's retrieve it*/
-    if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) >= 0) {
-      ret = (struct sockaddr*) malloc(sizeof(struct sockaddr));
+
+  if (if2.ifr_flags & IFF_BROADCAST) {
+      /* It does, let's retrieve it*/
+      if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+          NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
+          return ret;
+      }
+
+      ret = brdcast_store;
       memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-    } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                   "IOCTL failed");
-    }
   }
-  close(sock);
+
   return ret;
 }
 
@@ -1222,39 +1183,314 @@
  * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
  * interface, if it has one, otherwise return -1.
  */
-static short getSubnet(JNIEnv *env, const char *ifname) {
-  int sock;
-  unsigned int mask;
-  short ret;
-  struct ifreq if2;
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+    unsigned int mask;
+    short ret;
+    struct ifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.ifr_name, ifname);
+
+    if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+        return -1;
+    }
+
+    mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
+    ret = 0;
+    while (mask) {
+       mask <<= 1;
+       ret++;
+    }
+
+    return ret;
+}
+
+/**
+ * Get the Hardware address (usually MAC address) for the named interface.
+ * return puts the data in buf, and returns the length, in byte, of the
+ * MAC address. Returns -1 if there is no hardware address on that interface.
+ */
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+    static struct ifreq ifr;
+    int i;
 
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
+    strcpy(ifr.ifr_name, ifname);
+    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
+        return -1;
+    }
+
+    memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+
+   /*
+    * All bytes to 0 means no hardware address.
+    */
+
+    for (i = 0; i < IFHWADDRLEN; i++) {
+        if (buf[i] != 0)
+            return IFHWADDRLEN;
+    }
+
     return -1;
-  }
+}
+
+static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
+    struct ifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.ifr_name, ifname);
+
+    if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+        return -1;
+    }
+
+    return  if2.ifr_mtu;
+}
+
+static int getFlags(JNIEnv *env, int sock, const char *ifname) {
+  struct ifreq if2;
+  int ret = -1;
 
   memset((char *) &if2, 0, sizeof(if2));
   strcpy(if2.ifr_name, ifname);
-  if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) >= 0) {
-    mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
-    ret = 0;
-    while (mask) {
-      mask <<= 1;
-      ret++;
+
+  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
+      return -1;
+  }
+
+  return if2.ifr_flags;
+}
+
+#endif
+
+/** Solaris **/
+#ifdef __solaris__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    int sock, alreadyV6 = 0;
+    struct lifreq if2;
+
+     if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+         if (errno == EPROTONOSUPPORT){
+              if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+                 NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+                 return -1;
+              }
+
+              alreadyV6=1;
+         }
+         else{ // errno is not NOSUPPORT
+             NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+             return -1;
+         }
+   }
+
+     /**
+      * Solaris requires that we have IPv6 socket to query an
+      * interface without IPv4 address - check it here
+      * POSIX 1 require the kernell to return ENOTTY if the call is
+      * unappropriate for device e.g. NETMASK for device having IPv6
+      * only address but not all devices follows the standart so
+      * fallback on any error.  It's not an ecology friendly but more
+      * reliable.
+      */
+
+    if (! alreadyV6 ){
+        memset((char *) &if2, 0, sizeof(if2));
+        strcpy(if2.lifr_name, ifname);
+        if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+                close(sock);
+                if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+                      NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+                      return -1;
+                }
+        }
     }
-    close(sock);
-    return ret;
-  }
-  NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                               "IOCTL failed");
-  close(sock);
-  return -1;
+
+    return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+    return openSocket(env,AF_INET);
+}
+#endif
+
+/*
+ * Enumerates and returns all IPv4 interfaces
+ * (linux verison)
+ */
+
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+     return enumIPvXInterfaces(env,sock, ifs, AF_INET);
 }
 
-#ifdef __solaris__
-#define DEV_PREFIX      "/dev/"
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+    return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
+}
+#endif
+
+/*
+   Enumerates and returns all interfaces on Solaris
+   use the same code for IPv4 and IPv6
+ */
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
+    struct lifconf ifc;
+    struct lifreq *ifr;
+    int n;
+    char *buf;
+    struct lifnum numifs;
+    unsigned bufsize;
+
+    /*
+     * Get the interface count
+     */
+    numifs.lifn_family = family;
+    numifs.lifn_flags = 0;
+    if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
+        return ifs;
+    }
+
+    /*
+     *  Enumerate the interface configurations
+     */
+    bufsize = numifs.lifn_count * sizeof (struct lifreq);
+    CHECKED_MALLOC3(buf, char *, bufsize);
+
+    ifc.lifc_family = family;
+    ifc.lifc_flags = 0;
+    ifc.lifc_len = bufsize;
+    ifc.lifc_buf = buf;
+    if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
+        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
+        free(buf);
+        return ifs;
+    }
+
+    /*
+     * Iterate through each interface
+     */
+    ifr = ifc.lifc_req;
+    for (n=0; n<numifs.lifn_count; n++, ifr++) {
+        int index = -1;
+        struct lifreq if2;
+
+        /*
+        * Ignore either IPv4 or IPv6 addresses
+        */
+        if (ifr->lifr_addr.ss_family != family) {
+            continue;
+        }
+
+#ifdef AF_INET6
+        if (ifr->lifr_addr.ss_family == AF_INET6) {
+            struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
+            s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
+        }
+#endif
+
+        /* add to the list */
+        ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
+
+        /*
+        * If an exception occurred we return immediately
+        */
+        if ((*env)->ExceptionOccurred(env)) {
+            free(buf);
+            return ifs;
+        }
+
+   }
+
+    free(buf);
+    return ifs;
+}
+
+static int getIndex(int sock, const char *name){
+   /*
+    * Try to get the interface index
+    * (Not supported on Solaris 2.6 or 7)
+    */
+    struct lifreq if2;
+    strcpy(if2.lifr_name, name);
+
+    if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
+        return -1;
+    }
+
+    return if2.lifr_index;
+}
+
+/**
+ * Returns the IPv4 broadcast address of a named interface, if it exists.
+ * Returns 0 if it doesn't have one.
+ */
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+    struct sockaddr *ret = NULL;
+    struct lifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.lifr_name, ifname);
+
+    /* Let's make sure the interface does have a broadcast address */
+    if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
+        return ret;
+    }
+
+    if (if2.lifr_flags & IFF_BROADCAST) {
+        /* It does, let's retrieve it*/
+        if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
+            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
+            return ret;
+        }
+
+        ret = brdcast_store;
+        memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
+    }
+
+    return ret;
+}
+
+/**
+ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
+ * interface, if it has one, otherwise return -1.
+ */
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+    unsigned int mask;
+    short ret;
+    struct lifreq if2;
+
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.lifr_name, ifname);
+
+    if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
+        return -1;
+    }
+
+    mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
+    ret = 0;
+
+    while (mask) {
+       mask <<= 1;
+       ret++;
+    }
+
+    return ret;
+}
+
+
+
+#define DEV_PREFIX  "/dev/"
 
 /**
  * Solaris specific DLPI code to get hardware address from a device.
@@ -1262,306 +1498,147 @@
  * privileges (i.e. be root).
  */
 static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
-  char style1dev[MAXPATHLEN];
-  int fd;
-  dl_phys_addr_req_t dlpareq;
-  dl_phys_addr_ack_t *dlpaack;
-  struct strbuf msg;
-  char buf[128];
-  int flags = 0;
+    char style1dev[MAXPATHLEN];
+    int fd;
+    dl_phys_addr_req_t dlpareq;
+    dl_phys_addr_ack_t *dlpaack;
+    struct strbuf msg;
+    char buf[128];
+    int flags = 0;
+
+   /**
+    * Device is in /dev
+    * e.g.: /dev/bge0
+    */
+    strcpy(style1dev, DEV_PREFIX);
+    strcat(style1dev, ifname);
+    if ((fd = open(style1dev, O_RDWR)) < 0) {
+        /*
+         * Can't open it. We probably are missing the privilege.
+         * We'll have to try something else
+         */
+         return 0;
+    }
+
+    dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
+    dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
 
-  /**
-   * Device is in /dev
-   * e.g.: /dev/bge0
-   */
-  strcpy(style1dev, DEV_PREFIX);
-  strcat(style1dev, ifname);
-  if ((fd = open(style1dev, O_RDWR)) == -1) {
-    /*
-     * Can't open it. We probably are missing the privilege.
-     * We'll have to try something else
-     */
-    return 0;
-  }
-  dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
-  dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
-  msg.buf = (char *)&dlpareq;
-  msg.len = DL_PHYS_ADDR_REQ_SIZE;
-  if (putmsg(fd, &msg, NULL, 0) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "putmsg failed");
-    return -1;
-  }
-  dlpaack = (dl_phys_addr_ack_t *)buf;
-  msg.buf = (char *)buf;
-  msg.len = 0;
-  msg.maxlen = sizeof (buf);
-  if (getmsg(fd, &msg, NULL, &flags) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "getmsg failed");
-    return -1;
-  }
-  if (msg.len < DL_PHYS_ADDR_ACK_SIZE ||
-      dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
-    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                    "Couldn't obtain phys addr\n");
-    return -1;
-  }
+    msg.buf = (char *)&dlpareq;
+    msg.len = DL_PHYS_ADDR_REQ_SIZE;
+
+    if (putmsg(fd, &msg, NULL, 0) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
+        return -1;
+    }
+
+    dlpaack = (dl_phys_addr_ack_t *)buf;
 
-  memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
-  return dlpaack->dl_addr_length;
+    msg.buf = (char *)buf;
+    msg.len = 0;
+    msg.maxlen = sizeof (buf);
+    if (getmsg(fd, &msg, NULL, &flags) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
+        return -1;
+    }
+
+    if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
+        return -1;
+    }
+
+    memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
+    return dlpaack->dl_addr_length;
 }
-#endif
 
 /**
  * Get the Hardware address (usually MAC address) for the named interface.
  * return puts the data in buf, and returns the length, in byte, of the
  * MAC address. Returns -1 if there is no hardware address on that interface.
  */
-int getMacAddress(JNIEnv *env, const struct in_addr* addr, const char* ifname,
-                  unsigned char *buf) {
-  int sock;
-#ifdef __linux__
-  static struct ifreq ifr;
-  int i;
+static int getMacAddress(JNIEnv *env, int sock, const char *ifname,  const struct in_addr* addr, unsigned char *buf) {
+    struct arpreq arpreq;
+    struct sockaddr_in* sin;
+    struct sockaddr_in ipAddr;
+    int len, i;
+
+   /**
+    * On Solaris we have to use DLPI, but it will only work if we have
+    * privileged access (i.e. root). If that fails, we try a lookup
+    * in the ARP table, which requires an IPv4 address.
+    */
+    if ((len = getMacFromDevice(env, ifname, buf))  == 0) {
+        /*DLPI failed - trying to do arp lookup*/
+
+       if (addr == NULL) {
+          /**
+           * No IPv4 address for that interface, so can't do an ARP lookup.
+           */
+           return -1;
+      }
 
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
+      len = 6; //???
+
+      sin = (struct sockaddr_in *) &arpreq.arp_pa;
+      memset((char *) &arpreq, 0, sizeof(struct arpreq));
+      ipAddr.sin_port = 0;
+      ipAddr.sin_family = AF_INET;
+      memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
+      memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
+      arpreq.arp_flags= ATF_PUBL;
 
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return -1;
+      if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
+          if (errno != ENXIO) {
+              // "No such device or address" means no hardware address, so it's
+              // normal don't throw an exception
+              NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL failed");
+              return -1;
+          }
+     }
+
+     memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
   }
 
-  strcpy(ifr.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
-    fprintf(stderr, "SIOCIFHWADDR: %s\n",
-            strerror(errno));
-    close(sock);
-    return -1;
-  }
-  memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
-  close(sock);
-  for (i = 0; i < IFHWADDRLEN; i++) {
-    if (buf[i] != 0)
-      return IFHWADDRLEN;
-  }
-  /*
-   * All bytes to 0 means no hardware address.
-   */
-  return -1;
-#else
-  struct arpreq arpreq;
-  struct sockaddr_in* sin;
-  struct sockaddr_in ipAddr;
-  int len;
-
-  /**
-   * On Solaris we have to use DLPI, but it will only work if we have
-   * privileged access (i.e. root). If that fails, we try a lookup
-   * in the ARP table, which requires an IPv4 address.
-   */
-  if ((len = getMacFromDevice(env, ifname, buf)) > 0) {
-    return len;
-  }
-  if (addr == NULL) {
-    /**
-     * No IPv4 address for that interface, so can't do an ARP lookup.
+    /*
+     * All bytes to 0 means no hardware address.
      */
-    return -1;
-  }
-  sin = (struct sockaddr_in *) &arpreq.arp_pa;
-  memset((char *) &arpreq, 0, sizeof(struct arpreq));
-  ipAddr.sin_port = 0;
-  ipAddr.sin_family = AF_INET;
-  memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
-  memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
-  arpreq.arp_flags= ATF_PUBL;
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-    return -1;
-  }
 
-  if (ioctl(sock, SIOCGARP, &arpreq) >= 0) {
-    close(sock);
-    memcpy(buf, &arpreq.arp_ha.sa_data[0], 6);
-    return 6;
-  }
-
-  if (errno != ENXIO) {
-    // "No such device or address" means no hardware address, so it's
-    // normal don't throw an exception
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "IOCTL failed");
-  }
-  close(sock);
-#endif
-  return -1;
-}
-
-/*
- * Class:     java_net_NetworkInterface
- * Method:    isUp0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
-    (JNIEnv *env, jclass cls, jstring name, jint index) {
-    short val;
+    for (i = 0; i < len; i++) {
+      if (buf[i] != 0)
+         return len;
+    }
 
-    val = getFlags(env, name);
-    if ( (val & IFF_UP) && (val &  IFF_RUNNING))
-      return JNI_TRUE;
-    return JNI_FALSE;
-}
-
-/*
- * Class:     java_net_NetworkInterface
- * Method:    isP2P0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
-    (JNIEnv *env, jclass cls, jstring name, jint index) {
-    if (getFlags(env, name) & IFF_POINTOPOINT)
-      return JNI_TRUE;
-    return JNI_FALSE;
-}
-
-/*
- * Class:     java_net_NetworkInterface
- * Method:    isLoopback0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
-    (JNIEnv *env, jclass cls, jstring name, jint index) {
-    if (getFlags(env, name) & IFF_LOOPBACK)
-      return JNI_TRUE;
-    return JNI_FALSE;
+    return -1;
 }
 
-/*
- * Class:     java_net_NetworkInterface
- * Method:    supportsMulticast0
- * Signature: (Ljava/lang/String;I)Z
- */
-JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
-(JNIEnv *env, jclass cls, jstring name, jint index) {
-  short val;
+static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
+    struct lifreq if2;
 
-  val = getFlags(env, name);
-  if (val & IFF_MULTICAST)
-    return JNI_TRUE;
-  return JNI_FALSE;
-}
+    memset((char *) &if2, 0, sizeof(if2));
+    strcpy(if2.lifr_name, ifname);
 
-/*
- * Class:     java_net_NetworkInterface
- * Method:    getMacAddr0
- * Signature: ([bLjava/lang/String;I)[b
- */
-JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
-  jint addr;
-  jbyte caddr[4];
-  struct in_addr iaddr;
-  jbyteArray ret = NULL;
-  unsigned char mac[16];
-  int len;
-  jboolean isCopy;
-  const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+    if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
+        return -1;
+    }
 
-  if (!IS_NULL(addrArray)) {
-    (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
-    addr = ((caddr[0]<<24) & 0xff000000);
-    addr |= ((caddr[1] <<16) & 0xff0000);
-    addr |= ((caddr[2] <<8) & 0xff00);
-    addr |= (caddr[3] & 0xff);
-    iaddr.s_addr = htonl(addr);
-    len = getMacAddress(env, &iaddr, name_utf, mac);
-  } else {
-    len = getMacAddress(env, NULL, name_utf, mac);
-  }
-  if (len > 0) {
-    ret = (*env)->NewByteArray(env, len);
-    if (IS_NULL(ret)) {
-      /* we may have memory to free at the end of this */
-      goto fexit;
-    }
-    (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
-  }
- fexit:
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
-  return ret;
+    return  if2.lifr_mtu;
 }
 
-/*
- * Class:       java_net_NetworkInterface
- * Method:      getMTU0
- * Signature:   ([bLjava/lang/String;I)I
- */
 
-JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
-  jboolean isCopy;
-  int sock;
-  struct ifreq if2;
-  int ret = -1;
-  const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
-
-  sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-  if (sock < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                 "Socket creation failed");
-  } else {
-
-#ifdef __linux__
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.ifr_name, name_utf);
+static int getFlags(JNIEnv *env, int sock, const char *ifname) {
+     struct   lifreq lifr;
+     memset((caddr_t)&lifr, 0, sizeof(lifr));
+     strcpy((caddr_t)&(lifr.lifr_name), ifname);
 
-    if (ioctl(sock, SIOCGIFMTU, (char *)&if2) >= 0) {
-      ret= if2.ifr_mtu;
-    } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                   "IOCTL failed");
-    }
-#else /* Solaris */
-    struct   lifreq lifr;
-    memset((caddr_t)&lifr, 0, sizeof(lifr));
-    strcpy((caddr_t)&(lifr.lifr_name), name_utf);
-    if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
-      ret = lifr.lifr_mtu;
-#ifdef AF_INET6
-    } else {
-      /* Try wIth an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
-      close(sock);
-      sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
+         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+         return -1;
+     }
 
-      if (sock < 0) {
-        (*env)->ReleaseStringUTFChars(env, name, name_utf);
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "Socket creation failed");
-        return -1;
-      }
+     return  lifr.lifr_flags;
+}
+
 
-      if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
-        ret = lifr.lifr_mtu;
-      } else {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "IOCTL failed");
-      }
-    }
-#else
-    } else {
-        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "IOCTL failed");
-    }
 #endif
-#endif
-    close(sock);
-  }
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
-  return ret;
-}
+
+
--- a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c	Wed Jul 05 17:17:57 2017 +0200
@@ -42,6 +42,29 @@
             filename);
 }
 
+static void quit(gboolean isSignalHandler)
+{
+    if (dialog != NULL)
+    {
+        // Callbacks from GTK signals are made within the GTK lock
+        // So, within a signal handler there is no need to call
+        // gdk_threads_enter() / fp_gdk_threads_leave()
+        if (!isSignalHandler) {
+            fp_gdk_threads_enter();
+        }
+
+        fp_gtk_widget_hide (dialog);
+        fp_gtk_widget_destroy (dialog);
+
+        fp_gtk_main_quit ();
+        dialog = NULL;
+
+        if (!isSignalHandler) {
+            fp_gdk_threads_leave();
+        }
+    }
+}
+
 /*
  * Class:     sun_awt_X11_GtkFileDialogPeer
  * Method:    quit
@@ -50,18 +73,7 @@
 JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
 (JNIEnv * env, jobject jpeer)
 {
-    if (dialog != NULL)
-    {
-        fp_gdk_threads_enter();
-
-        fp_gtk_widget_hide (dialog);
-        fp_gtk_widget_destroy (dialog);
-
-        fp_gtk_main_quit ();
-        dialog = NULL;
-
-        fp_gdk_threads_leave();
-    }
+    quit(FALSE);
 }
 
 /**
@@ -147,7 +159,7 @@
             jfilenames);
     fp_g_free(current_folder);
 
-    Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL);
+    quit(TRUE);
 }
 
 /*
--- a/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c	Wed Jul 05 17:17:57 2017 +0200
@@ -65,6 +65,11 @@
 
     J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps");
 
+    if (oglsdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+        return;
+    }
+
     if (glxsdo == NULL) {
         JNU_ThrowOutOfMemoryError(env, "creating native GLX ops");
         return;
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Wed Jul 05 17:17:57 2017 +0200
@@ -253,6 +253,10 @@
 {
 #ifndef HEADLESS
     X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps));
+    if (xsdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+        return;
+    }
     xsdo->sdOps.Lock = X11SD_Lock;
     xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo;
     xsdo->sdOps.Unlock = X11SD_Unlock;
--- a/jdk/src/windows/bin/java_md.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/windows/bin/java_md.c	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, 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
@@ -80,26 +80,22 @@
  *
  */
 void
-CreateExecutionEnvironment(int *_argc,
-                           char ***_argv,
-                           char jrepath[],
-                           jint so_jrepath,
-                           char jvmpath[],
-                           jint so_jvmpath,
-                           char **original_argv) {
+CreateExecutionEnvironment(int *pargc, char ***pargv,
+                           char *jrepath, jint so_jrepath,
+                           char *jvmpath, jint so_jvmpath) {
     char * jvmtype;
     int i = 0;
-    char** pargv = *_argv;
     int running = CURRENT_DATA_MODEL;
 
     int wanted = running;
 
-    for (i = 0; i < *_argc ; i++) {
-        if (JLI_StrCmp(pargv[i], "-J-d64") == 0 || JLI_StrCmp(pargv[i], "-d64") == 0) {
+    char** argv = *pargv;
+    for (i = 0; i < *pargc ; i++) {
+        if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) {
             wanted = 64;
             continue;
         }
-        if (JLI_StrCmp(pargv[i], "-J-d32") == 0 || JLI_StrCmp(pargv[i], "-d32") == 0) {
+        if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) {
             wanted = 32;
             continue;
         }
@@ -123,7 +119,12 @@
         JLI_ReportErrorMessage(CFG_ERROR7);
         exit(1);
     }
-    jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE);
+
+    jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE);
+    if (JLI_StrCmp(jvmtype, "ERROR") == 0) {
+        JLI_ReportErrorMessage(CFG_ERROR9);
+        exit(4);
+    }
 
     jvmpath[0] = '\0';
     if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) {
@@ -131,7 +132,6 @@
         exit(4);
     }
     /* If we got here, jvmpath has been correctly initialized. */
-
 }
 
 
@@ -203,19 +203,21 @@
     PREJVMSTART PreJVMStart;
     struct stat s;
 
+    /* Make sure the jrepath contains something */
+    if (jrepath[0] == NULL) {
+        return;
+    }
     /* 32 bit windows only please */
-    if (strcmp(GetArch(), "i386") != 0 ) {
+    if (JLI_StrCmp(GetArch(), "i386") != 0 ) {
         return;
     }
     /* Does our bundle directory exist ? */
-    strcpy(tmpbuf, jrepath);
-    strcat(tmpbuf, "\\lib\\bundles");
+    JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\lib\\bundles", jrepath);
     if (stat(tmpbuf, &s) != 0) {
         return;
     }
     /* Does our jkernel dll exist ? */
-    strcpy(tmpbuf, jrepath);
-    strcat(tmpbuf, "\\bin\\jkernel.dll");
+    JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\bin\\jkernel.dll", jrepath);
     if (stat(tmpbuf, &s) != 0) {
         return;
     }
@@ -249,30 +251,30 @@
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
-        sprintf(javadll, "%s\\bin\\" JAVA_DLL, path);
+        JLI_Snprintf(javadll, sizeof(javadll), "%s\\bin\\" JAVA_DLL, path);
         if (stat(javadll, &s) == 0) {
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
 
         /* Does this app ship a private JRE in <apphome>\jre directory? */
-        sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path);
+        JLI_Snprintf(javadll, sizeof (javadll), "%s\\jre\\bin\\" JAVA_DLL, path);
         if (stat(javadll, &s) == 0) {
             JLI_StrCat(path, "\\jre");
-            goto found;
+            JLI_TraceLauncher("JRE path is %s\n", path);
+            return JNI_TRUE;
         }
     }
 
     /* Look for a public JRE on this machine. */
     if (GetPublicJREHome(path, pathsize)) {
-        goto found;
+        JLI_TraceLauncher("JRE path is %s\n", path);
+        return JNI_TRUE;
     }
 
     JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
     return JNI_FALSE;
 
- found:
-    JLI_TraceLauncher("JRE path is %s\n", path);
-    return JNI_TRUE;
 }
 
 /*
@@ -286,9 +288,9 @@
 {
     struct stat s;
     if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) {
-        sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype);
     } else {
-        sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
+        JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
     }
     if (stat(jvmpath, &s) == 0) {
         return JNI_TRUE;
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java	Wed Jul 05 17:17:57 2017 +0200
@@ -312,14 +312,17 @@
         private int processSelectedKeys(long updateCount) {
             int numKeysUpdated = 0;
             numKeysUpdated += processFDSet(updateCount, readFds,
-                                           PollArrayWrapper.POLLIN);
+                                           PollArrayWrapper.POLLIN,
+                                           false);
             numKeysUpdated += processFDSet(updateCount, writeFds,
                                            PollArrayWrapper.POLLCONN |
-                                           PollArrayWrapper.POLLOUT);
+                                           PollArrayWrapper.POLLOUT,
+                                           false);
             numKeysUpdated += processFDSet(updateCount, exceptFds,
                                            PollArrayWrapper.POLLIN |
                                            PollArrayWrapper.POLLCONN |
-                                           PollArrayWrapper.POLLOUT);
+                                           PollArrayWrapper.POLLOUT,
+                                           true);
             return numKeysUpdated;
         }
 
@@ -331,7 +334,9 @@
          *
          * me.updateCount <= me.clearedCount <= updateCount
          */
-        private int processFDSet(long updateCount, int[] fds, int rOps) {
+        private int processFDSet(long updateCount, int[] fds, int rOps,
+                                 boolean isExceptFds)
+        {
             int numKeysUpdated = 0;
             for (int i = 1; i <= fds[0]; i++) {
                 int desc = fds[i];
@@ -347,6 +352,17 @@
                 if (me == null)
                     continue;
                 SelectionKeyImpl sk = me.ski;
+
+                // The descriptor may be in the exceptfds set because there is
+                // OOB data queued to the socket. If there is OOB data then it
+                // is discarded and the key is not added to the selected set.
+                if (isExceptFds &&
+                    (sk.channel() instanceof SocketChannelImpl) &&
+                    discardUrgentData(desc))
+                {
+                    continue;
+                }
+
                 if (selectedKeys.contains(sk)) { // Key in selected set
                     if (me.clearedCount != updateCount) {
                         if (sk.channel.translateAndSetReadyOps(rOps, sk) &&
@@ -460,6 +476,8 @@
 
     private native void resetWakeupSocket0(int wakeupSourceFd);
 
+    private native boolean discardUrgentData(int fd);
+
     // We increment this counter on each call to updateSelectedKeys()
     // each entry in  SubSelector.fdsMap has a memorized value of
     // updateCount. When we increment numKeysUpdated we set updateCount
--- a/jdk/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c	Wed Jul 05 17:17:57 2017 +0200
@@ -66,6 +66,10 @@
 
     J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_initOps");
 
+    if (oglsdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+        return;
+    }
     if (wglsdo == NULL) {
         JNU_ThrowOutOfMemoryError(env, "creating native wgl ops");
         return;
--- a/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp	Wed Jul 05 17:17:57 2017 +0200
@@ -363,6 +363,10 @@
 {
     J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initOps");
     GDIWinSDOps *wsdo = (GDIWinSDOps *)SurfaceData_InitOps(env, wsd, sizeof(GDIWinSDOps));
+    if (wsdo == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
+        return;
+    }
     wsdo->sdOps.Lock = GDIWinSD_Lock;
     wsdo->sdOps.GetRasInfo = GDIWinSD_GetRasInfo;
     wsdo->sdOps.Unlock = GDIWinSD_Unlock;
--- a/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c	Wed Jul 05 17:17:57 2017 +0200
@@ -214,3 +214,19 @@
         recv(scinFd, bytes, WAKEUP_SOCKET_BUF_SIZE, 0);
     }
 }
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_WindowsSelectorImpl_discardUrgentData(JNIEnv* env, jobject this,
+                                                      jint s)
+{
+    char data[8];
+    jboolean discarded = JNI_FALSE;
+    int n;
+    do {
+        n = recv(s, &data, sizeof(data), MSG_OOB);
+        if (n > 0) {
+            discarded = JNI_TRUE;
+        }
+    } while (n > 0);
+    return discarded;
+}
--- a/jdk/test/Makefile	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/Makefile	Wed Jul 05 17:17:57 2017 +0200
@@ -495,19 +495,17 @@
 jdk_nio1: java/nio/file
 	$(call RunSamevmBatch)
 
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-#   Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_nio2
 jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
           java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
 	$(call SharedLibraryPermissions,java/nio/channels)
-	$(call RunOthervmBatch)
+	$(call RunSamevmBatch)
 
-# Stable othervm testruns (minus items from PROBLEM_LIST)
-#   Using samevm has serious problems with these tests
+# Stable samevm testruns (minus items from PROBLEM_LIST)
 JDK_ALL_TARGETS += jdk_nio3
 jdk_nio3: com/sun/nio sun/nio
-	$(call RunOthervmBatch)
+	$(call RunSamevmBatch)
 
 # All nio tests
 jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
--- a/jdk/test/ProblemList.txt	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 17:17:57 2017 +0200
@@ -295,9 +295,6 @@
 
 # jdk_misc
 
-# On Windows com.sun.java.swing.plaf.gtk does not exist, always fails there
-com/sun/java/swing/plaf/gtk/Test6635110.java		 	windows-all
-
 # Need to be marked othervm, or changed to be samevm safe
 com/sun/jndi/ldap/ReadTimeoutTest.java				generic-all
 com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java	generic-all
@@ -379,9 +376,6 @@
 #   Interrupted or IO exception, maybe writing to non-unique named file?
 com/sun/net/httpserver/bugs/B6373555.java			generic-all
 
-# Fails on OpenSolaris, BindException unexpected 
-java/net/BindException/Test.java				generic-all
-
 # Fails on OpenSolaris, times out
 java/net/MulticastSocket/SetOutgoingIf.java			generic-all
 
@@ -507,25 +501,46 @@
 
 ############################################################################
 
+# jdk_io
+
+# 6962637
+java/io/File/MaxPathLength.java                                 windows-all
+
+############################################################################
+
 # jdk_nio
 
-# Suspect many of these tests auffer from using fixed ports, no concrete 
-#   evidence.
+# 6944810
+java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java       windows-all
+
+# 6963118
+java/nio/channels/Selector/Wakeup.java                          windows-all
 
-# Occasionally Failing with java.lang.AssertionError on Windows X64
-#  at sun.nio.ch.PendingIoCache.clearPendingIoMap(PendingIoCache.java:144)
-#java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java	windows-all
+# The asynchronous I/O implementation on Windows requires Windows XP or newer.
+# We can remove the following once all Windows 2000 machines have been
+# decommissioned.
+java/nio/channels/AsynchronousChannelGroup/Basic.java           windows-5.0
+java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java      windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Identity.java        windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Restart.java         windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Unbounded.java       windows-5.0
+java/nio/channels/AsynchronousDatagramChannel/Basic.java        windows-5.0
+java/nio/channels/AsynchronousFileChannel/Lock.java             windows-5.0
+java/nio/channels/AsynchronousServerSocketChannel/Basic.java    windows-5.0
+java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/Basic.java          windows-5.0
+java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/Leaky.java          windows-5.0
+java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0
+java/nio/channels/Channels/Basic2.java                          windows-5.0
 
-# Some kind of sleep/wake problem on Windows X64
-java/nio/channels/Selector/Wakeup.java				windows-all
+# 6959891
+com/sun/nio/sctp/SctpChannel/SocketOptionTests.java
 
 # Fails with -ea -esa, Assertion error, but only on Solaris 10 machines?
 com/sun/nio/sctp/SctpChannel/Send.java				generic-all
 com/sun/nio/sctp/SctpChannel/Shutdown.java			generic-all
 
-# Fails on Windows 2000,  times out
-java/nio/channels/FileChannel/Transfer.java			generic-all
-
 # Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses 
 #    from a channel that is bound to the wildcard address
 com/sun/nio/sctp/SctpChannel/Bind.java				generic-all
@@ -533,18 +548,6 @@
 # Failed on OpenSolaris, java.lang.AssertionError: Unknown event type
 com/sun/nio/sctp/SctpChannel/Receive.java			generic-all
 
-# Triggers a hotspot crash on Fedora 9 32bit -server and Windows X64  samevm
-sun/nio/cs/TestUTF8.java					generic-all
-
-# Runtime exception on windows X64, samevm mode
-java/nio/channels/Selector/WakeupNow.java			generic-all
-
-# Occasional errors, solarix x86, address already in use, othervm mode
-java/nio/channels/Selector/SelectorTest.java			generic-all
-
-# Fails on Linux Fedora 9 X64
-sun/nio/cs/FindDecoderBugs.java					generic-all
-
 # Solaris 11 gave assert error and "connection refused", samevm issues?
 com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java 	generic-all
 
@@ -555,49 +558,6 @@
 com/sun/nio/sctp/SctpMultiChannel/Send.java			generic-all
 com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java	generic-all
 
-# Linux 64bit failures. too many files open
-java/nio/channels/Selector/HelperSlowToDie.java			generic-all
-
-# Gets java.lang.ExceptionInInitializerError on Windows 2000 (need XP or newer)
-java/nio/channels/AsynchronousChannelGroup/Basic.java	 	windows-5.0
-java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java 	windows-5.0
-java/nio/channels/AsynchronousChannelGroup/Identity.java 	windows-5.0
-java/nio/channels/AsynchronousChannelGroup/Restart.java 	windows-5.0
-java/nio/channels/AsynchronousChannelGroup/Unbounded.java	windows-5.0
-java/nio/channels/AsynchronousDatagramChannel/Basic.java 	windows-5.0
-java/nio/channels/AsynchronousFileChannel/Lock.java	 	windows-5.0
-java/nio/channels/AsynchronousServerSocketChannel/Basic.java 	windows-5.0
-java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0
-java/nio/channels/AsynchronousSocketChannel/Basic.java	 	windows-5.0
-java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0
-java/nio/channels/AsynchronousSocketChannel/Leaky.java	 	windows-5.0
-java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0
-java/nio/channels/Channels/Basic2.java			 	windows-5.0
-
-# Failed loopback connection? On windows 32bit? 
-#   Considered a stress test, can consume all resources.
-java/nio/channels/Selector/LotsOfChannels.java		 	generic-all
-
-# Windows i586 client, crashed hotspot? Unpredictable
-#   Considered a stress test, can consume all resources.
-java/nio/channels/Selector/RegAfterPreClose.java	 	generic-all
-
-# Solaris i586, cannot assign address, samevm issues
-java/nio/channels/Selector/SelectorLimit.java		 	generic-all
-
-# Socket timeout windows X64
-java/nio/channels/ServerSocketChannel/AdaptServerSocket.java 	windows-all
-
-# Timeouts etc. on Window
-java/nio/channels/SocketChannel/ConnectState.java	 	windows-all
-java/nio/channels/SocketChannel/FinishConnect.java	 	windows-all
-
-# Fails on all platforms due to overlap of JDK jar file contents:
-sun/nio/cs/Test4200310.sh				 	generic-all
-
-# Depends on motif packages that do not exist all the time:
-sun/nio/cs/TestX11CNS.java				 	generic-all
-
 ############################################################################
 
 # jdk_rmi
@@ -848,9 +808,6 @@
 
 # jdk_swing (not using samevm)
 
-# Fails on solaris 10 sparc, throws RuntimeException that just says "failed"
-javax/swing/JLabel/6501991/bug6501991.java			generic-all
-
 # Fails on solaris 11 i586, with othervm
 javax/swing/JFileChooser/6570445/bug6570445.java		generic-all
 javax/swing/JFileChooser/6738668/bug6738668.java		generic-all
--- a/jdk/test/com/sun/java/swing/plaf/gtk/Test6635110.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/com/sun/java/swing/plaf/gtk/Test6635110.java	Wed Jul 05 17:17:57 2017 +0200
@@ -28,7 +28,6 @@
    @run main Test6635110
 */
 
-import com.sun.java.swing.plaf.gtk.GTKLookAndFeel;
 import javax.swing.*;
 import java.awt.*;
 import java.awt.image.BufferedImage;
@@ -59,7 +58,12 @@
     }
 
     public static void main(String[] args) throws Exception {
-        UIManager.setLookAndFeel(new GTKLookAndFeel());
+        try {
+            UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+        } catch (Exception e) {
+            System.out.println("GTKLookAndFeel cannot be set, skipping this test");
+            return;
+        }
         SwingUtilities.invokeAndWait(new Test6635110());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/java/swing/plaf/gtk/Test6963870.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @bug 6963870
+   @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets()
+            doesn't return null
+   @author Peter Zhelezniakov
+   @run main Test6963870
+*/
+
+import java.awt.Insets;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+
+public class Test6963870 implements Runnable {
+
+    final static String[] UI_NAMES = {
+        "List.focusCellHighlightBorder",
+        "List.focusSelectedCellHighlightBorder",
+        "List.noFocusBorder",
+        "Table.focusCellHighlightBorder",
+        "Table.focusSelectedCellHighlightBorder",
+    };
+
+    public void run() {
+        for (String uiName: UI_NAMES) {
+            test(uiName);
+        }
+    }
+
+    void test(String uiName) {
+        Border b = UIManager.getBorder(uiName);
+        Insets i = b.getBorderInsets(null);
+        if (i == null) {
+            throw new RuntimeException("getBorderInsets() returns null for " + uiName);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        try {
+            UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+        } catch (Exception e) {
+            System.out.println("GTKLookAndFeel cannot be set, skipping this test");
+            return;
+        }
+
+        SwingUtilities.invokeAndWait(new Test6963870());
+    }
+}
+
--- a/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2010, 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 6304473 6727884
--- a/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java	Wed Jul 05 17:17:57 2017 +0200
@@ -34,35 +34,40 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.lang.Math;
+
+import sun.awt.SunToolkit;
+
 import test.java.awt.regtesthelpers.Util;
 
 public class LoopRobustness {
-    static int clicks = 0;
+
     final static long TIMEOUT = 5000;
     final static Object LOCK = new Object();
-    static volatile boolean notifyOccur = false;
 
-    public static void main(String [] args)  {
+    public static int clicks = 0;
+    public static volatile boolean notifyOccured = false;
+    public static volatile boolean otherExceptionsCaught = false;
+
+    public static void main(String [] args) throws Exception {
         ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
 
         long at;
         //wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff.
-        synchronized (LoopRobustness.LOCK){
+        synchronized (LoopRobustness.LOCK) {
             new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start();
             at = System.currentTimeMillis();
             try {
-                while(!notifyOccur && System.currentTimeMillis() - at < TIMEOUT) {
+                while (!notifyOccured && (System.currentTimeMillis() - at < TIMEOUT)) {
                     LoopRobustness.LOCK.wait(1000);
                 }
-            } catch(InterruptedException e){
+            } catch (InterruptedException e) {
                 throw new RuntimeException("Test interrupted.", e);
             }
         }
 
-        if( !notifyOccur){
+        if (!notifyOccured) {
             //notify doesn't occur after a reasonable time.
-            throw new RuntimeException("Test failed. Second Thread didn't notify MainThread.");
+            throw new RuntimeException("Test FAILED: second thread hasn't notified MainThread");
         }
 
         //now wait for two clicks
@@ -75,7 +80,10 @@
             }
         }
         if (clicks != 2) {
-            throw new RuntimeException("robot should press button twice");
+            throw new RuntimeException("Test FAILED: robot should press button twice");
+        }
+        if (otherExceptionsCaught) {
+            throw new RuntimeException("Test FAILED: unexpected exceptions caught");
         }
     }
 }
@@ -83,18 +91,11 @@
 class Impl implements Runnable{
     static Robot robot;
     public void run() {
+        SunToolkit.createNewAppContext();
+
         Button b = new Button("Press me to test the AWT-Event Queue thread");
         Frame lr = new Frame("ROBUST FRAME");
-        /* Must load Toolkit on this thread only, rather then on Main.
-           If load on Main (on the parent ThreadGroup of current ThreadGroup) then
-           EDT will be created on Main thread and supplied with it's own exceptionHandler,
-           which just throws an Exception and terminates current thread.
-           The test implies that EDT is created on the child ThreadGroup (testThreadGroup)
-           which is supplied with its own uncaughtException().
-        */
-        Toolkit.getDefaultToolkit();
         lr.setBounds(100, 100, 300, 100);
-
         b.addActionListener(new ActionListener() {
                 public void actionPerformed(ActionEvent e) {
                     LoopRobustness.clicks++;
@@ -107,40 +108,46 @@
 
         try {
             robot = new Robot();
-        } catch(AWTException e){
+        } catch (AWTException e) {
             throw new RuntimeException("Test interrupted.", e);
         }
         Util.waitForIdle(robot);
 
         synchronized (LoopRobustness.LOCK){
             LoopRobustness.LOCK.notify();
-            LoopRobustness.notifyOccur = true;
+            LoopRobustness.notifyOccured = true;
         }
 
         int i = 0;
-        while(i < 2){
+        while (i < 2) {
             robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2,
-                            b.getLocationOnScreen().y + b.getHeight()/2 );
+                            b.getLocationOnScreen().y + b.getHeight()/2);
+            Util.waitForIdle(robot);
             robot.mousePress(InputEvent.BUTTON1_MASK);
-            //                robot.delay(10);
+            Util.waitForIdle(robot);
             robot.mouseRelease(InputEvent.BUTTON1_MASK);
+            Util.waitForIdle(robot);
             i++;
-            robot.delay(1000);
         }
     }
 }
 
 class TestThreadGroup extends ThreadGroup {
-    TestThreadGroup(ThreadGroup threadGroup, String name){
+    TestThreadGroup(ThreadGroup threadGroup, String name) {
         super(threadGroup, name);
     }
 
-    public void uncaughtException(Thread exitedThread, Throwable e) {
-        e.printStackTrace();
-        if ((e instanceof ExceptionInInitializerError) || (e instanceof
-                NoClassDefFoundError)){
-            throw new RuntimeException("Test failed: other Exceptions were thrown ", e);
+    public void uncaughtException(Thread thread, Throwable e) {
+        System.out.println("Exception caught: " + e);
+        e.printStackTrace(System.out);
+        System.out.flush();
+        if ((e instanceof ExceptionInInitializerError) ||
+            (e instanceof NoClassDefFoundError))
+        {
+            // These two are expected
+            return;
         }
+        LoopRobustness.otherExceptionsCaught = true;
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/EventDispatchThread/PreserveDispathThread/PreserveDispatchThread.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2010, 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 6424157
+  @author Artem Ananiev: area=eventqueue
+  @run main PreserveDispatchThread
+*/
+
+import java.awt.*;
+import java.awt.event.*;
+
+public class PreserveDispatchThread {
+
+    private static volatile Frame f;
+    private static volatile Dialog d;
+
+    private static volatile boolean isEDT = true;
+
+    public static void main(String[] args) throws Exception {
+        f = new Frame("F");
+        f.setSize(320, 340);
+        f.setLocationRelativeTo(null);
+        f.setVisible(true);
+
+        try {
+            test1();
+            if (!isEDT) {
+                throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed");
+            }
+
+            test2();
+            if (!isEDT) {
+                throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed");
+            }
+
+            test3();
+            if (!isEDT) {
+                throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed");
+            }
+        } finally {
+            if (d != null) {
+                d.dispose();
+            }
+            f.dispose();
+        }
+    }
+
+    /*
+     * Tests that push/pop doesn't change the dispatch thread if
+     * called on EDT.
+     */
+    private static void test1() throws Exception {
+        EventQueue.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                TestEventQueue teq = new TestEventQueue();
+                EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+                try {
+                    seq.push(teq);
+                    d = new TestDialog();
+                    d.setVisible(true);
+                    checkEDT();
+                } finally {
+                    teq.pop();
+                }
+                checkEDT();
+            }
+        });
+    }
+
+    /*
+     * Tests that push/pop doesn't change the dispatch thread if
+     * called on the main thread.
+     */
+    private static void test2() throws Exception {
+        TestEventQueue teq = new TestEventQueue();
+        EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+        try {
+            seq.push(teq);
+            EventQueue.invokeAndWait(new Runnable() {
+                @Override
+                public void run() {
+                    checkEDT();
+                    d = new TestDialog();
+                    d.setVisible(true);
+                    checkEDT();
+                }
+            });
+        } finally {
+            teq.pop();
+        }
+    }
+
+    private static final Object test3Lock = new Object();
+    private static boolean test3Sync = false;
+
+    /*
+     * A complex test: several nested invokeLater() are called and
+     * in every runnable a check for EDT is performed. At the ent
+     * of the test we wait for all the runnables to be processed
+     * and the dialog is disposed; otherwise the last EDT check can
+     * be later than this method returns and the whole test is passed.
+     */
+    private static void test3() throws Exception {
+        EventQueue.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                d = new Dialog(f, true);
+                d.setSize(240, 180);
+                d.setLocationRelativeTo(f);
+                EventQueue.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        d.setVisible(true);
+                        checkEDT();
+                    }
+                });
+                EventQueue.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        TestEventQueue teq = new TestEventQueue();
+                        EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+                        try {
+                            seq.push(teq);
+                            checkEDT();
+                            EventQueue.invokeLater(new Runnable() {
+                                @Override
+                                public void run() {
+                                    d.dispose();
+                                    checkEDT();
+                                    synchronized (test3Lock) {
+                                        test3Sync = true;
+                                        test3Lock.notify();
+                                    }
+                                }
+                            });
+                        } finally {
+                            teq.pop();
+                        }
+                        checkEDT();
+                    }
+                });
+                checkEDT();
+            }
+        });
+        synchronized (test3Lock) {
+            while (!test3Sync) {
+                try {
+                    test3Lock.wait();
+                } catch (InterruptedException ie) {
+                    break;
+                }
+            }
+        }
+        // Make sure all the nested invokeLater/invokeAndWait are processed
+        EventQueue.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+            }
+        });
+    }
+
+    private static void checkEDT() {
+        isEDT = isEDT && EventQueue.isDispatchThread();
+    }
+
+    private static class TestEventQueue extends EventQueue {
+        public TestEventQueue() {
+            super();
+        }
+        public void pop() {
+            super.pop();
+        }
+    }
+
+    private static class TestDialog extends Dialog {
+        private volatile boolean dialogShown = false;
+        private volatile boolean paintCalled = false;
+        public TestDialog() {
+            super(f, true);
+            setSize(240, 180);
+            setLocationRelativeTo(f);
+            addComponentListener(new ComponentAdapter() {
+                @Override
+                public void componentShown(ComponentEvent e) {
+                    if (paintCalled) {
+                        dispose();
+                    }
+                    dialogShown = true;
+                }
+            });
+        }
+        @Override
+        public void paint(Graphics g) {
+            if (dialogShown) {
+                dispose();
+            }
+            paintCalled = true;
+        }
+    }
+
+}
--- a/jdk/test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java	Wed Jul 05 17:17:57 2017 +0200
@@ -43,6 +43,7 @@
         Runnable dummy = new Runnable() {
                 public void run() {
                     System.err.println("Dummy is here.");
+                    System.err.flush();
                 }
             };
         EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
@@ -58,10 +59,11 @@
         Runnable runnable = new Runnable() {
                 public void run() {
                     System.err.println("Dummy from SunToolkit");
+                    System.err.flush();
                 }
             };
         InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false);
-        System.err.println(ie);
+//        System.err.println(ie);
         SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie);
         eq1.pop();
         frame.dispose();
@@ -70,14 +72,14 @@
 
 class MyEventQueue1 extends EventQueue {
 
-    public void pop() throws EmptyStackException {
+    public void pop() {
         super.pop();
     }
 }
 
 class MyEventQueue2 extends EventQueue {
 
-    protected void pop() throws EmptyStackException {
+    protected void pop() {
         System.err.println("pop2()");
         Thread.dumpStack();
         try {
@@ -85,7 +87,8 @@
                     public void run() {
                         Runnable runnable = new Runnable() {
                                 public void run() {
-                                    System.err.println("Dummy from here");
+                                    System.err.println("Dummy from pop");
+                                    System.err.flush();
                                 }
                              };
                         InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
--- a/jdk/test/java/awt/FontClass/FontPrivilege.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/awt/FontClass/FontPrivilege.java	Wed Jul 05 17:17:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5010310 6319835 6904882
+ * @bug 5010310 6319835 6904882 6968373
  * @summary test fonts can be created in the presence of a security manager
  * @run main/othervm/secure=java.lang.SecurityManager FontPrivilege
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test6707234.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 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 6707234
+ * @summary Tests setter in a complex bean
+ * @author Sergey Malenkov
+ */
+
+public class Test6707234 {
+    public static void main(String[] args) {
+        if (null == BeanUtils.getPropertyDescriptor(C.class, "number").getWriteMethod()) {
+            throw new Error("no write method");
+        }
+    }
+
+    public interface I {
+        void setNumber(Object number);
+        Number getNumber();
+    }
+
+    public class C implements I {
+        public void setNumber(Object value) {
+        }
+        public void setNumber(Long value) {
+        }
+        public Long getNumber() {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test6963811.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010, 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 6963811
+ * @summary Tests deadlock in Introspector
+ * @author Sergey Malenkov
+ */
+
+import java.beans.Introspector;
+import java.beans.SimpleBeanInfo;
+
+public class Test6963811 implements Runnable {
+    private final long time;
+    private final boolean sync;
+
+    public Test6963811(long time, boolean sync) {
+        this.time = time;
+        this.sync = sync;
+    }
+
+    public void run() {
+        try {
+            Thread.sleep(this.time); // increase the chance of the deadlock
+            Introspector.getBeanInfo(
+                    this.sync ? Super.class : Sub.class,
+                    this.sync ? null : Object.class);
+        }
+        catch (Exception exception) {
+            exception.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Thread[] threads = new Thread[2];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i] = new Thread(new Test6963811(0L, i > 0));
+            threads[i].start();
+            Thread.sleep(500L); // increase the chance of the deadlock
+        }
+        for (Thread thread : threads) {
+            thread.join();
+        }
+    }
+
+    public static class Super {
+    }
+
+    public static class Sub extends Super {
+    }
+
+    public static class SubBeanInfo extends SimpleBeanInfo {
+        public SubBeanInfo() {
+            new Test6963811(1000L, true).run();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/PropertyEditor/Test6963811.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, 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 6963811
+ * @summary Tests deadlock in PropertyEditorManager
+ * @author Sergey Malenkov
+ */
+
+import java.beans.PropertyEditorManager;
+import sun.beans.editors.StringEditor;
+
+public class Test6963811 implements Runnable {
+    private final long time;
+    private final boolean sync;
+
+    public Test6963811(long time, boolean sync) {
+        this.time = time;
+        this.sync = sync;
+    }
+
+    public void run() {
+        try {
+            Thread.sleep(this.time); // increase the chance of the deadlock
+            if (this.sync) {
+                synchronized (Test6963811.class) {
+                    PropertyEditorManager.findEditor(Super.class);
+                }
+            }
+            else {
+                PropertyEditorManager.findEditor(Sub.class);
+            }
+        }
+        catch (Exception exception) {
+            exception.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Thread[] threads = new Thread[2];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i] = new Thread(new Test6963811(0L, i > 0));
+            threads[i].start();
+            Thread.sleep(500L); // increase the chance of the deadlock
+        }
+        for (Thread thread : threads) {
+            thread.join();
+        }
+    }
+
+    public static class Super {
+    }
+
+    public static class Sub extends Super {
+    }
+
+    public static class SubEditor extends StringEditor {
+        public SubEditor() {
+            new Test6963811(1000L, true).run();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/Test6963811.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010, 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 6963811
+ * @summary Tests deadlock in Encoder
+ * @author Sergey Malenkov
+ */
+
+import java.beans.Encoder;
+import java.beans.DefaultPersistenceDelegate;
+
+public class Test6963811 implements Runnable {
+    private static final Encoder ENCODER = new Encoder();
+    private final long time;
+    private final boolean sync;
+
+    public Test6963811(long time, boolean sync) {
+        this.time = time;
+        this.sync = sync;
+    }
+
+    public void run() {
+        try {
+            Thread.sleep(this.time); // increase the chance of the deadlock
+            if (this.sync) {
+                synchronized (Test6963811.class) {
+                    ENCODER.getPersistenceDelegate(Super.class);
+                }
+            }
+            else {
+                ENCODER.getPersistenceDelegate(Sub.class);
+            }
+        }
+        catch (Exception exception) {
+            exception.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Thread[] threads = new Thread[2];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i] = new Thread(new Test6963811(0L, i > 0));
+            threads[i].start();
+            Thread.sleep(500L); // increase the chance of the deadlock
+        }
+        for (Thread thread : threads) {
+            thread.join();
+        }
+    }
+
+    public static class Super {
+    }
+
+    public static class Sub extends Super {
+    }
+
+    public static class SubPersistenceDelegate extends DefaultPersistenceDelegate {
+        public SubPersistenceDelegate() {
+            new Test6963811(1000L, true).run();
+        }
+    }
+}
--- a/jdk/test/java/lang/String/Supplementary.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/lang/String/Supplementary.java	Wed Jul 05 17:17:57 2017 +0200
@@ -62,7 +62,7 @@
          0     1     2345     678     9     012     345678     9 01     2     */
         "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
 
-        // includes an undefined supprementary characters in Unicode 4.0.0
+        // includes an undefined supplementary character in Unicode 4.0.0
       /*                                    1     11     1     1111     1
          0     1     2345     6     789     0     12     3     4567     8     */
         "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
@@ -168,7 +168,7 @@
      * string in input[m].
      *
      * The meaning of each element in golden3[][n]
-     *   golden3[][0]: characater which is searched.
+     *   golden3[][0]: character which is searched.
      *   golden3[][2]: the golden data for indexOf(int ch)
      *   From golden3[][2] to golden3[][n-1]:
      *       the golden data for indexOf(int ch, int fromIndex)
@@ -201,17 +201,17 @@
             /*
              * Normal case
              */
-            testIndexOf(First, s, golden3[i][0], golden3[i][2]);
+            testIndexOf(s, golden3[i][0], golden3[i][2]);
 
             /*
              * Abnormal case - char which isn't included in the string.
              */
-            testIndexOf(First, s, 'Z', -1);
-            testIndexOf(First, s, 0xDB98, -1);
-            testIndexOf(First, s, 0xDE76, -1);
-            testIndexOf(First, s, 0x12345, -1);
-            testIndexOf(First, s, -1, -1);
-            testIndexOf(First, s, 0x110000, -1);
+            testIndexOf(s, 'Z', -1);
+            testIndexOf(s, 0xDB98, -1);
+            testIndexOf(s, 0xDE76, -1);
+            testIndexOf(s, 0x12345, -1);
+            testIndexOf(s, -1, -1);
+            testIndexOf(s, 0x110000, -1);
         }
     }
 
@@ -229,7 +229,7 @@
              */
             int fromIndex = 0;
             for (int j = 2; j < golden3[i].length; j++) {
-                fromIndex = testIndexOf(First, s, fromIndex, ch,
+                fromIndex = testIndexOf(s, fromIndex, ch,
                                         golden3[i][j]) + 1;
             }
 
@@ -237,19 +237,19 @@
              * Abnormal case1 - char is included in the string but fromIndex
              *                  is incorrect.
              */
-            testIndexOf(First, s, -1, ch, golden3[i][2]);
-            testIndexOf(First, s, s.length(), ch,
+            testIndexOf(s, -1, ch, golden3[i][2]);
+            testIndexOf(s, s.length(), ch,
                         golden3[i][golden3[i].length-1]);
 
             /*
              * Abnormal case2 - char which isn't included in the string.
              */
-            testIndexOf(First, s, 0, 'Z', -1);
-            testIndexOf(First, s, 0, 0xDB98, -1);
-            testIndexOf(First, s, 0, 0xDE76, -1);
-            testIndexOf(First, s, 0, 0x12345, -1);
-            testIndexOf(First, s, 0, -1, -1);
-            testIndexOf(First, s, 0, 0x110000, -1);
+            testIndexOf(s, 0, 'Z', -1);
+            testIndexOf(s, 0, 0xDB98, -1);
+            testIndexOf(s, 0, 0xDE76, -1);
+            testIndexOf(s, 0, 0x12345, -1);
+            testIndexOf(s, 0, -1, -1);
+            testIndexOf(s, 0, 0x110000, -1);
         }
     }
 
@@ -264,18 +264,18 @@
             /*
              * Normal case
              */
-            testIndexOf(Last, s, golden3[i][0],
+            testLastIndexOf(s, golden3[i][0],
                         golden3[i][golden3[i].length-2]);
 
             /*
              * Abnormal case - char which isn't included in the string.
              */
-            testIndexOf(Last, s, 'Z', -1);
-            testIndexOf(Last, s, 0xDB98, -1);
-            testIndexOf(Last, s, 0xDE76, -1);
-            testIndexOf(Last, s, 0x12345, -1);
-            testIndexOf(Last, s, -1, -1);
-            testIndexOf(Last, s, 0x110000, -1);
+            testLastIndexOf(s, 'Z', -1);
+            testLastIndexOf(s, 0xDB98, -1);
+            testLastIndexOf(s, 0xDE76, -1);
+            testLastIndexOf(s, 0x12345, -1);
+            testLastIndexOf(s, -1, -1);
+            testLastIndexOf(s, 0x110000, -1);
         }
     }
 
@@ -294,7 +294,7 @@
              */
             int fromIndex = len - 1;
             for (int j = golden3[i].length - 2; j > 0; j--) {
-                fromIndex = testIndexOf(Last, s, fromIndex, ch,
+                fromIndex = testLastIndexOf(s, fromIndex, ch,
                                         golden3[i][j]) - 1;
             }
 
@@ -302,18 +302,18 @@
              * Abnormal case1 - char is included in the string but fromIndex
              *                  is incorrect.
              */
-            testIndexOf(Last, s, -1, ch, golden3[i][1]);
-            testIndexOf(Last, s, len, ch, golden3[i][golden3[i].length-2]);
+            testLastIndexOf(s, -1, ch, golden3[i][1]);
+            testLastIndexOf(s, len, ch, golden3[i][golden3[i].length-2]);
 
             /*
              * Abnormal case2 - char which isn't included in the string.
              */
-            testIndexOf(Last, s, len, 'Z', -1);
-            testIndexOf(Last, s, len, 0xDB98, -1);
-            testIndexOf(Last, s, len, 0xDE76, -1);
-            testIndexOf(Last, s, len, 0x12345, -1);
-            testIndexOf(Last, s, len, -1, -1);
-            testIndexOf(Last, s, len, 0x110000, -1);
+            testLastIndexOf(s, len, 'Z', -1);
+            testLastIndexOf(s, len, 0xDB98, -1);
+            testLastIndexOf(s, len, 0xDE76, -1);
+            testLastIndexOf(s, len, 0x12345, -1);
+            testLastIndexOf(s, len, -1, -1);
+            testLastIndexOf(s, len, 0x110000, -1);
         }
     }
 
@@ -471,7 +471,7 @@
                       result, expected);
                 result = str.offsetByCodePoints(j, -nCodePoints);
                 check(result != 0,
-                      "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+                      "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
                       result, 0);
             }
 
@@ -531,7 +531,7 @@
                       result, expected);
                 result = str.offsetByCodePoints(j, -nCodePoints);
                 check(result != 0,
-                      "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
+                      "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")",
                       result, 0);
             }
         }
@@ -539,7 +539,7 @@
 
 
     static final boolean At = true, Before = false;
-    static final boolean First = true, Last = false;
+    static final boolean FIRST = true, LAST = false;
 
     static void testCodePoint(boolean isAt, String s, int index, int expected) {
         int c = isAt ? s.codePointAt(index) : s.codePointBefore(index);
@@ -563,22 +563,72 @@
               + s + "> should throw StringIndexOutOfBoundsPointerException.");
     }
 
-    static void testIndexOf(boolean isFirst, String s, int c, int expected) {
-        int index = isFirst ? s.indexOf(c) : s.lastIndexOf(c);
+    static void testIndexOf(String s, int c, int expected) {
+        testIndexOf2(s, c, expected);
+        if (s.indexOf(c) != -1) {
+            testIndexOf2(s + (char) c, c, expected);
+            if (Character.isSupplementaryCodePoint(c)) {
+                char[] surrogates = Character.toChars(c);
+                testIndexOf2(s + new String(surrogates), c, expected);
+                testIndexOf2(s + surrogates[0], c, expected);
+                testIndexOf2(s + surrogates[1], c, expected);
+                testIndexOf2(new String(surrogates) + s, c, 0);
+                testIndexOf2(surrogates[0] + s, c, expected + 1);
+                testIndexOf2(surrogates[1] + s, c, expected + 1);
+            }
+        }
+    }
+
+    static void testIndexOf2(String s, int c, int expected) {
+        int index = s.indexOf(c);
 
         check(index != expected,
-              (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c)
-              + ") for <" + s + ">", index, expected);
+              "indexOf(" + toHexString(c) + ") for <" + s + ">",
+              index, expected);
     }
 
-    static int testIndexOf(boolean isFirst, String s, int fromIndex, int c,
-                           int expected) {
-        int index = isFirst ? s.indexOf(c, fromIndex) :
-                              s.lastIndexOf(c, fromIndex);
+    static void testLastIndexOf(String s, int c, int expected) {
+        testLastIndexOf2(s, c, expected);
+        if (s.lastIndexOf(c) != -1) {
+            testLastIndexOf2((char) c + s, c, expected + 1);
+            if (Character.isSupplementaryCodePoint(c)) {
+                char[] surrogates = Character.toChars(c);
+                testLastIndexOf2(s + new String(surrogates), c, s.length());
+                testLastIndexOf2(s + surrogates[0], c, expected);
+                testLastIndexOf2(s + surrogates[1], c, expected);
+                testLastIndexOf2(new String(surrogates) + s, c, expected + 2);
+                testLastIndexOf2(surrogates[0] + s, c, expected + 1);
+                testLastIndexOf2(surrogates[1] + s, c, expected + 1);
+            }
+        }
+    }
+
+    static void testLastIndexOf2(String s, int c, int expected) {
+        int index = s.lastIndexOf(c);
 
         check(index != expected,
-              (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c) + ", "
-              + fromIndex + ") for <" + s + ">", index, expected);
+              "lastIndexOf(" + toHexString(c) + ") for <" + s + ">",
+              index, expected);
+    }
+
+    static int testIndexOf(String s, int fromIndex, int c, int expected) {
+        int index = s.indexOf(c, fromIndex);
+
+        check(index != expected,
+              "indexOf(" + toHexString(c) + ", "
+              + fromIndex + ") for <" + s + ">",
+              index, expected);
+
+        return index;
+    }
+
+    static int testLastIndexOf(String s, int fromIndex, int c, int expected) {
+        int index = s.lastIndexOf(c, fromIndex);
+
+        check(index != expected,
+              "lastIndexOf(" + toHexString(c) + ", "
+              + fromIndex + ") for <" + s + ">",
+              index, expected);
 
         return index;
     }
--- a/jdk/test/java/lang/StringBuffer/Supplementary.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/lang/StringBuffer/Supplementary.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,7 +24,7 @@
 /*
  *
  * @test
- * @bug 4533872 4915683 4985217 5017280
+ * @bug 4533872 4915683 4985217 5017280 6937112
  * @summary Unit tests for supplementary character support (JSR-204)
  */
 
@@ -57,7 +57,7 @@
          0     1     2345     678     9     012     345678     9 01     2     */
         "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
 
-        // includes an undefined supprementary characters in Unicode 4.0.0
+        // includes an undefined supplementary character in Unicode 4.0.0
       /*                                    1     11     1     1111     1
          0     1     2345     6     789     0     12     3     4567     8     */
         "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
@@ -151,7 +151,7 @@
         "\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00",
         "\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00",
 
-        // includes an undefined supprementary characters in Unicode 4.0.0
+        // includes an undefined supplementary character in Unicode 4.0.0
         "\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00",
     };
 
--- a/jdk/test/java/lang/StringBuilder/Supplementary.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/lang/StringBuilder/Supplementary.java	Wed Jul 05 17:17:57 2017 +0200
@@ -57,7 +57,7 @@
          0     1     2345     678     9     012     345678     9 01     2     */
         "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00",
 
-        // includes an undefined supprementary characters in Unicode 4.0.0
+        // includes an undefined supplementary character in Unicode 4.0.0
       /*                                    1     11     1     1111     1
          0     1     2345     6     789     0     12     3     4567     8     */
         "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02",
@@ -151,7 +151,7 @@
         "\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00",
         "\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00",
 
-        // includes an undefined supprementary characters in Unicode 4.0.0
+        // includes an undefined supplementary character in Unicode 4.0.0
         "\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00",
     };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Throwable/SuppressedExceptions.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2010, 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.util.*;
+
+/*
+ * @test
+ * @bug     6911258 6962571
+ * @summary Basic tests of suppressed exceptions
+ * @author  Joseph D. Darcy
+ */
+
+public class SuppressedExceptions {
+    private static String message = "Bad suppressed exception information";
+
+    public static void main(String... args) throws Exception {
+        basicSupressionTest();
+        serializationTest();
+        selfReference();
+    }
+
+    private static void basicSupressionTest() {
+        Throwable throwable = new Throwable();
+        RuntimeException suppressed = new RuntimeException("A suppressed exception.");
+        AssertionError repressed  = new AssertionError("A repressed error.");
+
+        Throwable[] t0 = throwable.getSuppressedExceptions();
+        if (t0.length != 0) {
+            throw new RuntimeException(message);
+        }
+        throwable.printStackTrace();
+
+        throwable.addSuppressedException(suppressed);
+        Throwable[] t1 = throwable.getSuppressedExceptions();
+        if (t1.length != 1 ||
+            t1[0] != suppressed) {throw new RuntimeException(message);
+        }
+        throwable.printStackTrace();
+
+        throwable.addSuppressedException(repressed);
+        Throwable[] t2 = throwable.getSuppressedExceptions();
+        if (t2.length != 2 ||
+            t2[0] != suppressed ||
+            t2[1] != repressed) {
+            throw new RuntimeException(message);
+        }
+        throwable.printStackTrace();
+    }
+
+    private static void serializationTest() throws Exception {
+        /*
+         * Bytes of the serial form of
+         *
+         * (new Throwable())setStackTrace(new StackTraceElement[0])
+         *
+         * from JDK 6; suppressedException field will be missing and
+         * thus default to null upon deserialization.
+         */
+        byte[] bytes = {
+            (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
+            (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+            (byte)0x67, (byte)0x2e, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61,
+            (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0xd5, (byte)0xc6, (byte)0x35, (byte)0x27, (byte)0x39,
+            (byte)0x77, (byte)0xb8, (byte)0xcb, (byte)0x03, (byte)0x00, (byte)0x03, (byte)0x4c, (byte)0x00,
+            (byte)0x05, (byte)0x63, (byte)0x61, (byte)0x75, (byte)0x73, (byte)0x65, (byte)0x74, (byte)0x00,
+            (byte)0x15, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+            (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f,
+            (byte)0x77, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x3b, (byte)0x4c, (byte)0x00,
+            (byte)0x0d, (byte)0x64, (byte)0x65, (byte)0x74, (byte)0x61, (byte)0x69, (byte)0x6c, (byte)0x4d,
+            (byte)0x65, (byte)0x73, (byte)0x73, (byte)0x61, (byte)0x67, (byte)0x65, (byte)0x74, (byte)0x00,
+            (byte)0x12, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+            (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69,
+            (byte)0x6e, (byte)0x67, (byte)0x3b, (byte)0x5b, (byte)0x00, (byte)0x0a, (byte)0x73, (byte)0x74,
+            (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65,
+            (byte)0x74, (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76,
+            (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53,
+            (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63,
+            (byte)0x65, (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74,
+            (byte)0x3b, (byte)0x78, (byte)0x70, (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x04,
+            (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a,
+            (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+            (byte)0x2e, (byte)0x53, (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72,
+            (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65,
+            (byte)0x6e, (byte)0x74, (byte)0x3b, (byte)0x02, (byte)0x46, (byte)0x2a, (byte)0x3c, (byte)0x3c,
+            (byte)0xfd, (byte)0x22, (byte)0x39, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+            (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0xac, (byte)0xed, (byte)0x00,
+            (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x6a, (byte)0x61, (byte)0x76,
+            (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x54,
+            (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65,
+            (byte)0xd5, (byte)0xc6, (byte)0x35, (byte)0x27, (byte)0x39, (byte)0x77, (byte)0xb8, (byte)0xcb,
+            (byte)0x03, (byte)0x00, (byte)0x03, (byte)0x4c, (byte)0x00, (byte)0x05, (byte)0x63, (byte)0x61,
+            (byte)0x75, (byte)0x73, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x15, (byte)0x4c, (byte)0x6a,
+            (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+            (byte)0x2f, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, (byte)0x62,
+            (byte)0x6c, (byte)0x65, (byte)0x3b, (byte)0x4c, (byte)0x00, (byte)0x0d, (byte)0x64, (byte)0x65,
+            (byte)0x74, (byte)0x61, (byte)0x69, (byte)0x6c, (byte)0x4d, (byte)0x65, (byte)0x73, (byte)0x73,
+            (byte)0x61, (byte)0x67, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x12, (byte)0x4c, (byte)0x6a,
+            (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x6e, (byte)0x67, (byte)0x3b,
+            (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69,
+            (byte)0x5b, (byte)0x00, (byte)0x0a, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b,
+            (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x1e,
+            (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+            (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x61, (byte)0x63,
+            (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x45, (byte)0x6c,
+            (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x3b, (byte)0x78, (byte)0x70,
+            (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x04, (byte)0x70, (byte)0x75, (byte)0x72,
+            (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
+            (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53, (byte)0x74,
+            (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65,
+            (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x3b,
+            (byte)0x02, (byte)0x46, (byte)0x2a, (byte)0x3c, (byte)0x3c, (byte)0xfd, (byte)0x22, (byte)0x39,
+            (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+        };
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        ObjectInputStream ois = new ObjectInputStream(bais);
+
+        Object o = ois.readObject();
+        Throwable throwable = (Throwable) o;
+
+        System.err.println("TESTING SERIALIZED EXCEPTION");
+
+        Throwable[] t0 = throwable.getSuppressedExceptions();
+        if (t0.length != 0) { // Will fail if t0 is null.
+            throw new RuntimeException(message);
+        }
+        throwable.printStackTrace();
+    }
+
+    private static void selfReference() {
+        Throwable throwable1 = new RuntimeException();
+        Throwable throwable2 = new AssertionError();
+        throwable1.initCause(throwable2);
+        throwable2.initCause(throwable1);
+
+        throwable1.printStackTrace();
+
+
+        throwable1.addSuppressedException(throwable1);
+        throwable1.addSuppressedException(throwable2);
+
+        throwable1.printStackTrace();
+    }
+}
--- a/jdk/test/java/net/Authenticator/B4769350.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/net/Authenticator/B4769350.java	Wed Jul 05 17:17:57 2017 +0200
@@ -54,6 +54,7 @@
         boolean allowerror;
 
         Client (String authority, String path, boolean allowerror) {
+            super("Thread-" + path);
             this.authority = authority;
             this.path = path;
             this.allowerror = allowerror;
@@ -72,7 +73,8 @@
                 error = true;
             } catch (IOException e) {
                 if (!allowerror) {
-                    System.out.println (e);
+                    System.out.println (Thread.currentThread().getName() + " " + e);
+                    e.printStackTrace();
                     error = true;
                 }
             }
@@ -94,6 +96,7 @@
         }
 
         void okReply (HttpTransaction req) throws IOException {
+            req.addResponseHeader ("Connection", "close");
             req.setResponseEntityBody ("Hello .");
             req.sendResponse (200, "Ok");
             req.orderlyClose();
--- a/jdk/test/java/net/BindException/Test.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/net/BindException/Test.java	Wed Jul 05 17:17:57 2017 +0200
@@ -180,7 +180,7 @@
             while (addrs.hasMoreElements()) {
                 InetAddress ia = (InetAddress)addrs.nextElement();
 
-                if (ia.isLoopbackAddress()) {
+                if (ia.isLoopbackAddress() || ia.isAnyLocalAddress()) {
                     continue;
                 }
 
--- a/jdk/test/java/net/Inet6Address/B6214234.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/net/Inet6Address/B6214234.java	Wed Jul 05 17:17:57 2017 +0200
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 6214234
+ * @bug 6214234 6967937
  * @summary IPv6 scope_id for local addresses not set in Solaris 10
  */
 
@@ -51,6 +51,7 @@
             return;
         }
         if (addr.getScopeId() == 0) {
+            System.out.println("addr: "+ addr);
             throw new RuntimeException ("Non zero scope_id expected");
         }
     }
--- a/jdk/test/java/net/ipv6tests/Tests.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/net/ipv6tests/Tests.java	Wed Jul 05 17:17:57 2017 +0200
@@ -248,7 +248,8 @@
                 }
                 while (addrs.hasMoreElements()) {
                     InetAddress addr = (InetAddress) addrs.nextElement();
-                    if (filter.isInstance (addr) && !addr.isLoopbackAddress()) {
+                    if (filter.isInstance (addr) && !addr.isLoopbackAddress()
+                            && !addr.isAnyLocalAddress()) {
                         if (Arrays.equals (addr.getAddress(), fe80_loopback)) {
                             continue;
                         }
--- a/jdk/test/java/nio/BufferPoolMXBean/Basic.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/BufferPoolMXBean/Basic.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 6606598
  * @summary Unit test for java.nio.BufferPoolMXBean
+ * @run main/othervm Basic
  */
 
 import java.nio.ByteBuffer;
--- a/jdk/test/java/nio/MappedByteBuffer/Basic.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/Basic.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 4462336
  * @summary Simple MappedByteBuffer tests
+ * @run main/othervm Basic
  */
 
 import java.io.*;
--- a/jdk/test/java/nio/MappedByteBuffer/Force.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/Force.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 4625907
  * @summary Testing force()
+ * @run main/othervm Force
  */
 
 import java.io.*;
--- a/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 4802340
  * @summary Testing force(), load() isLoaded() of zero len MBB
+ * @run main/othervm ZeroMap
  */
 
 import java.io.*;
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java	Wed Jul 05 17:17:57 2017 +0200
@@ -29,6 +29,7 @@
 import java.nio.ByteBuffer;
 import java.nio.channels.*;
 import java.net.*;
+import java.util.*;
 import java.util.concurrent.*;
 import java.io.IOException;
 
@@ -44,8 +45,12 @@
         final AsynchronousServerSocketChannel listener =
             AsynchronousServerSocketChannel.open()
                 .bind(new InetSocketAddress(0));
+        final List<AsynchronousSocketChannel> accepted = new ArrayList<AsynchronousSocketChannel>();
         listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
             public void completed(AsynchronousSocketChannel ch, Void att) {
+                synchronized (accepted) {
+                    accepted.add(ch);
+                }
                 listener.accept((Void)null, this);
             }
             public void failed(Throwable exc, Void att) {
@@ -58,6 +63,14 @@
         test(sa, true, false);
         test(sa, false, true);
         test(sa, true, true);
+
+        // clean-up
+        listener.close();
+        synchronized (accepted) {
+            for (AsynchronousSocketChannel ch: accepted) {
+                ch.close();
+            }
+        }
     }
 
     static void test(SocketAddress sa,
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java	Wed Jul 05 17:17:57 2017 +0200
@@ -32,6 +32,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
+import java.io.IOException;
 
 /**
  * Tests that the completion handler is invoked by a thread with
@@ -81,14 +82,18 @@
         listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
             public void completed(final AsynchronousSocketChannel ch, Void att) {
                 listener.accept((Void)null, this);
-
                 final ByteBuffer buf = ByteBuffer.allocate(100);
-                ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() {
-                    public void completed(Integer bytesRead, Void att) {
-                        buf.clear();
-                        ch.read(buf, (Void)null, this);
+                ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
+                    public void completed(Integer bytesRead, AsynchronousSocketChannel ch) {
+                        if (bytesRead < 0) {
+                            try { ch.close(); } catch (IOException ignore) { }
+                        } else {
+                            buf.clear();
+                            ch.read(buf, ch, this);
+                        }
                     }
-                    public void failed(Throwable exc, Void att) {
+                    public void failed(Throwable exc, AsynchronousSocketChannel ch) {
+                        try { ch.close(); } catch (IOException ignore) { }
                     }
                 });
             }
@@ -100,7 +105,8 @@
 
         // create 3-10 channels, each in its own group
         final int groupCount = 3 + rand.nextInt(8);
-        final AsynchronousSocketChannel[] channel = new AsynchronousSocketChannel[groupCount];
+        AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount];
+        final AsynchronousSocketChannel[] channels = new AsynchronousSocketChannel[groupCount];
         for (int i=0; i<groupCount; i++) {
             ThreadFactory factory = createThreadFactory(i);
             AsynchronousChannelGroup group;
@@ -111,17 +117,18 @@
                 ExecutorService pool = Executors.newCachedThreadPool(factory);
                 group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
             }
+            groups[i] = group;
 
             // create channel in group and connect it to the server
             AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
             ch.connect(sa).get();
-            channel[i] = ch;
+            channels[i] = ch;
         }
 
         // randomly write to each channel, ensuring that the completion handler
         // is always invoked by a thread with the right identity.
         final AtomicInteger writeCount = new AtomicInteger(100);
-        channel[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
+        channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() {
             public void completed(Integer bytesWritten, Integer groupId) {
                 if (bytesWritten != 1)
                     fail("Expected 1 byte to be written");
@@ -129,7 +136,7 @@
                     fail("Handler invoked by thread with the wrong identity");
                 if (writeCount.decrementAndGet() > 0) {
                     int id = rand.nextInt(groupCount);
-                    channel[id].write(getBuffer(), id, this);
+                    channels[id].write(getBuffer(), id, this);
                 } else {
                     done.countDown();
                 }
@@ -139,8 +146,16 @@
             }
         });
 
-        // wait until
+        // wait until done
         done.await();
+
+        // clean-up
+        for (AsynchronousSocketChannel ch: channels)
+            ch.close();
+        for (AsynchronousChannelGroup group: groups)
+            group.shutdownNow();
+        listener.close();
+
         if (failed.get())
             throw new RuntimeException("Test failed - see log for details");
     }
--- a/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java	Wed Jul 05 17:17:57 2017 +0200
@@ -371,17 +371,22 @@
     static void doMulticastTests() throws Exception {
         final byte[] msg = "hello".getBytes();
 
+        InetAddress lh = InetAddress.getLocalHost();
+        NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
+        if (interf.isLoopback() || !interf.supportsMulticast()) {
+            System.out.println("Multicasting not tested");
+            return;
+        }
+
         AsynchronousDatagramChannel ch = AsynchronousDatagramChannel
             .open(StandardProtocolFamily.INET, null)
             .setOption(StandardSocketOption.SO_REUSEADDR, true)
             .bind(new InetSocketAddress(0));
 
-        InetAddress lh = InetAddress.getLocalHost();
         int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
 
         // join group
         InetAddress group = InetAddress.getByName("225.4.5.6");
-        NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
         MembershipKey key = ch.join(group, interf);
 
         // check key
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java	Wed Jul 05 17:17:57 2017 +0200
@@ -45,16 +45,18 @@
         File blah = File.createTempFile("blah", null);
         blah.deleteOnExit();
 
-        final AsynchronousFileChannel ch = AsynchronousFileChannel
+        AsynchronousFileChannel ch = AsynchronousFileChannel
             .open(blah.toPath(), READ, WRITE);
+        try {
+            // run tests
+            testUsingCompletionHandlers(ch);
+            testUsingWaitOnResult(ch);
+            testInterruptHandlerThread(ch);
+        } finally {
+            ch.close();
+        }
 
-        // run tests
-        testUsingCompletionHandlers(ch);
-        testUsingWaitOnResult(ch);
-        testInterruptHandlerThread(ch);
-
-        // close channel and invoke test that expects channel to be closed
-        ch.close();
+        // run test that expects channel to be closed
         testClosedChannel(ch);
 
         // these tests open the file themselves
@@ -63,6 +65,9 @@
         testAsynchronousClose(blah.toPath());
         testCancel(blah.toPath());
         testTruncate(blah.toPath());
+
+        // eagerly clean-up
+        blah.delete();
     }
 
     /*
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java	Wed Jul 05 17:17:57 2017 +0200
@@ -53,13 +53,17 @@
         LockSlaveMirror slave = startLockSlave();
         try {
 
-             // create temporary file
+            // create temporary file
             File blah = File.createTempFile("blah", null);
             blah.deleteOnExit();
 
+            // run tests
             testLockProtocol(blah, slave);
             testAsyncClose(blah, slave);
 
+            // eagerly clean-up
+            blah.delete();
+
         } finally {
             slave.shutdown();
         }
@@ -150,7 +154,12 @@
         String sep = FileSystems.getDefault().getSeparator();
 
         String command = System.getProperty("java.home") +
-            sep + "bin" + sep + "java Lock -lockslave " + port;
+            sep + "bin" + sep + "java";
+        String testClasses = System.getProperty("test.classes");
+        if (testClasses != null)
+            command += " -cp " + testClasses;
+        command += " Lock -lockslave " + port;
+
         Process p = Runtime.getRuntime().exec(command);
         IOHandler.handle(p.getInputStream());
         IOHandler.handle(p.getErrorStream());
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java	Wed Jul 05 17:17:57 2017 +0200
@@ -135,6 +135,7 @@
         latch.await();
 
         // verify content of each file
+        boolean failed = false;
         byte[] buf = new byte[8192];
         for (int i=0; i<count ;i++) {
             Writer writer = writers[i];
@@ -145,18 +146,35 @@
                 int nread = in.read(buf);
                 while (nread > 0) {
                     for (int j=0; j<nread; j++) {
-                        if (buf[j] != expected)
-                            throw new RuntimeException("Unexpected byte");
+                        if (buf[j] != expected) {
+                            System.err.println("Unexpected contents");
+                            failed = true;
+                            break;
+                        }
                         expected++;
                     }
+                    if (failed)
+                        break;
                     size += nread;
                     nread = in.read(buf);
                 }
-                if (size != writer.size())
-                    throw new RuntimeException("Unexpected size");
+                if (!failed && size != writer.size()) {
+                    System.err.println("Unexpected size");
+                    failed = true;
+                }
+                if (failed)
+                    break;
             } finally {
                 in.close();
             }
         }
+
+        // clean-up
+        for (int i=0; i<count; i++) {
+            writers[i].file().delete();
+        }
+
+        if (failed)
+            throw new RuntimeException("Test failed");
     }
 }
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Wed Jul 05 17:17:57 2017 +0200
@@ -776,6 +776,7 @@
             throw new RuntimeException("RuntimeException expected after timeout.");
 
         ch.close();
+        server.close();
     }
 
     // returns ByteBuffer with random bytes
--- a/jdk/test/java/nio/channels/Channels/Basic2.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Channels/Basic2.java	Wed Jul 05 17:17:57 2017 +0200
@@ -61,6 +61,9 @@
         writerThread.join();
         readerThread.join();
 
+        // shutdown listener
+        listener.close();
+
         // check that reader received what we expected
         if (reader.total() != writer.total())
             throw new RuntimeException("Unexpected number of bytes read");
--- a/jdk/test/java/nio/channels/Channels/Write.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Channels/Write.java	Wed Jul 05 17:17:57 2017 +0200
@@ -47,5 +47,6 @@
         out.close();
         fc.close();
         fos.close();
+        testFile.delete();
     }
 }
--- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java	Wed Jul 05 17:17:57 2017 +0200
@@ -82,8 +82,6 @@
                 }
                 throw x;
             }
-            if (shouldTimeout)
-                throw new Exception("Receive did not time out");
             break;
         }
 
--- a/jdk/test/java/nio/channels/DatagramChannel/EmptyBuffer.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/EmptyBuffer.java	Wed Jul 05 17:17:57 2017 +0200
@@ -46,21 +46,25 @@
         Thread serverThread = new Thread(server);
         serverThread.start();
         DatagramChannel dc = DatagramChannel.open();
-        ByteBuffer bb = ByteBuffer.allocateDirect(12);
-        bb.order(ByteOrder.BIG_ENDIAN);
-        bb.putInt(1).putLong(1);
-        bb.flip();
-        InetAddress address = InetAddress.getLocalHost();
-        InetSocketAddress isa = new InetSocketAddress(address, server.port());
-        dc.connect(isa);
-        dc.write(bb);
-        bb.rewind();
-        dc.write(bb);
-        bb.rewind();
-        dc.write(bb);
-        Thread.sleep(2000);
-        serverThread.interrupt();
-        server.throwException();
+        try {
+            ByteBuffer bb = ByteBuffer.allocateDirect(12);
+            bb.order(ByteOrder.BIG_ENDIAN);
+            bb.putInt(1).putLong(1);
+            bb.flip();
+            InetAddress address = InetAddress.getLocalHost();
+            InetSocketAddress isa = new InetSocketAddress(address, server.port());
+            dc.connect(isa);
+            dc.write(bb);
+            bb.rewind();
+            dc.write(bb);
+            bb.rewind();
+            dc.write(bb);
+            Thread.sleep(2000);
+            serverThread.interrupt();
+            server.throwException();
+        } finally {
+            dc.close();
+        }
     }
 
     public static class Server implements Runnable {
@@ -118,6 +122,8 @@
                 }
             } catch (Exception ex) {
                 e = ex;
+            } finally {
+                try { dc.close(); } catch (IOException ignore) { }
             }
         }
     }
--- a/jdk/test/java/nio/channels/DatagramChannel/ReceiveISA.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/ReceiveISA.java	Wed Jul 05 17:17:57 2017 +0200
@@ -66,6 +66,10 @@
             rb.clear();
         }
 
+        dc1.close();
+        dc2.close();
+        dc3.close();
+
         /*
          * Check that sa[0] equals sa[1] (both from dc1)
          * Check that sa[1] not equal to sa[2] (one from dc1, one from dc2)
--- a/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java	Wed Jul 05 17:17:57 2017 +0200
@@ -43,9 +43,9 @@
         SocketAddress refuser = new InetSocketAddress(InetAddress.getLocalHost(), port);
 
         dc = DatagramChannel.open().bind(new InetSocketAddress(0));
+        Selector sel = Selector.open();
         try {
             dc.configureBlocking(false);
-            Selector sel = Selector.open();
             dc.register(sel, SelectionKey.OP_READ);
 
             /* Test 1: not connected so ICMP port unreachable should not be received */
@@ -81,6 +81,7 @@
             }
 
         } finally {
+            sel.close();
             dc.close();
         }
     }
--- a/jdk/test/java/nio/channels/FileChannel/Args.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Args.java	Wed Jul 05 17:17:57 2017 +0200
@@ -97,6 +97,8 @@
                            (long)Integer.MAX_VALUE << 3);
                 }});
 
+        fc.close();
+        f.delete();
     }
 
 }
--- a/jdk/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java	Wed Jul 05 17:17:57 2017 +0200
@@ -38,6 +38,7 @@
         test1(channel);
         test2(channel);
         channel.close();
+        file.delete();
     }
 
     static void test1(FileChannel channel) throws Exception {
--- a/jdk/test/java/nio/channels/FileChannel/ExpandingMap.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ExpandingMap.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,6 +25,7 @@
  * @bug 4938372 6541641
  * @summary Flushing dirty pages prior to unmap can cause Cleaner thread to
  *          abort VM if memory system has pages locked
+ * @run main/othervm ExpandingMap
  */
 import java.io.File;
 import java.io.RandomAccessFile;
--- a/jdk/test/java/nio/channels/FileChannel/Lock.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Lock.java	Wed Jul 05 17:17:57 2017 +0200
@@ -55,6 +55,7 @@
         test2(blah, true);
         test2(blah, false);
         test3(blah);
+        blah.delete();
     }
 
     private static void test2(File blah, boolean b) throws Exception {
@@ -90,7 +91,11 @@
 
         // Exec the tamperer
         String command = System.getProperty("java.home") +
-            File.separator + "bin" + File.separator + "java Lock " + str + " " + blah;
+            File.separator + "bin" + File.separator + "java";
+        String testClasses = System.getProperty("test.classes");
+        if (testClasses != null)
+            command += " -cp " + testClasses;
+        command += " Lock " + str + " " + blah;
         Process p = Runtime.getRuntime().exec(command);
 
         BufferedReader in = new BufferedReader
--- a/jdk/test/java/nio/channels/FileChannel/MapOverEnd.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapOverEnd.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 4463036
  * @summary Check if file mapping extends beyond end of file
+ * @run main/othervm MapOverEnd
  */
 
 import java.nio.*;
--- a/jdk/test/java/nio/channels/FileChannel/MapReadOnly.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapReadOnly.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 4510489
  * @summary Verify IOUtil.java reads to buffer limits
+ * @run main/othervm MapReadOnly
  */
 import java.io.*;
 import java.nio.*;
--- a/jdk/test/java/nio/channels/FileChannel/MapTest.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapTest.java	Wed Jul 05 17:17:57 2017 +0200
@@ -23,6 +23,7 @@
 
 /* @test
  * @summary Test file mapping with FileChannel
+ * @run main/othervm MapTest
  */
 
 import java.io.*;
--- a/jdk/test/java/nio/channels/FileChannel/Mode.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Mode.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
    @bug 4462298
  * @summary Test FileChannel maps with different accesses
+ * @run main/othervm Mode
  */
 
 import java.nio.channels.*;
--- a/jdk/test/java/nio/channels/FileChannel/Position.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Position.java	Wed Jul 05 17:17:57 2017 +0200
@@ -63,6 +63,7 @@
 
         c.close();
         fis.close();
+        blah.delete();
     }
 
     /**
--- a/jdk/test/java/nio/channels/FileChannel/Pread.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Pread.java	Wed Jul 05 17:17:57 2017 +0200
@@ -65,6 +65,9 @@
             throw new RuntimeException("Expected exception not thrown");
         } catch(IllegalArgumentException e) {
             // Correct result
+        } finally {
+            fc.close();
+            blah.delete();
         }
     }
 
@@ -73,13 +76,18 @@
         File blah = File.createTempFile("blah2", null);
         blah.deleteOnExit();
         FileOutputStream fos = new FileOutputStream(blah);
-        fos.write(new byte[128]);
-        FileChannel fc = fos.getChannel();
         try {
-            fc.read(ByteBuffer.allocate(256),1);
-            throw new RuntimeException("Expected exception not thrown");
-        } catch(NonReadableChannelException e) {
-            // Correct result
+            fos.write(new byte[128]);
+            FileChannel fc = fos.getChannel();
+            try {
+                fc.read(ByteBuffer.allocate(256),1);
+                throw new RuntimeException("Expected exception not thrown");
+            } catch(NonReadableChannelException e) {
+                // Correct result
+            }
+        } finally {
+            fos.close();
+            blah.delete();
         }
     }
 
@@ -130,6 +138,7 @@
 
         c.close();
         fis.close();
+        blah.delete();
     }
 
     /**
--- a/jdk/test/java/nio/channels/FileChannel/Pwrite.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Pwrite.java	Wed Jul 05 17:17:57 2017 +0200
@@ -62,6 +62,9 @@
             throw new RuntimeException("Expected exception not thrown");
         } catch(NonWritableChannelException e) {
             // Correct result
+        } finally {
+            fc.close();
+            blah.delete();
         }
     }
 
@@ -123,6 +126,7 @@
         }
         c.close();
         raf.close();
+        blah.delete();
     }
 
     /**
--- a/jdk/test/java/nio/channels/FileChannel/Read.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Read.java	Wed Jul 05 17:17:57 2017 +0200
@@ -80,6 +80,7 @@
 
         c.close();
         fis.close();
+        blah.delete();
     }
 
     /**
--- a/jdk/test/java/nio/channels/FileChannel/ReadFull.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReadFull.java	Wed Jul 05 17:17:57 2017 +0200
@@ -54,5 +54,6 @@
 
         fc.close();
         fis.close();
+        blah.delete();
     }
 }
--- a/jdk/test/java/nio/channels/FileChannel/ReadToLimit.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReadToLimit.java	Wed Jul 05 17:17:57 2017 +0200
@@ -48,6 +48,7 @@
                 throw new Exception("Test failed");
         fc.close();
         fis.close();
+        blah.delete();
     }
 
     /**
--- a/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java	Wed Jul 05 17:17:57 2017 +0200
@@ -39,8 +39,12 @@
     public static void main(String[] args) throws IOException {
         File blah = File.createTempFile("blah", null);
         blah.deleteOnExit();
-        for (int i=0; i<100; i++) {
-            test(blah.toPath());
+        try {
+            for (int i=0; i<100; i++) {
+                test(blah.toPath());
+            }
+        } finally {
+            blah.delete();
         }
     }
 
--- a/jdk/test/java/nio/channels/FileChannel/ScatteringRead.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ScatteringRead.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
    @bug 4452020 4629048 4638365 4869859
  * @summary Test FileChannel scattering reads
+ * @run main/othervm ScatteringRead
  */
 
 import java.nio.channels.*;
--- a/jdk/test/java/nio/channels/FileChannel/Size.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Size.java	Wed Jul 05 17:17:57 2017 +0200
@@ -24,6 +24,7 @@
 /* @test
  * @bug 4563125
  * @summary Test size method of FileChannel
+ * @run main/othervm Size
  */
 
 import java.io.*;
--- a/jdk/test/java/nio/channels/FileChannel/Transfer.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,7 +25,6 @@
  * @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145
  * @summary Test FileChannel.transferFrom and transferTo
  * @library ..
- * @run main/timeout=180 Transfer
  */
 
 import java.io.*;
@@ -33,6 +32,8 @@
 import java.nio.*;
 import java.nio.channels.*;
 import java.nio.channels.spi.SelectorProvider;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.FileAlreadyExistsException;
 import java.util.Random;
 
 
@@ -96,6 +97,9 @@
 
         sourceChannel.close();
         sinkChannel.close();
+
+        source.delete();
+        sink.delete();
     }
 
     private static void testReadableByteChannel(int size) throws Exception {
@@ -139,6 +143,8 @@
         fc.close();
         sink.close();
         source.close();
+
+        f.delete();
     }
 
     public static void xferTest02() throws Exception {
@@ -173,6 +179,9 @@
         fc2.close();
         raf1.close();
         raf2.close();
+
+        source.delete();
+        dest.delete();
     }
 
     public static void xferTest03() throws Exception {
@@ -207,6 +216,9 @@
         fc2.close();
         raf1.close();
         raf2.close();
+
+        source.delete();
+        dest.delete();
     }
 
     // Test transferTo with large file
@@ -245,27 +257,36 @@
         sourceChannel.close();
         sinkChannel.close();
 
+        source.delete();
+        sink.delete();
     }
 
     // Test transferFrom with large file
     public static void xferTest05() throws Exception {
-        // Linux can't handle the really large file sizes for a
-        // truncate or a positional write
-        String osName = System.getProperty("os.name");
-        if (osName.startsWith("Linux"))
-            return;
-
         // Create a source file & large sink file for the test
         File source = File.createTempFile("blech", null);
         source.deleteOnExit();
         initTestFile(source, 100);
 
-        File sink = File.createTempFile("sink", null);
+        // Create the sink file as a sparse file if possible
+        File sink = null;
+        FileChannel fc = null;
+        while (fc == null) {
+            sink = File.createTempFile("sink", null);
+            // re-create as a sparse file
+            sink.toPath().delete();
+            try {
+                fc = FileChannel.open(sink.toPath(),
+                                      StandardOpenOption.CREATE_NEW,
+                                      StandardOpenOption.WRITE,
+                                      StandardOpenOption.SPARSE);
+            } catch (FileAlreadyExistsException ignore) {
+                // someone else got it
+            }
+        }
         sink.deleteOnExit();
 
         long testSize = ((long)Integer.MAX_VALUE) * 2;
-        RandomAccessFile raf = new RandomAccessFile(sink, "rw");
-        FileChannel fc = raf.getChannel();
         try {
             fc.write(ByteBuffer.wrap("Use the source!".getBytes()),
                      testSize - 40);
@@ -275,24 +296,28 @@
             return;
         } finally {
             fc.close();
-            raf.close();
         }
 
         // Get new channels for the source and sink and attempt transfer
-        FileInputStream fis = new FileInputStream(source);
-        FileChannel sourceChannel = fis.getChannel();
-
-        raf = new RandomAccessFile(sink, "rw");
-        FileChannel sinkChannel = raf.getChannel();
+        FileChannel sourceChannel = new FileInputStream(source).getChannel();
+        try {
+            FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel();
+            try {
+                long bytesWritten = sinkChannel.transferFrom(sourceChannel,
+                                                             testSize - 40, 10);
+                if (bytesWritten != 10) {
+                    throw new RuntimeException("Transfer test 5 failed " +
+                                               bytesWritten);
+                }
+            } finally {
+                sinkChannel.close();
+            }
+        } finally {
+            sourceChannel.close();
+        }
 
-        long bytesWritten = sinkChannel.transferFrom(sourceChannel,
-                                                     testSize - 40, 10);
-        if (bytesWritten != 10) {
-            throw new RuntimeException("Transfer test 5 failed " +
-                                       bytesWritten);
-        }
-        sourceChannel.close();
-        sinkChannel.close();
+        source.delete();
+        sink.delete();
     }
 
     static void checkFileData(File file, String expected) throws Exception {
@@ -338,6 +363,8 @@
 
         checkFileData(source, data);
         checkFileData(sink, data.substring(7,data.length()));
+
+        source.delete();
     }
 
     // Test transferTo to non-blocking socket channel
@@ -371,6 +398,7 @@
         sink.close();
         other.close();
         ssc.close();
+        source.delete();
     }
 
 
@@ -473,6 +501,7 @@
             source.close();
             ssc.close();
             fc.close();
+            file.delete();
         }
     }
 
--- a/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java	Wed Jul 05 17:17:57 2017 +0200
@@ -51,6 +51,8 @@
         test1();
         test2();
         in.close();
+        file.delete();
+        outFile.delete();
     }
 
     static void test1() throws Exception {
--- a/jdk/test/java/nio/channels/FileChannel/TransferToNonWritable.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TransferToNonWritable.java	Wed Jul 05 17:17:57 2017 +0200
@@ -43,6 +43,9 @@
             throw new RuntimeException("Test failed");
         } catch (NonWritableChannelException nwce) {
             // Correct result
+        } finally {
+            channel.close();
+            blah.delete();
         }
     }
 }
--- a/jdk/test/java/nio/channels/FileChannel/Transfers.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Transfers.java	Wed Jul 05 17:17:57 2017 +0200
@@ -554,6 +554,10 @@
                 break;
         }
 
+        sourceFile.delete();
+        targetFile.delete();
+        fn.delete();
+
         if (failures > 0) {
             out.println();
             throw new RuntimeException("Some tests failed");
--- a/jdk/test/java/nio/channels/FileChannel/TryLock.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TryLock.java	Wed Jul 05 17:17:57 2017 +0200
@@ -56,7 +56,6 @@
 
     public static void test1(boolean shared, boolean trylock) throws Exception {
         File testFile = File.createTempFile("test1", null);
-        testFile.deleteOnExit();
         FileInputStream fis = new FileInputStream(testFile);
         FileChannel fc = fis.getChannel();
         FileLock fl = null;
@@ -73,12 +72,13 @@
         } finally {
             if (fl != null)
                 fl.release();
+            fc.close();
+            testFile.delete();
         }
     }
 
     public static void test2(boolean shared, boolean trylock) throws Exception {
         File testFile = File.createTempFile("test2", null);
-        testFile.deleteOnExit();
         FileOutputStream fis = new FileOutputStream(testFile);
         FileChannel fc = fis.getChannel();
         FileLock fl = null;
@@ -95,19 +95,25 @@
         } finally {
             if (fl != null)
                 fl.release();
+            fc.close();
+            testFile.delete();
         }
     }
 
     public static void test3(boolean shared, boolean trylock) throws Exception {
         File testFile = File.createTempFile("test3", null);
-        testFile.deleteOnExit();
         RandomAccessFile fis = new RandomAccessFile(testFile, "rw");
         FileChannel fc = fis.getChannel();
-        FileLock fl = null;
-        if (trylock)
-            fl = fc.tryLock(0, fc.size(), shared);
-        else
-            fl = fc.lock(0, fc.size(), shared);
-        fl.release();
+        try {
+            FileLock fl = null;
+            if (trylock)
+                fl = fc.tryLock(0, fc.size(), shared);
+            else
+                fl = fc.lock(0, fc.size(), shared);
+            fl.release();
+        } finally {
+            fc.close();
+            testFile.delete();
+        }
     }
 }
--- a/jdk/test/java/nio/channels/FileChannel/Write.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Write.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,6 +25,7 @@
  * @test
  * @bug 4475533 4698138 4638365 4796221
  * @summary Test FileChannel write
+ * @run main/othervm Write
  */
 
 import java.nio.channels.*;
@@ -46,23 +47,25 @@
 
     // Test to see that offset > length does not throw exception
     static void test1() throws Exception {
-        File testFile = File.createTempFile("test1", null);
-        testFile.deleteOnExit();
-
         ByteBuffer[] dsts = new ByteBuffer[4];
         for (int i=0; i<4; i++)
             dsts[i] = ByteBuffer.allocateDirect(10);
 
-        FileOutputStream fos = new FileOutputStream(testFile);
-        FileChannel fc = fos.getChannel();
-        fc.write(dsts, 2, 1);
-        fos.close();
+        File testFile = File.createTempFile("test1", null);
+        try {
+            FileOutputStream fos = new FileOutputStream(testFile);
+            FileChannel fc = fos.getChannel();
+            fc.write(dsts, 2, 1);
+            fos.close();
+        } finally {
+            testFile.delete();
+        }
     }
 
     // Test to see that the appropriate buffers are updated
     static void test2() throws Exception {
         File testFile = File.createTempFile("test2", null);
-        testFile.deleteOnExit();
+        testFile.delete();
         ByteBuffer[] srcs = new ByteBuffer[4];
         for (int i=0; i<4; i++)
             srcs[i] = ByteBuffer.allocateDirect(10);
@@ -74,25 +77,34 @@
 
         FileOutputStream fos = new FileOutputStream(testFile);
         FileChannel fc = fos.getChannel();
-        fc.write(srcs, 1, 2);
-        fos.close();
+        try {
+            fc.write(srcs, 1, 2);
+        } finally {
+            fc.close();
+        }
 
         FileInputStream fis = new FileInputStream(testFile);
         fc = fis.getChannel();
-        ByteBuffer bb = ByteBuffer.allocateDirect(10);
-        fc.read(bb);
-        bb.flip();
-        if (bb.get() != 2)
-            throw new RuntimeException("Write failure");
-        if (bb.get() != 3)
-            throw new RuntimeException("Write failure");
         try {
-            bb.get();
-            throw new RuntimeException("Write failure");
-        } catch (BufferUnderflowException bufe) {
-            // correct result
+            ByteBuffer bb = ByteBuffer.allocateDirect(10);
+            fc.read(bb);
+            bb.flip();
+            if (bb.get() != 2)
+                throw new RuntimeException("Write failure");
+            if (bb.get() != 3)
+                throw new RuntimeException("Write failure");
+            try {
+                bb.get();
+                throw new RuntimeException("Write failure");
+            } catch (BufferUnderflowException bufe) {
+                // correct result
+            }
+        } finally {
+            fc.close();
         }
-        fis.close();
+
+        // eagerly clean-up
+        testFile.delete();
     }
 
     // Test write to a negative position (bug 4698138).
--- a/jdk/test/java/nio/channels/Pipe/NonBlocking.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Pipe/NonBlocking.java	Wed Jul 05 17:17:57 2017 +0200
@@ -41,12 +41,17 @@
 
     static void test1() throws Exception {
         Pipe p = Pipe.open();
-        p.sink().configureBlocking(false);
-        if (p.sink().isBlocking())
-            throw new Exception("Sink still blocking");
-        p.source().configureBlocking(false);
-        if (p.source().isBlocking())
-            throw new Exception("Source still blocking");
+        try {
+            p.sink().configureBlocking(false);
+            if (p.sink().isBlocking())
+                throw new Exception("Sink still blocking");
+            p.source().configureBlocking(false);
+            if (p.source().isBlocking())
+                throw new Exception("Source still blocking");
+        } finally {
+            p.sink().close();
+            p.source().close();
+        }
     }
 
 }
--- a/jdk/test/java/nio/channels/Pipe/SelectPipe.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Pipe/SelectPipe.java	Wed Jul 05 17:17:57 2017 +0200
@@ -78,10 +78,12 @@
                 totalRead += bytesRead;
         } while(totalRead < 10);
 
+        sink.close();
+        source.close();
+        selector.close();
+
         for(int i=0; i<10; i++)
             if (outgoingdata.get(i) != incomingdata.get(i))
                 throw new Exception("Pipe failed");
-        sink.close();
-        source.close();
     }
 }
--- a/jdk/test/java/nio/channels/SelectionKey/AtomicAttachTest.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SelectionKey/AtomicAttachTest.java	Wed Jul 05 17:17:57 2017 +0200
@@ -58,6 +58,11 @@
         };
 
         t.join();
+
+        pipe.sink().close();
+        pipe.source().close();
+        selector.close();
+
         int count = errorCount.get();
         if (count > 0) {
             throw new RuntimeException("Error count:" + count);
--- a/jdk/test/java/nio/channels/Selector/BasicAccept.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/BasicAccept.java	Wed Jul 05 17:17:57 2017 +0200
@@ -36,49 +36,60 @@
 
 public class BasicAccept {
 
-    public static int TEST_PORT = 40170;
-
-    static void server() throws Exception {
+    static void server(ServerSocketChannel ssc) throws Exception {
         Selector acceptSelector = Selector.open();
-        ServerSocketChannel ssc = ServerSocketChannel.open();
-        ssc.configureBlocking(false);
-        InetAddress lh = InetAddress.getLocalHost();
-        InetSocketAddress isa
-            = new InetSocketAddress(lh, SelectorTest.TEST_PORT);
-        ssc.socket().bind(isa);
-        SelectionKey acceptKey
-            = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
-        for (;;) {
-            if (acceptSelector.select() == 0)
-                continue;
-            Set readyKeys = acceptSelector.selectedKeys();
-            Iterator i = readyKeys.iterator();
-            while (i.hasNext()) {
-                SelectionKey sk = (SelectionKey)i.next();
-                i.remove();
-                ServerSocketChannel nextReady
-                    = (ServerSocketChannel)sk.channel();
-                SocketChannel sc = nextReady.accept();
-                ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 });
-                sc.write(bb);
+        try {
+            ssc.configureBlocking(false);
+            SelectionKey acceptKey
+                = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+            for (;;) {
+                int n = acceptSelector.select();
+                if (Thread.interrupted())
+                    break;
+                if (n == 0)
+                    continue;
+                Set<SelectionKey> readyKeys = acceptSelector.selectedKeys();
+                Iterator<SelectionKey> i = readyKeys.iterator();
+                while (i.hasNext()) {
+                    SelectionKey sk = i.next();
+                    i.remove();
+                    ServerSocketChannel nextReady
+                        = (ServerSocketChannel)sk.channel();
+                    SocketChannel sc = nextReady.accept();
+                    ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 });
+                    sc.write(bb);
+                    sc.close();
+                }
+            }
+        } finally {
+            acceptSelector.close();
+        }
+    }
+
+    private static class Server extends TestThread {
+        final ServerSocketChannel ssc;
+        Server() throws IOException {
+            super("Server", System.err);
+            this.ssc = ServerSocketChannel.open()
+                .bind(new InetSocketAddress(0));
+        }
+        int port() {
+            return ssc.socket().getLocalPort();
+        }
+        void go() throws Exception {
+            try {
+                server(ssc);
+            } finally {
+                ssc.close();
             }
         }
     }
 
-    private static class Server extends TestThread {
-        Server() {
-            super("Server", System.err);
-        }
-        void go() throws Exception {
-            server();
-        }
-    }
-
-    static void client() throws Exception {
+    static void client(int port) throws Exception {
         // Get a connection from the server
         InetAddress lh = InetAddress.getLocalHost();
         InetSocketAddress isa
-            = new InetSocketAddress(lh, SelectorTest.TEST_PORT);
+            = new InetSocketAddress(lh, port);
         int connectFailures = 0;
         boolean result = false;
         SocketChannel sc = SocketChannel.open();
@@ -122,17 +133,17 @@
         if (bb.get(0) != 42)
             throw new RuntimeException("Read wrong byte from server");
         System.err.println("Read from server");
+        sc.close();
     }
 
     public static void main(String[] args) throws Exception {
-        if (args.length == 0) {
-            Server server = new Server();
-            server.start();
-            client();
-        } else if (args[0].equals("client")) {
-            client();
-        } else if (args[0].equals("server")) {
-            server();
+        Server server = new Server();
+        server.start();
+        try {
+            client(server.port());
+        } finally {
+            server.interrupt();
+            server.finish(2000);
         }
     }
 
--- a/jdk/test/java/nio/channels/Selector/BasicConnect.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/BasicConnect.java	Wed Jul 05 17:17:57 2017 +0200
@@ -83,10 +83,13 @@
         ByteBuffer bb2 = ByteBuffer.allocateDirect(100);
         int n = sc.read(bb2);
         bb2.flip();
+
+        sc.close();
+        connectSelector.close();
+
         if (!bb.equals(bb2))
             throw new Exception("Echoed bytes incorrect: Sent "
                                 + bb + ", got " + bb2);
-        sc.close();
     }
 
 }
--- a/jdk/test/java/nio/channels/Selector/CheckLocking.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CheckLocking.java	Wed Jul 05 17:17:57 2017 +0200
@@ -61,5 +61,7 @@
         doSelect();
         sk.interestOps(SelectionKey.OP_READ);
         selector.wakeup();
+        sc.close();
+        selector.close();
     }
 }
--- a/jdk/test/java/nio/channels/Selector/CloseInvalidatesKeys.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CloseInvalidatesKeys.java	Wed Jul 05 17:17:57 2017 +0200
@@ -33,12 +33,16 @@
 
     public static void main (String [] args) throws Exception {
         DatagramChannel ch = DatagramChannel.open();
-        ch.configureBlocking(false);
-        Selector sel = Selector.open();
-        SelectionKey key = ch.register(sel, SelectionKey.OP_WRITE);
-        sel.close();
-        if (key.isValid())
-            throw new Exception("Key valid after selector closed");
+        try {
+            ch.configureBlocking(false);
+            Selector sel = Selector.open();
+            SelectionKey key = ch.register(sel, SelectionKey.OP_WRITE);
+            sel.close();
+            if (key.isValid())
+                throw new Exception("Key valid after selector closed");
+        } finally {
+            ch.close();
+        }
     }
 
 }
--- a/jdk/test/java/nio/channels/Selector/CloseWhenKeyIdle.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CloseWhenKeyIdle.java	Wed Jul 05 17:17:57 2017 +0200
@@ -111,10 +111,14 @@
         // select should block
 
         int spinCount = 0;
+        boolean failed = false;
         for (;;) {
             int n = sel.select();
-            if (n > 0)
-                throw new RuntimeException("channel should not be selected");
+            if (n > 0) {
+                System.err.println("Channel should not be selected!!!");
+                failed = true;
+                break;
+            }
 
             // wakeup
             if (wakeupDone)
@@ -123,10 +127,19 @@
             // wakeup for no reason - if it happens a few times then we have a
             // problem
             spinCount++;
-            if (spinCount >= 3)
-                throw new RuntimeException("Selector appears to be spinning");
+            if (spinCount >= 3) {
+                System.err.println("Selector appears to be spinning");
+                failed = true;
+                break;
+            }
         }
 
+        sc1.close();
+        sel.close();
+
+        if (failed)
+            throw new RuntimeException("Test failed");
+
         System.out.println("PASS");
     }
 
--- a/jdk/test/java/nio/channels/Selector/Connect.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/Connect.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,7 +25,6 @@
  * @bug 4511624
  * @summary Test Making lots of Selectors
  * @library ..
- * @run main/timeout=240 Connect
  */
 
 import java.io.*;
@@ -38,7 +37,7 @@
 public class Connect {
 
     static int success = 0;
-    static int LIMIT = 500;
+    static int LIMIT = 100;
 
     public static void main(String[] args) throws Exception {
         scaleTest();
@@ -51,29 +50,30 @@
         for (int j=0; j<LIMIT; j++) {
             SocketChannel sc = SocketChannel.open();
             sc.configureBlocking(false);
-            boolean result = sc.connect(isa);
-            if (!result) {
+            boolean connected = sc.connect(isa);
+            if (!connected) {
                 Selector RSelector = SelectorProvider.provider().openSelector();
                 SelectionKey RKey = sc.register (RSelector, SelectionKey.OP_CONNECT);
-                while (!result) {
+                while (!connected) {
                     int keysAdded = RSelector.select(100);
                     if (keysAdded > 0) {
-                        Set readyKeys = RSelector.selectedKeys();
-                        Iterator i = readyKeys.iterator();
+                        Set<SelectionKey> readyKeys = RSelector.selectedKeys();
+                        Iterator<SelectionKey> i = readyKeys.iterator();
                         while (i.hasNext()) {
-                            SelectionKey sk = (SelectionKey)i.next();
+                            SelectionKey sk = i.next();
                             SocketChannel nextReady = (SocketChannel)sk.channel();
-                            result = nextReady.finishConnect();
+                            connected = nextReady.finishConnect();
                         }
+                        readyKeys.clear();
                     }
                 }
                 RSelector.close();
             }
-            read(sc);
+            readAndClose(sc);
         }
     }
 
-    static void read(SocketChannel sc) throws Exception {
+    static void readAndClose(SocketChannel sc) throws Exception {
         ByteBuffer bb = ByteBuffer.allocateDirect(100);
         int n = 0;
         while (n == 0) // Note this is not a rigorous check for done reading
--- a/jdk/test/java/nio/channels/Selector/ConnectWrite.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/ConnectWrite.java	Wed Jul 05 17:17:57 2017 +0200
@@ -45,8 +45,8 @@
         Selector selector = SelectorProvider.provider().openSelector();
         InetAddress myAddress=InetAddress.getByName(TestUtil.HOST);
         InetSocketAddress isa = new InetSocketAddress(myAddress, port);
+        SocketChannel sc = SocketChannel.open();
         try {
-            SocketChannel sc = SocketChannel.open();
             sc.configureBlocking(false);
             SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
             boolean result = sc.connect(isa);
@@ -80,6 +80,7 @@
                 }
             }
         } finally {
+            sc.close();
             selector.close();
         }
     }
--- a/jdk/test/java/nio/channels/Selector/HelperSlowToDie.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/HelperSlowToDie.java	Wed Jul 05 17:17:57 2017 +0200
@@ -33,9 +33,15 @@
 
 public class HelperSlowToDie {
     private static final int CHANNELS_PER_THREAD = 1023;
+    private static final int TEST_ITERATIONS = 200;
     private static volatile boolean done;
 
     public static void main(String[] args) throws IOException {
+        if (!System.getProperty("os.name").startsWith("Windows")) {
+            System.out.println("Test skipped as it verifies a Windows specific bug");
+            return;
+        }
+
         Selector sel = Selector.open();
 
         // register channels
@@ -60,7 +66,7 @@
             new Thread(busy).start();
 
         // Loop changing the number of channels from 1023 to 1024 and back.
-        for (int i=0; i<1000; i++) {
+        for (int i=0; i<TEST_ITERATIONS; i++) {
             SocketChannel sc = SocketChannel.open();
             sc.configureBlocking(false);
             sc.register(sel, SelectionKey.OP_CONNECT);
@@ -71,5 +77,11 @@
 
         // terminate busy threads
         done = true;
+
+        // clean-up
+        for (int i=0; i<CHANNELS_PER_THREAD; i++) {
+            channels[i].close();
+        }
+        sel.close();
     }
 }
--- a/jdk/test/java/nio/channels/Selector/KeysReady.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/KeysReady.java	Wed Jul 05 17:17:57 2017 +0200
@@ -49,14 +49,18 @@
 
         // Prepare a selector
         Selector selector = SelectorProvider.provider().openSelector();
-        SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
-        int keysAdded = selector.select();
-        if (keysAdded > 0) {
-            keysAdded = selector.select(1000);
-            if (keysAdded > 0)
-                throw new Exception("Same key reported added twice");
+        try {
+            SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
+            int keysAdded = selector.select();
+            if (keysAdded > 0) {
+                keysAdded = selector.select(1000);
+                if (keysAdded > 0)
+                    throw new Exception("Same key reported added twice");
+            }
+        } finally {
+            selector.close();
+            sc.close();
         }
-        sc.close();
     }
 
     public static void main(String[] args) throws Exception {
--- a/jdk/test/java/nio/channels/Selector/LotsOfChannels.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/LotsOfChannels.java	Wed Jul 05 17:17:57 2017 +0200
@@ -35,19 +35,11 @@
 
 public class LotsOfChannels {
 
-    private final static int PIPES_COUNT = 1900;
+    private final static int PIPES_COUNT = 256;
     private final static int BUF_SIZE = 8192;
     private final static int LOOPS = 10;
 
     public static void main(String[] argv) throws Exception {
-
-
-        String os = System.getProperty("os.name");
-        if (!(os.equals("Windows NT")
-           || os.equals("Windows 2000")
-           || os.equals("Windows XP")))
-            return;
-
         Pipe[] pipes = new Pipe[PIPES_COUNT];
         Pipe pipe = Pipe.open();
         Pipe.SinkChannel sink = pipe.sink();
@@ -72,6 +64,13 @@
             sel.selectedKeys().clear();
             source.read(ByteBuffer.allocate(BUF_SIZE));
         }
+
+        for (int i = 0; i < PIPES_COUNT; i++ ) {
+            pipes[i].sink().close();
+            pipes[i].source().close();
+        }
+        pipe.sink().close();
+        pipe.source().close();
         sel.close();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/Selector/OutOfBand.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010, 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 6213702
+ * @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be
+ *    selected
+ */
+
+import java.net.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.io.IOException;
+
+public class OutOfBand {
+
+    public static void main(String[] args) throws Exception {
+        ServerSocketChannel ssc = null;
+        SocketChannel sc = null;
+        Selector sel = null;
+        Socket s = null;
+
+        try {
+            // establish loopback connection.
+            ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
+            s = new Socket(InetAddress.getLocalHost(),
+                           ssc.socket().getLocalPort());
+            sc = ssc.accept();
+
+            sel = Selector.open();
+            sc.configureBlocking(false);
+            sc.register(sel, SelectionKey.OP_READ);
+
+            // OOB data should be disabled by default
+            if (sc.socket().getOOBInline())
+                throw new RuntimeException("SO_OOBINLINE enabled");
+            test(s, false, 0,   0,   sel);
+            test(s, false, 512, 0,   sel);
+            test(s, false, 0,   512, sel);
+            test(s, false, 512, 512, sel);
+
+            // enable SO_OOBINLINE
+            sc.socket().setOOBInline(true);
+
+            // OOB data should be received
+            test(s, true, 0,   0,   sel);
+            test(s, true, 512, 0,   sel);
+            test(s, true, 0,   512, sel);
+            test(s, true, 512, 512, sel);
+
+        } finally {
+            if (sel != null) sel.close();
+            if (sc != null) sc.close();
+            if (ssc != null) ssc.close();
+            if (s != null) sc.close();
+        }
+    }
+
+    static void test(Socket s, boolean urgentExpected,
+                     int bytesBefore, int bytesAfter,
+                     Selector sel)
+        throws IOException
+    {
+        // send data
+        int bytesExpected = 0;
+        if (bytesBefore > 0) {
+            s.getOutputStream().write(new byte[bytesBefore]);
+            bytesExpected += bytesBefore;
+        }
+        s.sendUrgentData(0xff);
+        if (urgentExpected)
+            bytesExpected++;
+        if (bytesAfter > 0) {
+            s.getOutputStream().write(new byte[bytesAfter]);
+            bytesExpected += bytesAfter;
+        }
+
+        // receive data, checking for spurious wakeups and reads
+        int spuriousWakeups = 0;
+        int spuriousReads = 0;
+        int bytesRead = 0;
+        ByteBuffer bb = ByteBuffer.allocate(100);
+        for (;;) {
+            int n = sel.select(2000);
+            if (n == 0) {
+                if (bytesRead == bytesExpected) {
+                    System.out.format("Selector wakeups %d\tSpurious reads %d%n",
+                            spuriousWakeups, spuriousReads);
+                    return;
+                }
+                if (++spuriousWakeups >= 3)
+                    throw new RuntimeException("Selector appears to be spinning" +
+                        " or data not received");
+                continue;
+            }
+            if (n > 1)
+                throw new RuntimeException("More than one key selected????");
+            SelectionKey key = sel.selectedKeys().iterator().next();
+            bb.clear();
+            n = ((SocketChannel)key.channel()).read(bb);
+            if (n == 0) {
+                if (++spuriousReads >=3)
+                    throw new RuntimeException("Too many spurious reads");
+            } else {
+                bytesRead += n;
+                if (bytesRead > bytesExpected)
+                    throw new RuntimeException("Received more than expected");
+            }
+            sel.selectedKeys().clear();
+        }
+    }
+}
--- a/jdk/test/java/nio/channels/Selector/RegAfterPreClose.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/RegAfterPreClose.java	Wed Jul 05 17:17:57 2017 +0200
@@ -35,6 +35,7 @@
 
 public class RegAfterPreClose {
 
+    static final int TEST_ITERATIONS = 300;
     static volatile boolean done;
 
     /**
@@ -96,26 +97,21 @@
             }
         };
 
-        // schedule test to run for 1 minute
-        Executors.newScheduledThreadPool(1, factory).schedule(new Runnable() {
-            public void run() {
-                done = true;
-                sel.wakeup();
-            }}, 1, TimeUnit.MINUTES);
-
         // create Executor that handles tasks that closes channels
         // "asynchronously" - this creates the conditions to provoke the bug.
-        Executor executor = Executors.newFixedThreadPool(2, factory);
+        ExecutorService executor = Executors.newFixedThreadPool(2, factory);
 
         // submit task that connects to listener
         executor.execute(new Connector(ssc.socket().getLocalPort()));
 
         // loop accepting connections until done (or an IOException is thrown)
-        while (!done) {
+        int remaining = TEST_ITERATIONS;
+        while (remaining > 0) {
             sel.select();
             if (key.isAcceptable()) {
                 SocketChannel sc = ssc.accept();
                 if (sc != null) {
+                    remaining--;
                     sc.configureBlocking(false);
                     sc.register(sel, SelectionKey.OP_READ);
                     executor.execute(new Closer(sc));
@@ -123,5 +119,8 @@
             }
             sel.selectedKeys().clear();
         }
+        done = true;
+        sel.close();
+        executor.shutdown();
     }
 }
--- a/jdk/test/java/nio/channels/Selector/SelectAndCancel.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectAndCancel.java	Wed Jul 05 17:17:57 2017 +0200
@@ -31,11 +31,7 @@
 import java.net.*;
 
 public class SelectAndCancel {
-    static ServerSocketChannel ssc;
-    static Selector selector;
     static SelectionKey sk;
-    static InetSocketAddress isa;
-    public static int TEST_PORT = 40170;
 
     /*
      * CancelledKeyException is the failure symptom of 4729342
@@ -43,17 +39,17 @@
      * seen immediately when the bug is present.
      */
     public static void main(String[] args) throws Exception {
-        InetAddress lh = InetAddress.getLocalHost();
-        isa = new InetSocketAddress(lh, TEST_PORT);
-        selector = Selector.open();
-        ssc = ServerSocketChannel.open();
+        final Selector selector = Selector.open();
+        final ServerSocketChannel ssc =
+            ServerSocketChannel.open().bind(new InetSocketAddress(0));
+        final InetSocketAddress isa =
+            new InetSocketAddress(InetAddress.getLocalHost(), ssc.socket().getLocalPort());
 
         // Create and start a selector in a separate thread.
         new Thread(new Runnable() {
                 public void run() {
                     try {
                         ssc.configureBlocking(false);
-                        ssc.socket().bind(isa);
                         sk = ssc.register(selector, SelectionKey.OP_ACCEPT);
                         selector.select();
                     } catch (IOException e) {
--- a/jdk/test/java/nio/channels/Selector/SelectorLimit.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectorLimit.java	Wed Jul 05 17:17:57 2017 +0200
@@ -26,6 +26,8 @@
  * @summary Ensure that a Selector can return at least 100 selected keys
  * @author Mark Reinhold
  * @library ..
+ * @build SelectorLimit
+ * @run main/othervm SelectorLimit
  */
 
 import java.io.*;
--- a/jdk/test/java/nio/channels/Selector/SelectorTest.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectorTest.java	Wed Jul 05 17:17:57 2017 +0200
@@ -57,13 +57,13 @@
      */
     public static void main(String[] args) throws Exception {
         if (args.length == 0) {
-            InetSocketAddress isa
-                = new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT);
-            Server server = new Server(isa);
+            Server server = new Server(0);
             server.start();
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) { }
+            InetSocketAddress isa
+                = new InetSocketAddress(InetAddress.getLocalHost(), server.port());
             Client client = new Client(isa);
             client.start();
             if ((server.finish(FINISH_TIME) & client.finish(FINISH_TIME)) == 0)
@@ -74,9 +74,7 @@
 
             if (args.length > 1)
                 TEST_PORT = Integer.parseInt(args[1]);
-            InetSocketAddress isa
-                = new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT);
-            Server server = new Server(isa);
+            Server server = new Server(TEST_PORT);
             server.start();
             if (server.finish(FINISH_TIME) == 0)
                 throw new Exception("Failure");
@@ -136,18 +134,22 @@
     }
 
     static class Server extends TestThread {
+        private final ServerSocketChannel ssc;
         private List socketList = new ArrayList();
         private ServerSocket ss;
         private int connectionsAccepted = 0;
         private Selector pollSelector;
         private Selector acceptSelector;
-        private InetSocketAddress isa;
         private Set pkeys;
         private Set pskeys;
 
-        Server(InetSocketAddress isa) {
+        Server(int port) throws IOException {
             super("Server", SelectorTest.log);
-            this.isa = isa;
+            this.ssc = ServerSocketChannel.open().bind(new InetSocketAddress(port));
+        }
+
+        int port() {
+            return ssc.socket().getLocalPort();
         }
 
         public void go() throws Exception {
@@ -162,11 +164,7 @@
 
             requestThread.start();
 
-            ServerSocketChannel ssc = ServerSocketChannel.open();
             ssc.configureBlocking(false);
-            ssc.socket().setReuseAddress(true);
-            ssc.socket().bind(isa);
-
             SelectionKey acceptKey = ssc.register(acceptSelector,
                                                   SelectionKey.OP_ACCEPT);
             while(connectionsAccepted < SelectorTest.NUM_CLIENTS) {
--- a/jdk/test/java/nio/channels/Selector/WakeupNow.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupNow.java	Wed Jul 05 17:17:57 2017 +0200
@@ -44,10 +44,15 @@
         p.source().configureBlocking(false);
         p.source().register(sel, SelectionKey.OP_READ);
         sel.wakeup();
+        // ensure wakeup is consumed by selectNow
+        Thread.sleep(2000);
         sel.selectNow();
         long startTime = System.currentTimeMillis();
         int n = sel.select(2000);
         long endTime = System.currentTimeMillis();
+        p.source().close();
+        p.sink().close();
+        sel.close();
         if (endTime - startTime < 1000)
             throw new RuntimeException("test failed");
     }
@@ -60,10 +65,13 @@
         Pipe p = Pipe.open();
         p.source().configureBlocking(false);
         sel.wakeup();
+        // ensure wakeup is consumed by selectNow
+        Thread.sleep(2000);
         sel.selectNow();
         long startTime = System.currentTimeMillis();
         int n = sel.select(2000);
         long endTime = System.currentTimeMillis();
+        sel.close();
         if (endTime - startTime < 1000)
             throw new RuntimeException("test failed");
     }
--- a/jdk/test/java/nio/channels/Selector/WakeupOverflow.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupOverflow.java	Wed Jul 05 17:17:57 2017 +0200
@@ -31,8 +31,12 @@
 public class WakeupOverflow {
     public static void main( String[] args ) throws Exception {
         Selector selector = Selector.open();
-        for(int i=0; i<10000; i++) {
-            selector.wakeup();
+        try {
+            for(int i=0; i<10000; i++) {
+                selector.wakeup();
+            }
+        } finally {
+            selector.close();
         }
     }
 }
--- a/jdk/test/java/nio/channels/Selector/WakeupSpeed.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupSpeed.java	Wed Jul 05 17:17:57 2017 +0200
@@ -35,16 +35,19 @@
     public static void main(String argv[]) throws Exception {
         int waitTime = 4000;
         Selector selector = Selector.open();
-
-        selector.wakeup();
+        try {
+            selector.wakeup();
 
-        long t1 = System.currentTimeMillis();
-        selector.select(waitTime);
-        long t2 = System.currentTimeMillis();
-        long totalTime = t2 - t1;
+            long t1 = System.currentTimeMillis();
+            selector.select(waitTime);
+            long t2 = System.currentTimeMillis();
+            long totalTime = t2 - t1;
 
-        if (totalTime > waitTime)
-            throw new RuntimeException("Test failed");
+            if (totalTime > waitTime)
+                throw new RuntimeException("Test failed");
+        } finally {
+            selector.close();
+        }
     }
 
 }
--- a/jdk/test/java/nio/channels/ServerSocketChannel/AcceptAddress.java	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 test the address returned in socket from accept
- */
-
-import java.io.*;
-import java.net.*;
-import java.nio.*;
-import java.nio.channels.*;
-
-
-public class AcceptAddress {
-
-    public static void main(String[] args) throws Exception {
-        InetAddress local = InetAddress.getLocalHost();
-        InetSocketAddress isa = new InetSocketAddress(local, 5555);
-
-        ServerSocketChannel ssc;
-        ssc = ServerSocketChannel.open();
-        ssc.socket().bind(isa);
-
-        SocketChannel sc;
-        sc = SocketChannel.open();
-        sc.connect(isa);
-
-        SocketChannel sc2 = ssc.accept();
-        System.err.println("Socket connected to " + sc2);
-    }
-}
--- a/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java	Wed Jul 05 17:17:57 2017 +0200
@@ -78,8 +78,6 @@
                     throw x;
                 }
             }
-            if (shouldTimeout)
-                throw new Exception("Connection did not time out");
         }
         out.println("connected: " + so);
         out.println("           " + sc);
@@ -118,8 +116,6 @@
             }
             throw x;
         }
-        if (shouldTimeout)
-            throw new Exception("Read did not time out");
     }
 
     static void testRead(String hn, int timeout, boolean shouldTimeout)
--- a/jdk/test/java/nio/channels/SocketChannel/Bind.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Bind.java	Wed Jul 05 17:17:57 2017 +0200
@@ -31,13 +31,20 @@
 
 public class Bind {
     public static void main(String[] args) throws Exception {
+        SocketChannel sc1 = SocketChannel.open();
         try {
-            SocketChannel channel1 = SocketChannel.open();
-            channel1.socket().bind(new InetSocketAddress(5555));
-            SocketChannel channel2 = SocketChannel.open();
-            channel2.socket().bind(new InetSocketAddress(5555));
+            sc1.bind(new InetSocketAddress(0));
+            int port = sc1.socket().getLocalPort();
+            SocketChannel sc2 = SocketChannel.open();
+            try {
+                sc2.bind(new InetSocketAddress(port));
+            } finally {
+               sc2.close();
+            }
         } catch (BindException be) {
             // Correct result
+        } finally {
+            sc1.close();
         }
     }
 }
--- a/jdk/test/java/nio/channels/SocketChannel/Close.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Close.java	Wed Jul 05 17:17:57 2017 +0200
@@ -56,8 +56,12 @@
 
     static void testChannelClose() throws IOException {
         SelectionKey sk = open();
-        sk.channel().close();
-        check(sk);
+        try {
+            sk.channel().close();
+            check(sk);
+        } finally {
+            sk.selector().close();
+        }
     }
 
     public static void main(String[] args) throws Exception {
--- a/jdk/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java	Wed Jul 05 17:17:57 2017 +0200
@@ -55,5 +55,8 @@
         System.out.println ("Will hang here...");
         int nb = slave.read (ByteBuffer.allocate (1024));
         //System.out.println("read nb=" + nb);
+
+        selector.close();
+        server.close();
     }
 }
--- a/jdk/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java	Wed Jul 05 17:17:57 2017 +0200
@@ -33,11 +33,12 @@
 import java.net.*;
 
 public class CloseTimeoutChannel {
-    final static int PORT=6347;
     public static void main(String args[]) throws Exception {
+        int port = -1;
         try {
             ServerSocketChannel listener=ServerSocketChannel.open();
-            listener.socket().bind(new InetSocketAddress(PORT));
+            listener.socket().bind(new InetSocketAddress(0));
+            port = listener.socket().getLocalPort();
             AcceptorThread thread=new AcceptorThread(listener);
             thread.start();
         } catch (IOException e) {
@@ -50,7 +51,7 @@
         try {
             System.out.println("Establishing connection");
             Socket socket=SocketChannel.open(
-                new InetSocketAddress("127.0.0.1", PORT)).socket();
+                new InetSocketAddress("127.0.0.1", port)).socket();
             OutputStream out=socket.getOutputStream();
             InputStream in=socket.getInputStream();
 
@@ -98,7 +99,8 @@
                     Thread.sleep(100);
                 } catch (InterruptedException e) { }
 
-                System.out.println(INDENT+"Listening on port "+ PORT);
+                System.out.println(INDENT+"Listening on port "+
+                    _listener.socket().getLocalPort());
                 ByteBuffer buf=ByteBuffer.allocate(5);
                 Socket client=_listener.accept().socket();;
                 System.out.println(INDENT+"Accepted client");
@@ -123,6 +125,8 @@
                 client.close();
             } catch (IOException e) {
                 System.out.println(INDENT+"Error accepting!");
+            } finally {
+                try { _listener.close(); } catch (IOException ignore) { }
             }
         }
     }
--- a/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java	Wed Jul 05 17:17:57 2017 +0200
@@ -48,27 +48,31 @@
         sc.connect(isa);
 
         Selector selector = SelectorProvider.provider().openSelector();
-        SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
-        int keysAdded = selector.select();
-        if (keysAdded > 0) {
-            boolean result = sc.finishConnect();
-            if (result) {
-                keysAdded = selector.select(5000);
-                // 4750573: keysAdded should not be incremented when op is dropped
-                // from a key already in the selected key set
-                if (keysAdded > 0)
-                    throw new Exception("Test failed: 4750573 detected");
-                Set sel = selector.selectedKeys();
-                Iterator i = sel.iterator();
-                SelectionKey sk = (SelectionKey)i.next();
-                // 4737146: isConnectable should be false while connected
-                if (sk.isConnectable())
-                    throw new Exception("Test failed: 4737146 detected");
+        try {
+            SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT);
+            int keysAdded = selector.select();
+            if (keysAdded > 0) {
+                boolean result = sc.finishConnect();
+                if (result) {
+                    keysAdded = selector.select(5000);
+                    // 4750573: keysAdded should not be incremented when op is dropped
+                    // from a key already in the selected key set
+                    if (keysAdded > 0)
+                        throw new Exception("Test failed: 4750573 detected");
+                    Set<SelectionKey> sel = selector.selectedKeys();
+                    Iterator<SelectionKey> i = sel.iterator();
+                    SelectionKey sk = i.next();
+                    // 4737146: isConnectable should be false while connected
+                    if (sk.isConnectable())
+                        throw new Exception("Test failed: 4737146 detected");
+                }
+            } else {
+                throw new Exception("Select failed");
             }
-        } else {
-            throw new Exception("Select failed");
+        } finally {
+            sc.close();
+            selector.close();
         }
-        sc.close();
     }
 
     public static void main(String[] args) throws Exception {
--- a/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java	Wed Jul 05 17:17:57 2017 +0200
@@ -38,25 +38,33 @@
 
     static void test1() throws Exception {
         InetAddress bogus = InetAddress.getByName("0.0.0.0");
-        SocketChannel sc = SocketChannel.open();
         InetSocketAddress saddr = new InetSocketAddress(
             InetAddress.getByName(TestUtil.HOST), 23);
 
         //Test1: connect only
-        sc.connect(saddr);
-        InetAddress isa = sc.socket().getLocalAddress();
-        if (isa == null || isa.equals(bogus))
-            throw new RuntimeException("test failed");
+        SocketChannel sc = SocketChannel.open();
+        try {
+            sc.connect(saddr);
+            InetAddress ia = sc.socket().getLocalAddress();
+            if (ia == null || ia.equals(bogus))
+                throw new RuntimeException("test failed");
+        } finally {
+            sc.close();
+        }
 
         //Test2: bind and connect
         sc = SocketChannel.open();
-        sc.socket().bind(new InetSocketAddress(0));
-        if (sc.socket().getLocalPort() == 0)
-            throw new RuntimeException("test failed");
-        sc.socket().connect(saddr);
-        isa = sc.socket().getLocalAddress();
-        if (isa == null || isa.isAnyLocalAddress())
-            throw new RuntimeException("test failed");
+        try {
+            sc.socket().bind(new InetSocketAddress(0));
+            if (sc.socket().getLocalPort() == 0)
+                throw new RuntimeException("test failed");
+            sc.socket().connect(saddr);
+            InetAddress ia = sc.socket().getLocalAddress();
+            if (ia == null || ia.isAnyLocalAddress())
+                throw new RuntimeException("test failed");
+        } finally {
+            sc.close();
+        }
 
     }
 }
--- a/jdk/test/java/nio/channels/SocketChannel/SocketInheritance.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/SocketInheritance.java	Wed Jul 05 17:17:57 2017 +0200
@@ -105,7 +105,11 @@
 
         // launch the child
         String cmd = System.getProperty("java.home") + File.separator + "bin" +
-            File.separator + "java SocketInheritance -child " + port;
+            File.separator + "java";
+        String testClasses = System.getProperty("test.classes");
+        if (testClasses != null)
+            cmd += " -cp " + testClasses;
+        cmd += " SocketInheritance -child " + port;
 
         Process p = Runtime.getRuntime().exec(cmd);
 
--- a/jdk/test/java/nio/channels/SocketChannel/Trivial.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Trivial.java	Wed Jul 05 17:17:57 2017 +0200
@@ -33,22 +33,27 @@
     public static void main(String[] args) throws Exception {
         SocketChannel sc = SocketChannel.open();
         Selector sel = Selector.open();
-        if (sc.keyFor(sel) != null)
-            throw new Exception("keyFor != null");
-        sc.configureBlocking(false);
-        SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args);
-        if (sc.keyFor(sel) != sk)
-            throw new Exception("keyFor returned " + sc.keyFor(sel));
-        if (sk.attachment() != args)
-            throw new Exception("attachment() returned " + sk.attachment());
-        Trivial t = new Trivial();
-        sk.attach(t);
-        if (sk.attachment() != t)
-            throw new Exception("Wrong attachment");
-        sk.isReadable();
-        sk.isWritable();
-        sk.isConnectable();
-        sk.isAcceptable();
+        try {
+            if (sc.keyFor(sel) != null)
+                throw new Exception("keyFor != null");
+            sc.configureBlocking(false);
+            SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args);
+            if (sc.keyFor(sel) != sk)
+                throw new Exception("keyFor returned " + sc.keyFor(sel));
+            if (sk.attachment() != args)
+                throw new Exception("attachment() returned " + sk.attachment());
+            Trivial t = new Trivial();
+            sk.attach(t);
+            if (sk.attachment() != t)
+                throw new Exception("Wrong attachment");
+            sk.isReadable();
+            sk.isWritable();
+            sk.isConnectable();
+            sk.isAcceptable();
+        } finally {
+            sel.close();
+            sc.close();
+        }
     }
 
 }
--- a/jdk/test/java/nio/channels/SocketChannel/UnboundSocketTests.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/UnboundSocketTests.java	Wed Jul 05 17:17:57 2017 +0200
@@ -57,39 +57,47 @@
         System.out.println("\n-- SocketChannel --");
 
         SocketChannel sc = SocketChannel.open();
+        try {
+            check("getLocalPort()", sc.socket().getLocalPort(), -1);
+            checkIsAnyLocalAddress("getLocalAddress()",
+                sc.socket().getLocalAddress());
+            check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null);
 
-        check("getLocalPort()", sc.socket().getLocalPort(), -1);
-        checkIsAnyLocalAddress("getLocalAddress()",
-            sc.socket().getLocalAddress());
-        check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null);
-
-        check("getPort()", sc.socket().getPort(), 0);
-        check("getInetAddress()", sc.socket().getInetAddress(), null);
-        check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null);
-
+            check("getPort()", sc.socket().getPort(), 0);
+            check("getInetAddress()", sc.socket().getInetAddress(), null);
+            check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null);
+        } finally {
+            sc.close();
+        }
 
         System.out.println("\n-- ServerSocketChannel --");
 
         ServerSocketChannel ssc = ServerSocketChannel.open();
-
-        check("getLocalPort()", ssc.socket().getLocalPort(), -1);
-        check("getInetAddress()", ssc.socket().getInetAddress(), null);
-        check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null);
+        try {
+            check("getLocalPort()", ssc.socket().getLocalPort(), -1);
+            check("getInetAddress()", ssc.socket().getInetAddress(), null);
+            check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null);
+        } finally {
+            ssc.close();
+        }
 
         System.out.println("\n-- DatagramChannel --");
 
         DatagramChannel dc = DatagramChannel.open();
-
-        // not specified
-        check("getLocalPort()", dc.socket().getLocalPort(), 0);
+        try {
+            // not specified
+            check("getLocalPort()", dc.socket().getLocalPort(), 0);
 
-        checkIsAnyLocalAddress("getLocalAddress()",
-            dc.socket().getLocalAddress());
-        check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null);
+            checkIsAnyLocalAddress("getLocalAddress()",
+                dc.socket().getLocalAddress());
+            check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null);
 
-        check("getPort()", dc.socket().getPort(), -1);
-        check("getInetAddress()", dc.socket().getInetAddress(), null);
-        check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null);
+            check("getPort()", dc.socket().getPort(), -1);
+            check("getInetAddress()", dc.socket().getInetAddress(), null);
+            check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null);
+        } finally {
+            dc.close();
+        }
 
         if (failures > 0) {
             throw new RuntimeException(failures + " sub-tests(s) failed.");
--- a/jdk/test/java/nio/channels/etc/Shadow.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/etc/Shadow.java	Wed Jul 05 17:17:57 2017 +0200
@@ -35,7 +35,6 @@
 
 public class Shadow {
 
-    private static final int PORT = 2019;
     static PrintStream log = System.err;
 
     private static void dump(ServerSocket s) {
@@ -69,7 +68,7 @@
     public static void main(String[] args) throws Exception {
         boolean useChannels
             = ((args.length == 0) || Boolean.valueOf(args[0]).booleanValue());
-        int port = (args.length > 1 ? Integer.parseInt(args[1]) : PORT);
+        int port = (args.length > 1 ? Integer.parseInt(args[1]) : -1);
 
         // open server socket
         ServerSocket serverSocket;
@@ -86,7 +85,8 @@
         }
 
         // bind server socket to port
-        SocketAddress bindAddr = new InetSocketAddress(port);
+        SocketAddress bindAddr =
+            new InetSocketAddress((port == -1) ? 0 : port);
         serverSocket.bind(bindAddr);
         log.println("bound ServerSocket: " + serverSocket);
 
--- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java	Wed Jul 05 17:17:57 2017 +0200
@@ -26,6 +26,8 @@
  * @bug 4997227
  * @summary Calling inheritedChannel() after FileDescriptor.in was closed
  *          caused an InternalError to be thrown.
+ * @build ClosedStreams
+ * @run main/othervm ClosedStreams
  */
 
 import java.io.FileDescriptor;
--- a/jdk/test/java/nio/charset/coders/BashStreams.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/charset/coders/BashStreams.java	Wed Jul 05 17:17:57 2017 +0200
@@ -46,7 +46,7 @@
 
         CharacterGenerator(long seed, String csn, int limit) {
             rand = new Random(seed);
-            this.max = Surrogate.UCS4_MAX + 1;
+            this.max = Character.MAX_CODE_POINT + 1;
             this.limit = limit;
         }
 
@@ -77,17 +77,20 @@
             int c;
             for (;;) {
                 c = rand.nextInt(max);
-                if (Surrogate.is(c) || (c == 0xfffe) || (c == 0xffff))
+                if ((Character.isBmpCodePoint(c)
+                     && (Character.isSurrogate((char) c)
+                         || (c == 0xfffe) || (c == 0xffff))))
                     continue;
-                if (Surrogate.neededFor(c) && (count == limit - 1))
+                if (Character.isSupplementaryCodePoint(c)
+                        && (count == limit - 1))
                     continue;
                 break;
             }
             count++;
-            if (Surrogate.neededFor(c)) {
+            if (Character.isSupplementaryCodePoint(c)) {
                 count++;
-                push(Surrogate.low(c));
-                return Surrogate.high(c);
+                push(Character.lowSurrogate(c));
+                return Character.highSurrogate(c);
             }
             return (char)c;
         }
@@ -137,7 +140,7 @@
                 char d = cg.next();
                 if (c != d) {
                     if (c == '?') {
-                        if (Surrogate.isHigh(d))
+                        if (Character.isHighSurrogate(d))
                             cg.next();
                         continue;
                     }
@@ -187,7 +190,7 @@
             w.write(ca, 0, n);
             count += n;
         }
-        if (Surrogate.isHigh(ca[n - 1]))
+        if (Character.isHighSurrogate(ca[n - 1]))
             w.write(cg.next());
         w.close();
     }
@@ -253,7 +256,8 @@
                         if (!cg.hasNext())
                             break;
                         char c = cg.next();
-                        if (Surrogate.isHigh(c) && (cb.remaining() == 1)) {
+                        if (Character.isHighSurrogate(c)
+                                && cb.remaining() == 1) {
                             cg.push(c);
                             break;
                         }
@@ -311,7 +315,7 @@
                     mismatchedEOF(csn, count + i, cg.count());
                 char d = cg.next();
                 if (c == '?') {
-                    if (Surrogate.isHigh(d)) {
+                    if (Character.isHighSurrogate(d)) {
                         cg.next();
                         continue;
                     }
--- a/jdk/test/java/nio/charset/coders/Surrogate.java	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- */
-
-public class Surrogate {
-
-    public static final int UCS4_SURROGATE_MIN = 0x10000;
-    public static final int UCS4_MAX = (1 << 20) + UCS4_SURROGATE_MIN - 1;
-
-    // UTF-16 surrogate-character ranges
-    //
-    public static final char MIN_HIGH = '\uD800';
-    public static final char MAX_HIGH = '\uDBFF';
-    public static final char MIN_LOW  = '\uDC00';
-    public static final char MAX_LOW  = '\uDFFF';
-    public static final char MIN = MIN_HIGH;
-    public static final char MAX = MAX_LOW;
-
-    public static boolean neededFor(int uc) {
-        return (uc >= UCS4_SURROGATE_MIN) && (uc <= UCS4_MAX);
-    }
-
-    public static boolean isHigh(int c) {
-        return (MIN_HIGH <= c) && (c <= MAX_HIGH);
-    }
-
-    static char high(int uc) {
-        return (char)(0xd800 | (((uc - UCS4_SURROGATE_MIN) >> 10) & 0x3ff));
-    }
-
-    public static boolean isLow(int c) {
-        return (MIN_LOW <= c) && (c <= MAX_LOW);
-    }
-
-    static char low(int uc) {
-        return (char)(0xdc00 | ((uc - UCS4_SURROGATE_MIN) & 0x3ff));
-    }
-
-    public static boolean is(int c) {
-        return (MIN <= c) && (c <= MAX);
-    }
-
-    static int toUCS4(char c, char d) {
-        return (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000;
-    }
-
-}
--- a/jdk/test/java/nio/charset/coders/Surrogates.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/nio/charset/coders/Surrogates.java	Wed Jul 05 17:17:57 2017 +0200
@@ -42,9 +42,8 @@
     static void initData() throws IOException {
         StringBuffer sb = new StringBuffer();
         for (int i = 0; i < LEN; i++) {
-            int c = Surrogate.UCS4_SURROGATE_MIN + 1;
-            sb.append(Surrogate.high(c));
-            sb.append(Surrogate.low(c));
+            int c = Character.MIN_SUPPLEMENTARY_CODE_POINT + 1;
+            sb.append(Character.toChars(c));
         }
         input = sb.toString().toCharArray();
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
--- a/jdk/test/java/util/Arrays/Sorting.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/java/util/Arrays/Sorting.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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
@@ -43,10 +43,11 @@
 
     // Array lengths used in a long run (default)
     private static final int[] LONG_RUN_LENGTHS = {
-        1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000};
+        1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 };
 
     // Array lengths used in a short run
-    private static final int[] SHORT_RUN_LENGTHS = { 1, 2, 3, 21, 55, 1000, 10000 };
+    private static final int[] SHORT_RUN_LENGTHS = {
+        1, 2, 3, 21, 55, 1000, 10000 };
 
     // Random initial values used in a long run (default)
     private static final long[] LONG_RUN_RANDOMS = {666, 0xC0FFEE, 999};
@@ -65,99 +66,338 @@
         }
         long end = System.currentTimeMillis();
 
-        out.format("PASS in %d sec.\n", Math.round((end - start) / 1E3));
+        out.format("\nPASSED in %d sec.\n", Math.round((end - start) / 1E3));
     }
 
     private static void testAndCheck(int[] lengths, long[] randoms) {
+        testEmptyAndNullIntArray();
+        testEmptyAndNullLongArray();
+        testEmptyAndNullShortArray();
+        testEmptyAndNullCharArray();
+        testEmptyAndNullByteArray();
+        testEmptyAndNullFloatArray();
+        testEmptyAndNullDoubleArray();
+
         for (long random : randoms) {
             reset(random);
 
-            for (int len : lengths) {
-                testAndCheckWithCheckSum(len, random);
-            }
-            reset(random);
-
-            for (int len : lengths) {
-                testAndCheckWithScrambling(len, random);
+            for (int length : lengths) {
+                testAndCheckWithCheckSum(length, random);
             }
             reset(random);
 
-            for (int len : lengths) {
-                testAndCheckFloat(len, random);
+            for (int length : lengths) {
+                testAndCheckWithScrambling(length, random);
+            }
+            reset(random);
+
+            for (int length : lengths) {
+                testAndCheckFloat(length, random);
             }
             reset(random);
 
-            for (int len : lengths) {
-                testAndCheckDouble(len, random);
+            for (int length : lengths) {
+                testAndCheckDouble(length, random);
             }
             reset(random);
 
-            for (int len : lengths) {
-                testAndCheckRange(len, random);
+            for (int length : lengths) {
+                testAndCheckRange(length, random);
             }
             reset(random);
 
-            for (int len : lengths) {
-                testAndCheckSubArray(len, random);
+            for (int length : lengths) {
+                testAndCheckSubArray(length, random);
+            }
+            reset(random);
+
+            for (int length : lengths) {
+                testStable(length, random);
             }
         }
     }
 
-    private static void testAndCheckSubArray(int len, long random) {
-        int[] golden = new int[len];
+    private static void testEmptyAndNullIntArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new int[] {});
+        Arrays.sort(new int[] {}, 0, 0);
+
+        try {
+            Arrays.sort((int[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((int[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(int[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(int[]) shouldn't catch null array");
+    }
+
+    private static void testEmptyAndNullLongArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new long[] {});
+        Arrays.sort(new long[] {}, 0, 0);
+
+        try {
+            Arrays.sort((long[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((long[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(long[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(long[]) shouldn't catch null array");
+    }
+
+    private static void testEmptyAndNullShortArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new short[] {});
+        Arrays.sort(new short[] {}, 0, 0);
+
+        try {
+            Arrays.sort((short[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((short[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(short[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(short[]) shouldn't catch null array");
+    }
+
+    private static void testEmptyAndNullCharArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new char[] {});
+        Arrays.sort(new char[] {}, 0, 0);
 
-        for (int m = 1; m < len / 2; m *= 2) {
+        try {
+            Arrays.sort((char[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((char[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(char[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(char[]) shouldn't catch null array");
+    }
+
+    private static void testEmptyAndNullByteArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new byte[] {});
+        Arrays.sort(new byte[] {}, 0, 0);
+
+        try {
+            Arrays.sort((byte[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((byte[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(byte[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(byte[]) shouldn't catch null array");
+    }
+
+    private static void testEmptyAndNullFloatArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new float[] {});
+        Arrays.sort(new float[] {}, 0, 0);
+
+        try {
+            Arrays.sort((float[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((float[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(float[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(float[]) shouldn't catch null array");
+    }
+
+    private static void testEmptyAndNullDoubleArray() {
+        ourDescription = "Check empty and null array";
+        Arrays.sort(new double[] {});
+        Arrays.sort(new double[] {}, 0, 0);
+
+        try {
+            Arrays.sort((double[]) null);
+        } catch (NullPointerException expected) {
+            try {
+                Arrays.sort((double[]) null, 0, 0);
+            } catch (NullPointerException expected2) {
+                return;
+            }
+            failed("Arrays.sort(double[],fromIndex,toIndex) shouldn't " +
+                "catch null array");
+        }
+        failed("Arrays.sort(double[]) shouldn't catch null array");
+    }
+
+    private static void testAndCheckSubArray(int length, long random) {
+        ourDescription = "Check sorting of subarray";
+        int[] golden = new int[length];
+        boolean newLine = false;
+
+        for (int m = 1; m < length / 2; m *= 2) {
+            newLine = true;
             int fromIndex = m;
-            int toIndex = len - m;
+            int toIndex = length - m;
 
             prepareSubArray(golden, fromIndex, toIndex, m);
             int[] test = golden.clone();
 
             for (TypeConverter converter : TypeConverter.values()) {
-                out.println("Test #6: " + converter +
-                   " len = " + len + ", m = " + m);
+                out.println("Test 'subarray': " + converter +
+                   " length = " + length + ", m = " + m);
                 Object convertedGolden = converter.convert(golden);
                 Object convertedTest = converter.convert(test);
-
-                // outArr(test);
+                // outArray(test);
                 sortSubArray(convertedTest, fromIndex, toIndex);
-                // outArr(test);
+                // outArray(test);
                 checkSubArray(convertedTest, fromIndex, toIndex, m);
             }
         }
+        if (newLine) {
+            out.println();
+        }
+    }
+
+    private static void testAndCheckRange(int length, long random) {
+        ourDescription = "Check range check";
+        int[] golden = new int[length];
+
+        for (int m = 1; m < 2 * length; m *= 2) {
+            for (int i = 1; i <= length; i++) {
+                golden[i - 1] = i % m + m % i;
+            }
+            for (TypeConverter converter : TypeConverter.values()) {
+                out.println("Test 'range': " + converter +
+                   ", length = " + length + ", m = " + m);
+                Object convertedGolden = converter.convert(golden);
+                checkRange(convertedGolden, m);
+            }
+        }
         out.println();
     }
 
-    private static void testAndCheckRange(int len, long random) {
-        int[] golden = new int[len];
+    private static void testStable(int length, long random) {
+        ourDescription = "Check if sorting is stable";
+        Pair[] a = build(length);
 
-        for (int m = 1; m < 2 * len; m *= 2) {
-            for (int i = 1; i <= len; i++) {
-                golden[i - 1] = i % m + m % i;
+        out.println("Test 'stable': " + "random = " +  random +
+            ", length = " + length);
+        Arrays.sort(a);
+        checkSorted(a);
+        checkStable(a);
+    }
+
+    private static void checkSorted(Pair[] a) {
+        for (int i = 0; i < a.length - 1; i++) {
+            if (a[i].getKey() > a[i + 1].getKey()) {
+                failed(i, "" + a[i].getKey(), "" + a[i + 1].getKey());
             }
-            for (TypeConverter converter : TypeConverter.values()) {
-                out.println("Test #5: " + converter +
-                   ", len = " + len + ", m = " + m);
-                Object convertedGolden = converter.convert(golden);
-                sortRange(convertedGolden, m);
-                sortEmpty(convertedGolden);
+        }
+    }
+
+    private static void checkStable(Pair[] a) {
+        for (int i = 0; i < a.length / 4; ) {
+            int key1 = a[i].getKey();
+            int value1 = a[i++].getValue();
+            int key2 = a[i].getKey();
+            int value2 = a[i++].getValue();
+            int key3 = a[i].getKey();
+            int value3 = a[i++].getValue();
+            int key4 = a[i].getKey();
+            int value4 = a[i++].getValue();
+
+            if (!(key1 == key2 && key2 == key3 && key3 == key4)) {
+                failed("On position " + i + " must keys are different " +
+                    key1 + ", " + key2 + ", " + key3 + ", " + key4);
+            }
+            if (!(value1 < value2 && value2 < value3 && value3 < value4)) {
+                failed("Sorting is not stable at position " + i +
+                    ". Second values have been changed: " +  value1 + ", " +
+                    value2 + ", " + value3 + ", " + value4);
             }
         }
-        out.println();
+    }
+
+    private static Pair[] build(int length) {
+        Pair[] a = new Pair[length * 4];
+
+        for (int i = 0; i < a.length; ) {
+            int key = ourRandom.nextInt();
+            a[i++] = new Pair(key, 1);
+            a[i++] = new Pair(key, 2);
+            a[i++] = new Pair(key, 3);
+            a[i++] = new Pair(key, 4);
+        }
+        return a;
     }
 
-    private static void testAndCheckWithCheckSum(int len, long random) {
-        int[] golden = new int[len];
+    private static final class Pair implements Comparable<Pair> {
+        Pair(int key, int value) {
+            myKey = key;
+            myValue = value;
+        }
+
+        int getKey() {
+            return myKey;
+        }
+
+        int getValue() {
+            return myValue;
+        }
 
-        for (int m = 1; m < 2 * len; m *= 2) {
+        public int compareTo(Pair pair) {
+            if (myKey < pair.myKey) {
+                return -1;
+            }
+            if (myKey > pair.myKey) {
+                return 1;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return "(" + myKey + ", " + myValue + ")";
+        }
+
+        private int myKey;
+        private int myValue;
+    }
+
+    private static void testAndCheckWithCheckSum(int length, long random) {
+        ourDescription = "Check sorting with check sum";
+        int[] golden = new int[length];
+
+        for (int m = 1; m < 2 * length; m *= 2) {
             for (UnsortedBuilder builder : UnsortedBuilder.values()) {
                 builder.build(golden, m);
                 int[] test = golden.clone();
 
                 for (TypeConverter converter : TypeConverter.values()) {
-                    out.println("Test #1: " + converter + " " + builder +
-                       "random = " +  random + ", len = " + len +
-                       ", m = " + m);
+                    out.println("Test 'check sum': " + converter + " " +
+                        builder + "random = " +  random + ", length = " +
+                        length + ", m = " + m);
                     Object convertedGolden = converter.convert(golden);
                     Object convertedTest = converter.convert(test);
                     sort(convertedTest);
@@ -168,11 +408,12 @@
         out.println();
     }
 
-    private static void testAndCheckWithScrambling(int len, long random) {
-        int[] golden = new int[len];
+    private static void testAndCheckWithScrambling(int length, long random) {
+        ourDescription = "Check sorting with scrambling";
+        int[] golden = new int[length];
 
         for (int m = 1; m <= 7; m++) {
-            if (m > len) {
+            if (m > length) {
                 break;
             }
             for (SortedBuilder builder : SortedBuilder.values()) {
@@ -181,9 +422,9 @@
                 scramble(test);
 
                 for (TypeConverter converter : TypeConverter.values()) {
-                    out.println("Test #2: " + converter + " " + builder +
-                       "random = " +  random + ", len = " + len +
-                       ", m = " + m);
+                    out.println("Test 'scrambling': " + converter + " " +
+                       builder + "random = " +  random + ", length = " +
+                       length + ", m = " + m);
                     Object convertedGolden = converter.convert(golden);
                     Object convertedTest = converter.convert(test);
                     sort(convertedTest);
@@ -194,8 +435,9 @@
         out.println();
     }
 
-    private static void testAndCheckFloat(int len, long random) {
-        float[] golden = new float[len];
+    private static void testAndCheckFloat(int length, long random) {
+        ourDescription = "Check float sorting";
+        float[] golden = new float[length];
         final int MAX = 10;
         boolean newLine = false;
 
@@ -204,22 +446,23 @@
                 for (int z = 0; z <= MAX; z++) {
                     for (int n = 0; n <= MAX; n++) {
                         for (int p = 0; p <= MAX; p++) {
-                            if (a + g + z + n + p > len) {
+                            if (a + g + z + n + p > length) {
                                 continue;
                             }
-                            if (a + g + z + n + p < len) {
+                            if (a + g + z + n + p < length) {
                                 continue;
                             }
                             for (FloatBuilder builder : FloatBuilder.values()) {
-                                out.println("Test #3: random = " + random +
-                                   ", len = " + len + ", a = " + a + ", g = " + g +
-                                   ", z = " + z + ", n = " + n + ", p = " + p);
+                                out.println("Test 'float': random = " + random +
+                                   ", length = " + length + ", a = " + a +
+                                   ", g = " + g + ", z = " + z + ", n = " + n +
+                                   ", p = " + p);
                                 builder.build(golden, a, g, z, n, p);
                                 float[] test = golden.clone();
                                 scramble(test);
-                                // outArr(test);
+                                // outArray(test);
                                 sort(test);
-                                // outArr(test);
+                                // outArray(test);
                                 compare(test, golden, a, n, g);
                             }
                             newLine = true;
@@ -233,8 +476,9 @@
         }
     }
 
-    private static void testAndCheckDouble(int len, long random) {
-        double[] golden = new double[len];
+    private static void testAndCheckDouble(int length, long random) {
+        ourDescription = "Check double sorting";
+        double[] golden = new double[length];
         final int MAX = 10;
         boolean newLine = false;
 
@@ -243,22 +487,22 @@
                 for (int z = 0; z <= MAX; z++) {
                     for (int n = 0; n <= MAX; n++) {
                         for (int p = 0; p <= MAX; p++) {
-                            if (a + g + z + n + p > len) {
+                            if (a + g + z + n + p > length) {
                                 continue;
                             }
-                            if (a + g + z + n + p < len) {
+                            if (a + g + z + n + p < length) {
                                 continue;
                             }
                             for (DoubleBuilder builder : DoubleBuilder.values()) {
-                                out.println("Test #4: random = " + random +
-                                   ", len = " + len + ", a = " + a + ", g = " + g +
-                                   ", z = " + z + ", n = " + n + ", p = " + p);
+                                out.println("Test 'double': random = " + random +
+                                   ", length = " + length + ", a = " + a + ", g = " +
+                                   g + ", z = " + z + ", n = " + n + ", p = " + p);
                                 builder.build(golden, a, g, z, n, p);
                                 double[] test = golden.clone();
                                 scramble(test);
-                                // outArr(test);
+                                // outArray(test);
                                 sort(test);
-                                // outArr(test);
+                                // outArray(test);
                                 compare(test, golden, a, n, g);
                             }
                             newLine = true;
@@ -276,37 +520,29 @@
         for (int i = 0; i < fromIndex; i++) {
             a[i] = 0xBABA;
         }
-
         for (int i = fromIndex; i < toIndex; i++) {
             a[i] = -i + m;
         }
-
         for (int i = toIndex; i < a.length; i++) {
             a[i] = 0xDEDA;
         }
     }
 
     private static void scramble(int[] a) {
-        int length = a.length;
-
-        for (int i = 0; i < length * 7; i++) {
-            swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+        for (int i = 0; i < a.length * 7; i++) {
+            swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length));
         }
     }
 
     private static void scramble(float[] a) {
-        int length = a.length;
-
-        for (int i = 0; i < length * 7; i++) {
-            swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+        for (int i = 0; i < a.length * 7; i++) {
+            swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length));
         }
     }
 
     private static void scramble(double[] a) {
-        int length = a.length;
-
-        for (int i = 0; i < length * 7; i++) {
-            swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+        for (int i = 0; i < a.length * 7; i++) {
+            swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length));
         }
     }
 
@@ -393,6 +629,16 @@
                 }
                 return b;
             }
+        },
+        INTEGER {
+            Object convert(int[] a) {
+                Integer[] b = new Integer[a.length];
+
+                for (int i = 0; i < a.length; i++) {
+                    b[i] = new Integer(a[i]);
+                }
+                return b;
+            }
         };
 
         abstract Object convert(int[] a);
@@ -691,6 +937,8 @@
             compare((float[]) test, (float[]) golden);
         } else if (test instanceof double[]) {
             compare((double[]) test, (double[]) golden);
+        } else if (test instanceof Integer[]) {
+            compare((Integer[]) test, (Integer[]) golden);
         } else {
             failed("Unknow type of array: " + test + " of class " +
                 test.getClass().getName());
@@ -703,13 +951,13 @@
     }
 
     private static void failed(String message) {
-        err.format("\n*** FAILED: %s\n\n", message);
+        err.format("\n*** TEST FAILED - %s\n\n%s\n\n", ourDescription, message);
         throw new RuntimeException("Test failed - see log file for details");
     }
 
     private static void failed(int index, String value1, String value2) {
-        failed("Array is not sorted at " + index + "-th position: " + value1 +
-               " and " + value2);
+        failed("Array is not sorted at " + index + "-th position: " +
+            value1 + " and " + value2);
     }
 
     private static void checkSorted(Object object) {
@@ -727,12 +975,22 @@
             checkSorted((float[]) object);
         } else if (object instanceof double[]) {
             checkSorted((double[]) object);
+        } else if (object instanceof Integer[]) {
+            checkSorted((Integer[]) object);
         } else {
             failed("Unknow type of array: " + object + " of class " +
                 object.getClass().getName());
         }
     }
 
+    private static void compare(Integer[] a, Integer[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i].intValue() != b[i].intValue()) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
     private static void compare(int[] a, int[] b) {
         for (int i = 0; i < a.length; i++) {
             if (a[i] != b[i]) {
@@ -789,6 +1047,14 @@
         }
     }
 
+    private static void checkSorted(Integer[] a) {
+        for (int i = 0; i < a.length - 1; i++) {
+            if (a[i].intValue() > a[i + 1].intValue()) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+    }
+
     private static void checkSorted(int[] a) {
         for (int i = 0; i < a.length - 1; i++) {
             if (a[i] > a[i + 1]) {
@@ -847,7 +1113,7 @@
 
     private static void checkCheckSum(Object test, Object golden) {
         if (checkSum(test) != checkSum(golden)) {
-            failed("Original and sorted arrays seems not identical");
+            failed("It seems that original and sorted arrays are not identical");
         }
     }
 
@@ -866,6 +1132,8 @@
             return checkSum((float[]) object);
         } else if (object instanceof double[]) {
             return checkSum((double[]) object);
+        } else if (object instanceof Integer[]) {
+            return checkSum((Integer[]) object);
         } else {
             failed("Unknow type of array: " + object + " of class " +
                 object.getClass().getName());
@@ -873,6 +1141,15 @@
         }
     }
 
+    private static int checkSum(Integer[] a) {
+        int checkXorSum = 0;
+
+        for (Integer e : a) {
+            checkXorSum ^= e.intValue();
+        }
+        return checkXorSum;
+    }
+
     private static int checkSum(int[] a) {
         int checkXorSum = 0;
 
@@ -951,6 +1228,8 @@
             Arrays.sort((float[]) object);
         } else if (object instanceof double[]) {
             Arrays.sort((double[]) object);
+        } else if (object instanceof Integer[]) {
+            Arrays.sort((Integer[]) object);
         } else {
             failed("Unknow type of array: " + object + " of class " +
                 object.getClass().getName());
@@ -972,6 +1251,8 @@
             Arrays.sort((float[]) object, fromIndex, toIndex);
         } else if (object instanceof double[]) {
             Arrays.sort((double[]) object, fromIndex, toIndex);
+        } else if (object instanceof Integer[]) {
+            Arrays.sort((Integer[]) object, fromIndex, toIndex);
         } else {
             failed("Unknow type of array: " + object + " of class " +
                 object.getClass().getName());
@@ -993,12 +1274,36 @@
             checkSubArray((float[]) object, fromIndex, toIndex, m);
         } else if (object instanceof double[]) {
             checkSubArray((double[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof Integer[]) {
+            checkSubArray((Integer[]) object, fromIndex, toIndex, m);
         } else {
             failed("Unknow type of array: " + object + " of class " +
                 object.getClass().getName());
         }
     }
 
+    private static void checkSubArray(Integer[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i].intValue() != 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i].intValue() > a[i + 1].intValue()) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i].intValue() != 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
     private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) {
         for (int i = 0; i < fromIndex; i++) {
             if (a[i] != 0xBABA) {
@@ -1153,49 +1458,30 @@
         }
     }
 
-    private static void sortRange(Object object, int m) {
+    private static void checkRange(Object object, int m) {
         if (object instanceof int[]) {
-            sortRange((int[]) object, m);
+            checkRange((int[]) object, m);
         } else if (object instanceof long[]) {
-            sortRange((long[]) object, m);
+            checkRange((long[]) object, m);
         } else if (object instanceof short[]) {
-            sortRange((short[]) object, m);
+            checkRange((short[]) object, m);
         } else if (object instanceof byte[]) {
-            sortRange((byte[]) object, m);
+            checkRange((byte[]) object, m);
         } else if (object instanceof char[]) {
-            sortRange((char[]) object, m);
+            checkRange((char[]) object, m);
         } else if (object instanceof float[]) {
-            sortRange((float[]) object, m);
+            checkRange((float[]) object, m);
         } else if (object instanceof double[]) {
-            sortRange((double[]) object, m);
+            checkRange((double[]) object, m);
+        } else if (object instanceof Integer[]) {
+            checkRange((Integer[]) object, m);
         } else {
             failed("Unknow type of array: " + object + " of class " +
                 object.getClass().getName());
         }
     }
 
-    private static void sortEmpty(Object object) {
-        if (object instanceof int[]) {
-            Arrays.sort(new int [] {});
-        } else if (object instanceof long[]) {
-            Arrays.sort(new long [] {});
-        } else if (object instanceof short[]) {
-            Arrays.sort(new short [] {});
-        } else if (object instanceof byte[]) {
-            Arrays.sort(new byte [] {});
-        } else if (object instanceof char[]) {
-            Arrays.sort(new char [] {});
-        } else if (object instanceof float[]) {
-            Arrays.sort(new float [] {});
-        } else if (object instanceof double[]) {
-            Arrays.sort(new double [] {});
-        } else {
-            failed("Unknow type of array: " + object + " of class " +
-                object.getClass().getName());
-        }
-    }
-
-    private static void sortRange(int[] a, int m) {
+    private static void checkRange(Integer[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1224,7 +1510,36 @@
         }
     }
 
-    private static void sortRange(long[] a, int m) {
+    private static void checkRange(int[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void checkRange(long[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1253,7 +1568,7 @@
         }
     }
 
-    private static void sortRange(byte[] a, int m) {
+    private static void checkRange(byte[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1282,7 +1597,7 @@
         }
     }
 
-    private static void sortRange(short[] a, int m) {
+    private static void checkRange(short[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1311,7 +1626,7 @@
         }
     }
 
-    private static void sortRange(char[] a, int m) {
+    private static void checkRange(char[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1340,7 +1655,7 @@
         }
     }
 
-    private static void sortRange(float[] a, int m) {
+    private static void checkRange(float[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1369,7 +1684,7 @@
         }
     }
 
-    private static void sortRange(double[] a, int m) {
+    private static void checkRange(double[] a, int m) {
         try {
             Arrays.sort(a, m + 1, m);
 
@@ -1410,31 +1725,36 @@
         ourSecond = 0;
     }
 
-    private static void outArr(int[] a) {
+    private static void outArray(Object[] a) {
+        for (int i = 0; i < a.length; i++) {
+            out.print(a[i] + " ");
+        }
+        out.println();
+    }
+
+    private static void outArray(int[] a) {
         for (int i = 0; i < a.length; i++) {
             out.print(a[i] + " ");
         }
         out.println();
-        out.println();
     }
 
-    private static void outArr(float[] a) {
+    private static void outArray(float[] a) {
         for (int i = 0; i < a.length; i++) {
             out.print(a[i] + " ");
         }
         out.println();
-        out.println();
     }
 
-    private static void outArr(double[] a) {
+    private static void outArray(double[] a) {
         for (int i = 0; i < a.length; i++) {
             out.print(a[i] + " ");
         }
         out.println();
-        out.println();
     }
 
     private static int ourFirst;
     private static int ourSecond;
     private static Random ourRandom;
+    private static String ourDescription;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010, 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.util.logging.*;
+
+public class AnonLoggerWeakRefLeak {
+    public static int DEFAULT_LOOP_TIME = 60;  // time is in seconds
+
+    public static void main(String[] args) {
+        int loop_time = 0;
+        int max_loop_time = DEFAULT_LOOP_TIME;
+
+        if (args.length == 0) {
+            System.out.println("INFO: using default time of "
+                + max_loop_time + " seconds.");
+        } else {
+            try {
+                max_loop_time = Integer.parseInt(args[0]);
+            } catch (NumberFormatException nfe) {
+                System.err.println("Error: '" + args[0]
+                    + "': is not a valid seconds value.");
+                System.err.println("Usage: AnonLoggerWeakRefLeak [seconds]");
+                System.exit(1);
+            }
+        }
+
+        long count = 0;
+        long now = 0;
+        long startTime = System.currentTimeMillis();
+
+        while (now < (startTime + (max_loop_time * 1000))) {
+            if ((count % 1000) == 0) {
+                // Print initial call count to let caller know that
+                // we're up and running and then periodically
+                System.out.println("INFO: call count = " + count);
+            }
+
+            for (int i = 0; i < 100; i++) {
+                // this Logger call is leaking a WeakReference in Logger.kids
+                java.util.logging.Logger.getAnonymousLogger();
+                count++;
+            }
+
+            try {
+                // delay for 1/10 of a second to avoid CPU saturation
+                Thread.sleep(100);
+            } catch (InterruptedException ie) {
+                // ignore any exceptions
+            }
+
+            now = System.currentTimeMillis();
+        }
+
+        System.out.println("INFO: final loop count = " + count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,247 @@
+#
+# Copyright (c) 2010, 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 6942989
+# @ignore until 6964018 is fixed
+# @summary Check for WeakReference leak in anonymous Logger objects
+# @author Daniel D. Daugherty
+#
+# @run build AnonLoggerWeakRefLeak
+# @run shell/timeout=180 AnonLoggerWeakRefLeak.sh
+
+# The timeout is: 2 minutes for infrastructure and 1 minute for the test
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+  echo "TESTJAVA not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+  echo "TESTSRC not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+JAVA="${TESTJAVA}"/bin/java
+JMAP="${TESTJAVA}"/bin/jmap
+JPS="${TESTJAVA}"/bin/jps
+
+set -eu
+
+TEST_NAME="AnonLoggerWeakRefLeak"
+TARGET_CLASS="java\.lang\.ref\.WeakReference"
+
+is_cygwin=false
+is_mks=false
+is_windows=false
+
+case `uname -s` in
+CYGWIN*)
+    is_cygwin=true
+    is_windows=true
+    ;;
+Windows_*)
+    is_mks=true
+    is_windows=true
+    ;;
+*)
+    ;;
+esac
+
+
+# wrapper for grep
+#
+grep_cmd() {
+    set +e
+    if $is_windows; then
+        # need dos2unix to get rid of CTRL-M chars from java output
+        dos2unix | grep "$@"
+        status="$?"
+    else
+        grep "$@"
+        status="$?"
+    fi
+    set -e
+}
+
+
+# MAIN begins here
+#
+
+seconds=
+if [ "$#" -gt 0 ]; then
+    seconds="$1"
+fi
+
+# see if this version of jmap supports the '-histo:live' option
+jmap_option="-histo:live"
+set +e
+"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1
+grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1
+status="$?"
+set -e
+if [ "$status" = 0 ]; then
+    echo "INFO: switching jmap option from '$jmap_option'\c"
+    jmap_option="-histo"
+    echo " to '$jmap_option'."
+fi
+
+"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \
+    "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 &
+test_pid="$!"
+echo "INFO: starting $TEST_NAME as pid = $test_pid"
+
+# wait for test program to get going
+count=0
+while [ "$count" -lt 30 ]; do
+    sleep 2
+    grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1
+    if [ "$status" = 0 ]; then
+        break
+    fi
+    count=`expr $count + 1`
+done
+
+if [ "$count" -ge 30 ]; then
+    echo "ERROR: $TEST_NAME failed to get going." >&2
+    echo "INFO: killing $test_pid"
+    kill "$test_pid"
+    exit 1
+elif [ "$count" -gt 1 ]; then
+    echo "INFO: $TEST_NAME took $count loops to start."
+fi
+
+if $is_cygwin; then
+    # We need the Windows pid for jmap and not the Cygwin pid.
+    # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris.
+    jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'`
+    if [ -z "$jmap_pid" ]; then
+        echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2
+        echo "INFO: killing $test_pid"
+        kill "$test_pid"
+        exit 2
+    fi
+    echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid"
+else
+    jmap_pid="$test_pid"
+fi
+
+decreasing_cnt=0
+increasing_cnt=0
+loop_cnt=0
+prev_instance_cnt=0
+
+while true; do
+    # Output format for 'jmap -histo' in JDK1.5.0:
+    #
+    #     <#bytes> <#instances> <class_name>
+    #
+    # Output format for 'jmap -histo:live':
+    #
+    #     <num>: <#instances> <#bytes> <class_name>
+    #
+    set +e
+    "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1
+    status="$?"
+    set -e
+
+    if [ "$status" != 0 ]; then
+        echo "INFO: jmap exited with exit code = $status"
+        if [ "$loop_cnt" = 0 ]; then
+            echo "INFO: on the first iteration so no samples were taken."
+            echo "INFO: start of jmap output:"
+            cat "$TEST_NAME.jmap"
+            echo "INFO: end of jmap output."
+            echo "FAIL: jmap is unable to take any samples." >&2
+            echo "INFO: killing $test_pid"
+            kill "$test_pid"
+            exit 2
+        fi
+        echo "INFO: The likely reason is that $TEST_NAME has finished running."
+        break
+    fi
+
+    instance_cnt=`grep_cmd "[ 	]$TARGET_CLASS$" \
+        < "$TEST_NAME.jmap" \
+        | sed '
+            # strip leading whitespace; does nothing in JDK1.5.0
+            s/^[ 	][ 	]*//
+            # strip <#bytes> in JDK1.5.0; does nothing otherwise
+            s/^[1-9][0-9]*[ 	][ 	]*//
+            # strip <num>: field; does nothing in JDK1.5.0
+            s/^[1-9][0-9]*:[ 	][ 	]*//
+            # strip <class_name> field
+            s/[ 	].*//
+            '`
+    if [ -z "$instance_cnt" ]; then
+        echo "INFO: instance count is unexpectedly empty"
+        if [ "$loop_cnt" = 0 ]; then
+            echo "INFO: on the first iteration so no sample was found."
+            echo "INFO: There is likely a problem with the sed filter."
+            echo "INFO: start of jmap output:"
+            cat "$TEST_NAME.jmap"
+            echo "INFO: end of jmap output."
+            echo "FAIL: cannot find the instance count value." >&2
+            echo "INFO: killing $test_pid"
+            kill "$test_pid"
+            exit 2
+        fi
+    else
+        echo "INFO: instance_cnt = $instance_cnt"
+
+        if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then
+            increasing_cnt=`expr $increasing_cnt + 1`
+        else
+            decreasing_cnt=`expr $decreasing_cnt + 1`
+        fi
+        prev_instance_cnt="$instance_cnt"
+    fi
+
+    # delay between samples
+    sleep 5
+
+    loop_cnt=`expr $loop_cnt + 1`
+done
+
+echo "INFO: increasing_cnt = $increasing_cnt"
+echo "INFO: decreasing_cnt = $decreasing_cnt"
+
+echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects"
+if [ "$decreasing_cnt" = 0 ]; then
+    echo "INFO: is always increasing."
+    echo "FAIL: This indicates that there is a memory leak." >&2
+    exit 2
+fi
+
+echo "INFO: is both increasing and decreasing."
+echo "PASS: This indicates that there is not a memory leak."
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010, 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.util.logging.*;
+
+public class LoggerWeakRefLeak {
+    // AnonLoggerWeakRefLeak checks for one weak reference leak.
+    // LoggerWeakRefLeak checks for two weak reference leaks so
+    // this test runs twice as long, by default.
+    public static int DEFAULT_LOOP_TIME = 120;  // time is in seconds
+
+    public static void main(String[] args) {
+        int loop_time = 0;
+        int max_loop_time = DEFAULT_LOOP_TIME;
+
+        if (args.length == 0) {
+            System.out.println("INFO: using default time of "
+                + max_loop_time + " seconds.");
+        } else {
+            try {
+                max_loop_time = Integer.parseInt(args[0]);
+            } catch (NumberFormatException nfe) {
+                System.err.println("Error: '" + args[0]
+                    + "': is not a valid seconds value.");
+                System.err.println("Usage: LoggerWeakRefLeak [seconds]");
+                System.exit(1);
+            }
+        }
+
+        long count = 0;
+        int  loggerCount = 0;
+        long now = 0;
+        long startTime = System.currentTimeMillis();
+
+        while (now < (startTime + (max_loop_time * 1000))) {
+            if ((count % 1000) == 0) {
+                // Print initial call count to let caller know that
+                // we're up and running and then periodically
+                System.out.println("INFO: call count = " + count);
+            }
+
+            for (int i = 0; i < 100; i++) {
+                // This Logger call is leaking two different WeakReferences:
+                // - one in LogManager.LogNode
+                // - one in Logger.kids
+                java.util.logging.Logger.getLogger("logger-" + loggerCount);
+                count++;
+                if (++loggerCount >= 25000) {
+                    // Limit the Logger namespace used by the test so
+                    // the weak refs in LogManager.loggers that are
+                    // being properly managed don't skew the counts
+                    // by too much.
+                    loggerCount = 0;
+                }
+            }
+
+            try {
+                // delay for 1/10 of a second to avoid CPU saturation
+                Thread.sleep(100);
+            } catch (InterruptedException ie) {
+                // ignore any exceptions
+            }
+
+            now = System.currentTimeMillis();
+        }
+
+        System.out.println("INFO: final loop count = " + count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.sh	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,247 @@
+#
+# Copyright (c) 2010, 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 6942989
+# @ignore until 6964018 is fixed
+# @summary Check for WeakReference leak in Logger objects
+# @author Daniel D. Daugherty
+#
+# @run build LoggerWeakRefLeak
+# @run shell/timeout=240 LoggerWeakRefLeak.sh
+
+# The timeout is: 2 minutes for infrastructure and 1 minute for the test
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+  echo "TESTJAVA not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTSRC}" = "" ]
+then
+  echo "TESTSRC not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+JAVA="${TESTJAVA}"/bin/java
+JMAP="${TESTJAVA}"/bin/jmap
+JPS="${TESTJAVA}"/bin/jps
+
+set -eu
+
+TEST_NAME="LoggerWeakRefLeak"
+TARGET_CLASS="java\.lang\.ref\.WeakReference"
+
+is_cygwin=false
+is_mks=false
+is_windows=false
+
+case `uname -s` in
+CYGWIN*)
+    is_cygwin=true
+    is_windows=true
+    ;;
+Windows_*)
+    is_mks=true
+    is_windows=true
+    ;;
+*)
+    ;;
+esac
+
+
+# wrapper for grep
+#
+grep_cmd() {
+    set +e
+    if $is_windows; then
+        # need dos2unix to get rid of CTRL-M chars from java output
+        dos2unix | grep "$@"
+        status="$?"
+    else
+        grep "$@"
+        status="$?"
+    fi
+    set -e
+}
+
+
+# MAIN begins here
+#
+
+seconds=
+if [ "$#" -gt 0 ]; then
+    seconds="$1"
+fi
+
+# see if this version of jmap supports the '-histo:live' option
+jmap_option="-histo:live"
+set +e
+"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1
+grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1
+status="$?"
+set -e
+if [ "$status" = 0 ]; then
+    echo "INFO: switching jmap option from '$jmap_option'\c"
+    jmap_option="-histo"
+    echo " to '$jmap_option'."
+fi
+
+"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \
+    "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 &
+test_pid="$!"
+echo "INFO: starting $TEST_NAME as pid = $test_pid"
+
+# wait for test program to get going
+count=0
+while [ "$count" -lt 30 ]; do
+    sleep 2
+    grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1
+    if [ "$status" = 0 ]; then
+        break
+    fi
+    count=`expr $count + 1`
+done
+
+if [ "$count" -ge 30 ]; then
+    echo "ERROR: $TEST_NAME failed to get going." >&2
+    echo "INFO: killing $test_pid"
+    kill "$test_pid"
+    exit 1
+elif [ "$count" -gt 1 ]; then
+    echo "INFO: $TEST_NAME took $count loops to start."
+fi
+
+if $is_cygwin; then
+    # We need the Windows pid for jmap and not the Cygwin pid.
+    # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris.
+    jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'`
+    if [ -z "$jmap_pid" ]; then
+        echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2
+        echo "INFO: killing $test_pid"
+        kill "$test_pid"
+        exit 2
+    fi
+    echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid"
+else
+    jmap_pid="$test_pid"
+fi
+
+decreasing_cnt=0
+increasing_cnt=0
+loop_cnt=0
+prev_instance_cnt=0
+
+while true; do
+    # Output format for 'jmap -histo' in JDK1.5.0:
+    #
+    #     <#bytes> <#instances> <class_name>
+    #
+    # Output format for 'jmap -histo:live':
+    #
+    #     <num>: <#instances> <#bytes> <class_name>
+    #
+    set +e
+    "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1
+    status="$?"
+    set -e
+
+    if [ "$status" != 0 ]; then
+        echo "INFO: jmap exited with exit code = $status"
+        if [ "$loop_cnt" = 0 ]; then
+            echo "INFO: on the first iteration so no samples were taken."
+            echo "INFO: start of jmap output:"
+            cat "$TEST_NAME.jmap"
+            echo "INFO: end of jmap output."
+            echo "FAIL: jmap is unable to take any samples." >&2
+            echo "INFO: killing $test_pid"
+            kill "$test_pid"
+            exit 2
+        fi
+        echo "INFO: The likely reason is that $TEST_NAME has finished running."
+        break
+    fi
+
+    instance_cnt=`grep_cmd "[ 	]$TARGET_CLASS$" \
+        < "$TEST_NAME.jmap" \
+        | sed '
+            # strip leading whitespace; does nothing in JDK1.5.0
+            s/^[ 	][ 	]*//
+            # strip <#bytes> in JDK1.5.0; does nothing otherwise
+            s/^[1-9][0-9]*[ 	][ 	]*//
+            # strip <num>: field; does nothing in JDK1.5.0
+            s/^[1-9][0-9]*:[ 	][ 	]*//
+            # strip <class_name> field
+            s/[ 	].*//
+            '`
+    if [ -z "$instance_cnt" ]; then
+        echo "INFO: instance count is unexpectedly empty"
+        if [ "$loop_cnt" = 0 ]; then
+            echo "INFO: on the first iteration so no sample was found."
+            echo "INFO: There is likely a problem with the sed filter."
+            echo "INFO: start of jmap output:"
+            cat "$TEST_NAME.jmap"
+            echo "INFO: end of jmap output."
+            echo "FAIL: cannot find the instance count value." >&2
+            echo "INFO: killing $test_pid"
+            kill "$test_pid"
+            exit 2
+        fi
+    else
+        echo "INFO: instance_cnt = $instance_cnt"
+
+        if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then
+            increasing_cnt=`expr $increasing_cnt + 1`
+        else
+            decreasing_cnt=`expr $decreasing_cnt + 1`
+        fi
+        prev_instance_cnt="$instance_cnt"
+    fi
+
+    # delay between samples
+    sleep 5
+
+    loop_cnt=`expr $loop_cnt + 1`
+done
+
+echo "INFO: increasing_cnt = $increasing_cnt"
+echo "INFO: decreasing_cnt = $decreasing_cnt"
+
+echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects"
+if [ "$decreasing_cnt" = 0 ]; then
+    echo "INFO: is always increasing."
+    echo "FAIL: This indicates that there is a memory leak." >&2
+    exit 2
+fi
+
+echo "INFO: is both increasing and decreasing."
+echo "PASS: This indicates that there is not a memory leak."
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/AbstractButton/6711682/bug6711682.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2009, 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 6711682
+   @summary  JCheckBox in JTable: checkbox doesn't alaways respond to the first mouse click
+   @author Alexander Potochkin
+   @run main bug6711682
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.event.CellEditorListener;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.EventObject;
+
+public class bug6711682 {
+    private static JCheckBox editorCb;
+    private static JCheckBox rendererCb;
+    private static JTable table;
+
+    public static void main(String[] args) throws Exception {
+        Robot robot = new Robot();
+        robot.setAutoDelay(50);
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                createAndShowGUI();
+            }
+        });
+        toolkit.realSync();
+        Point l = table.getLocationOnScreen();
+        int h = table.getRowHeight();
+        for (int i = 0; i < 3; i++) {
+            robot.mouseMove(l.x + 5, l.y + 5 + i * h);
+            robot.mousePress(InputEvent.BUTTON1_MASK);
+            robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        }
+        // Without pressing F2 the last table's cell
+        // reported <code>false</code> value
+        // note that I can't press it inside the for loop
+        // because it doesn't reproduce the bug
+        robot.keyPress(KeyEvent.VK_F2);
+        robot.keyRelease(KeyEvent.VK_F2);
+
+        for (int i = 0; i < 3; i++) {
+            if (!Boolean.TRUE.equals(table.getValueAt(i, 0))) {
+                throw new RuntimeException("Row #" + i + " checkbox is not selected");
+            }
+        }
+        for (int i = 2; i >= 0; i--) {
+            robot.mouseMove(l.x + 5, l.y + 5 + i * h);
+            robot.mousePress(InputEvent.BUTTON1_MASK);
+            robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        }
+        robot.keyPress(KeyEvent.VK_F2);
+        robot.keyRelease(KeyEvent.VK_F2);
+        for (int i = 0; i < 3; i++) {
+            if (Boolean.TRUE.equals(table.getValueAt(i, 0))) {
+                throw new RuntimeException("Row #" + i + " checkbox is selected");
+            }
+        }
+    }
+
+    private static void createAndShowGUI() {
+        editorCb = new JCheckBox();
+        rendererCb = new JCheckBox();
+        JFrame f = new JFrame("Table with CheckBox");
+        Container p = f.getContentPane();
+        p.setLayout(new BorderLayout());
+        table = new JTable(new Object[][]{{false}, {false}, {false}}, new Object[]{"CheckBox"});
+        TableCellEditor editor = new TableCellEditor() {
+            int editedRow;
+
+            public Component getTableCellEditorComponent(JTable table,
+                                                         Object value, boolean isSelected, int row, int column) {
+                this.editedRow = row;
+                editorCb.setSelected(Boolean.TRUE.equals(value));
+                editorCb.setBackground(UIManager.getColor("Table.selectionBackground"));
+                return editorCb;
+            }
+
+            public void addCellEditorListener(CellEditorListener l) {
+            }
+
+            public void cancelCellEditing() {
+            }
+
+            public Object getCellEditorValue() {
+                return editorCb.isSelected();
+            }
+
+            public boolean isCellEditable(EventObject anEvent) {
+                return true;
+            }
+
+            public void removeCellEditorListener(CellEditorListener l) {
+            }
+
+            public boolean shouldSelectCell(EventObject anEvent) {
+                return true;
+            }
+
+            public boolean stopCellEditing() {
+                table.getModel().setValueAt(editorCb.isSelected(), editedRow, 0);
+                return true;
+            }
+        };
+        table.getColumnModel().getColumn(0).setCellEditor(editor);
+
+        TableCellRenderer renderer = new TableCellRenderer() {
+            public Component getTableCellRendererComponent(JTable table,
+                                                           Object value, boolean isSelected, boolean hasFocus,
+                                                           int row, int column) {
+                rendererCb.setSelected(Boolean.TRUE.equals(value));
+                return rendererCb;
+            }
+        };
+        table.getColumnModel().getColumn(0).setCellRenderer(renderer);
+
+        p.add(table, BorderLayout.CENTER);
+
+        f.pack();
+        f.setVisible(true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/6520101/bug6520101.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010, 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 @(#)bug6520101
+ * @bug 6520101
+ * @summary JFileChooser throws OOM in 1.4.2, 5.0u4 and 1.6.0
+ * @author Praveen Gupta
+ * @run main/othervm/timeout=600 -Xmx8m -verify bug6520101
+*/
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class bug6520101 implements Runnable {
+
+    private static final int ATTEMPTS = 500;
+    private static final int INTERVAL = 100;
+
+    private static final boolean ALWAYS_NEW_INSTANCE = false;
+    private static final boolean DO_GC_EACH_INTERVAL = false;
+    private static final boolean UPDATE_UI_EACH_INTERVAL = true;
+    private static final boolean AUTO_CLOSE_DIALOG = true;
+
+    private static JFileChooser CHOOSER;
+
+    public static void main(String[] args) throws Exception {
+        UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
+
+        for (int i = 0; i < ATTEMPTS; i++) {
+            doAttempt();
+        }
+
+        System.out.println("Test passed successfully");
+    }
+
+    private static void doAttempt() throws InterruptedException {
+        if (ALWAYS_NEW_INSTANCE || (CHOOSER == null))
+            CHOOSER = new JFileChooser(".");
+
+        if (UPDATE_UI_EACH_INTERVAL) {
+            CHOOSER.updateUI();
+        }
+
+        if (AUTO_CLOSE_DIALOG) {
+            Thread t = new Thread(new bug6520101(CHOOSER));
+            t.start();
+            CHOOSER.showOpenDialog(null);
+            t.join();
+        } else {
+            CHOOSER.showOpenDialog(null);
+        }
+
+        if (DO_GC_EACH_INTERVAL) {
+            System.gc();
+        }
+    }
+
+    private final JFileChooser chooser;
+
+    bug6520101(JFileChooser chooser) {
+        this.chooser = chooser;
+    }
+
+    public void run() {
+        while (!this.chooser.isShowing()) {
+            try {
+                Thread.sleep(30);
+            } catch (InterruptedException exception) {
+                exception.printStackTrace();
+            }
+        }
+
+        Timer timer = new Timer(INTERVAL, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                chooser.cancelSelection();
+            }
+        });
+
+        timer.setRepeats(false);
+        timer.start();
+    }
+}
--- a/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, 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
@@ -43,7 +43,7 @@
                     new com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel());
         } catch(UnsupportedLookAndFeelException e) {
             System.out.println("The test is for Windows LaF only");
-            System.exit(0);
+            return;
         }
 
         final bug6725409 bug6725409 = new bug6725409();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JPopupMenu/6495920/bug6495920.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010, 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 6495920
+ * @summary Tests that if the JPopupMenu.setVisible method throws an exception,
+            interaction with GNOME is not crippled
+ * @author Sergey Malenkov
+ * @library ../..
+ */
+
+import sun.awt.AppContext;
+
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.lang.reflect.Field;
+import javax.swing.JFrame;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.basic.BasicPopupMenuUI;
+
+public class bug6495920 implements Thread.UncaughtExceptionHandler {
+
+    public static void main(String[] args) throws Throwable {
+        SwingTest.start(bug6495920.class);
+    }
+
+    private static Robot robot;
+    private final JPanel panel;
+
+    public bug6495920(JFrame frame) {
+        JPopupMenu menu = new JPopupMenu() {
+            public void setVisible(boolean visible) {
+                super.setVisible(visible);
+                throw new AssertionError(visible ? "show popup" : "hide popup");
+            }
+        };
+        for (int i = 0; i < 10; i++) {
+            menu.add(new JMenuItem(String.valueOf(i)));
+        }
+        this.panel = new JPanel();
+        this.panel.setComponentPopupMenu(menu);
+        frame.add(this.panel);
+    }
+
+    public void firstShowPopup() throws Exception {
+        Point point = this.panel.getLocation();
+        SwingUtilities.convertPointToScreen(point, this.panel);
+
+        robot = new Robot(); // initialize shared static field first time
+        robot.mouseMove(point.x + 1, point.y + 1);
+        robot.mousePress(InputEvent.BUTTON3_MASK);
+        Thread.currentThread().setUncaughtExceptionHandler(this);
+        robot.mouseRelease(InputEvent.BUTTON3_MASK); // causes first AssertionError on EDT
+    }
+
+    public void secondHidePopup() {
+        Point point = this.panel.getLocation();
+        SwingUtilities.convertPointToScreen(point, this.panel);
+
+        robot.mouseMove(point.x - 1, point.y - 1);
+        Thread.currentThread().setUncaughtExceptionHandler(this);
+        robot.mousePress(InputEvent.BUTTON1_MASK); // causes second AssertionError on EDT
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+    }
+
+    public void thirdValidate() throws Exception {
+        Field key = BasicPopupMenuUI.class.getDeclaredField("MOUSE_GRABBER_KEY");
+        key.setAccessible(true);
+
+        Object grabber = AppContext.getAppContext().get(key.get(null));
+        if (grabber == null) {
+            throw new Exception("cannot find a mouse grabber in app's context");
+        }
+
+        Field field = grabber.getClass().getDeclaredField("grabbedWindow");
+        field.setAccessible(true);
+
+        Object window = field.get(grabber);
+        if (window != null) {
+            throw new Exception("interaction with GNOME is crippled");
+        }
+    }
+
+    public void uncaughtException(Thread thread, Throwable throwable) {
+        System.out.println(throwable);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/6777378/bug6777378.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010, 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 6777378
+   @summary NullPointerException in XPDefaultRenderer.paint()
+   @author Alexander Potochkin
+   @run main bug6777378
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.JTableHeader;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import java.awt.event.MouseEvent;
+import java.awt.event.InputEvent;
+import java.awt.*;
+
+public class bug6777378 {
+    private static JFrame frame;
+    private static JTableHeader header;
+
+    public static void main(String[] args) throws Exception {
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Robot robot = new Robot();
+        robot.setAutoDelay(20);
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                try {
+                    UIManager.setLookAndFeel(new MetalLookAndFeel());
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+                JTable table = new JTable(new AbstractTableModel() {
+                    public int getRowCount() {
+                        return 10;
+                    }
+
+                    public int getColumnCount() {
+                        return 10;
+                    }
+
+                    public Object getValueAt(int rowIndex, int columnIndex) {
+                        return "" + rowIndex + " " + columnIndex;
+                    }
+                });
+
+                header = new JTableHeader(table.getColumnModel());
+                header.setToolTipText("hello");
+
+                frame = new JFrame();
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+                frame.add(header);
+
+                frame.setSize(300, 300);
+                frame.setVisible(true);
+            }
+        });
+        toolkit.realSync();
+        Point point = header.getLocationOnScreen();
+        robot.mouseMove(point.x + 20, point.y + 50);
+        robot.mouseMove(point.x + 30, point.y + 50);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4129681.html	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,10 @@
+<html>
+<body>
+When applet starts, you'll see a checkbox and a label with a titled border.
+Turn on the checkbox to disable the label.
+The test passes if the title of the border is disabled as well as the label.
+
+<applet width="300" height="200" code="Test4129681.class">
+</applet>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4129681.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 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 4129681
+ * @summary Tests enabling/disabling of titled border's caption
+ * @author Sergey Malenkov
+ * @run applet/manual=yesno Test4129681.html
+ */
+
+import java.awt.BorderLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import javax.swing.BorderFactory;
+import javax.swing.JApplet;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+
+public class Test4129681 extends JApplet implements ItemListener {
+    private JLabel label;
+
+    @Override
+    public void init() {
+        JCheckBox check = new JCheckBox("disable");
+        check.addItemListener(this);
+
+        this.label = new JLabel("message");
+        this.label.setBorder(BorderFactory.createTitledBorder("label"));
+        this.label.setEnabled(!check.isSelected());
+
+        add(BorderLayout.NORTH, check);
+        add(BorderLayout.CENTER, this.label);
+    }
+
+    public void itemStateChanged(ItemEvent event) {
+        this.label.setEnabled(ItemEvent.DESELECTED == event.getStateChange());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4760089.html	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,10 @@
+<html>
+<body>
+When applet starts, you'll see a panel with a compound titled border.
+If one of its titles is overstriken with the border's line then test fails.
+Otherwise test passes.
+
+<applet width="600" height="300" code="Test4760089.class">
+</applet>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/border/Test4760089.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 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 4760089
+ * @summary Tests that titled border do not paint inner titled border over its caption
+ * @author Sergey Malenkov
+ * @run applet/manual=yesno Test4760089.html
+ */
+
+import javax.swing.JApplet;
+import javax.swing.JPanel;
+import javax.swing.border.Border;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+
+public class Test4760089 extends JApplet {
+    @Override
+    public void init() {
+        Border border = new EtchedBorder();
+        border = new TitledBorder(border, "LEFT",  TitledBorder.LEFT,  TitledBorder.TOP);
+        border = new TitledBorder(border, "RIGHT", TitledBorder.RIGHT, TitledBorder.TOP);
+
+        JPanel panel = new JPanel();
+        panel.setBorder(border);
+        getContentPane().add(panel);
+    }
+}
--- a/jdk/test/sun/nio/ch/Basic.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/ch/Basic.java	Wed Jul 05 17:17:57 2017 +0200
@@ -32,5 +32,7 @@
 public class Basic {
     public static void main(String[] args) throws Exception {
         Pipe p = Pipe.open();
+        p.source().close();
+        p.sink().close();
     }
 }
--- a/jdk/test/sun/nio/ch/TempBuffer.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/ch/TempBuffer.java	Wed Jul 05 17:17:57 2017 +0200
@@ -54,8 +54,12 @@
                     blah.deleteOnExit();
                     TempBuffer.initTestFile(blah);
                     RandomAccessFile raf = new RandomAccessFile(blah, "rw");
-                    FileChannel fs = raf.getChannel();
-                    fs.transferTo(0, SIZE, Channels.newChannel(out));
+                    FileChannel fc = raf.getChannel();
+                    try {
+                        fc.transferTo(0, SIZE, Channels.newChannel(out));
+                    } finally {
+                        fc.close();
+                    }
                     out.flush();
                 } catch (IOException ioe) {
                     throw new RuntimeException(ioe);
@@ -69,10 +73,17 @@
         File blah = File.createTempFile("blah2", null);
         blah.deleteOnExit();
         RandomAccessFile raf = new RandomAccessFile(blah, "rw");
-        FileChannel fs = raf.getChannel();
-        raf.setLength(SIZE);
-        fs.transferFrom(Channels.newChannel(in), 0, SIZE);
-        fs.close();
+        FileChannel fc = raf.getChannel();
+        try {
+            raf.setLength(SIZE);
+            fc.transferFrom(Channels.newChannel(in), 0, SIZE);
+        } finally {
+            fc.close();
+        }
+
+        sourceChannel.close();
+        sinkChannel.close();
+        blah.delete();
     }
 
     private static void initTestFile(File blah) throws IOException {
--- a/jdk/test/sun/nio/cs/FindDecoderBugs.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/cs/FindDecoderBugs.java	Wed Jul 05 17:17:57 2017 +0200
@@ -298,7 +298,7 @@
         void testRandomly(byte[] prefix, int n) {
             int len = prefix.length;
             byte[] ia = Arrays.copyOf(prefix, len + n);
-            for (int i = 0; i < 10000; i++) {
+            for (int i = 0; i < 5000; i++) {
                 for (int j = 0; j < n; j++)
                     ia[len + j] = randomByte();
                 test(ia);
@@ -435,6 +435,9 @@
     static void equal(Object x, Object y) {
         if (x == null ? y == null : x.equals(y)) pass();
         else fail(x + " not equal to " + y);}
+    static void equal(int x, int y) {
+        if (x == y) pass();
+        else fail(x + " not equal to " + y);}
     public static void main(String[] args) throws Throwable {
         try {realMain(args);} catch (Throwable t) {unexpected(t);}
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
--- a/jdk/test/sun/nio/cs/ReadZero.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/cs/ReadZero.java	Wed Jul 05 17:17:57 2017 +0200
@@ -43,15 +43,18 @@
                 return 0;
             }
         };
-
-        is.read(new byte[1], 0, 1); // ok
-        InputStreamReader isr = new InputStreamReader(is);
+        try {
+            is.read(new byte[1], 0, 1); // ok
+            InputStreamReader isr = new InputStreamReader(is);
 
-        try {
-            int res = isr.read(new char[1], 0, 1);
-        } catch (IOException x) {
-            System.out.println("IOException caught");
-            return;
+            try {
+                int res = isr.read(new char[1], 0, 1);
+            } catch (IOException x) {
+                System.out.println("IOException caught");
+                return;
+            }
+        } finally {
+            is.close();
         }
         throw new RuntimeException("IOException not thrown");
     }
--- a/jdk/test/sun/nio/cs/Test4206507.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/cs/Test4206507.java	Wed Jul 05 17:17:57 2017 +0200
@@ -32,7 +32,12 @@
 
 public class Test4206507 {
     public static void main(String[] args) throws UnsupportedEncodingException {
-        Locale.setDefault(new Locale("tr", "TR"));
-        byte[] b = "".getBytes("ISO8859-9");
+        Locale l = Locale.getDefault();
+        try {
+            Locale.setDefault(new Locale("tr", "TR"));
+            byte[] b = "".getBytes("ISO8859-9");
+        } finally {
+            Locale.setDefault(l);
+        }
     }
 }
--- a/jdk/test/sun/nio/cs/TestStringCoding.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/cs/TestStringCoding.java	Wed Jul 05 17:17:57 2017 +0200
@@ -26,7 +26,7 @@
 /* @test
    @bug 6636323 6636319
    @summary Test if StringCoding and NIO result have the same de/encoding result
- * @run main/timeout=2000 TestStringCoding
+ * @run main/othervm/timeout=2000 TestStringCoding
  */
 
 import java.util.*;
--- a/jdk/test/sun/nio/cs/TestX11CNS.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/nio/cs/TestX11CNS.java	Wed Jul 05 17:17:57 2017 +0200
@@ -94,6 +94,8 @@
     }
 
     static void compare(Charset newCS, Charset oldCS) throws Exception {
+        if (newCS == null)
+            return;  // does not exist on this platform
         char[] cc = getChars(newCS, oldCS);
         System.out.printf("    Diff <%s> <%s>...%n", newCS.name(), oldCS.name());
 
@@ -120,14 +122,22 @@
         }
     }
 
+    private static Charset getCharset(String czName)
+        throws Exception {
+        try {
+            return (Charset)Class.forName(czName).newInstance();
+        } catch (ClassNotFoundException e){}
+        return null;  // does not exist
+    }
+
     public static void main(String[] args) throws Exception {
-        compare(new sun.awt.motif.X11CNS11643P1(),
+        compare(getCharset("sun.awt.motif.X11CNS11643P1"),
                 new X11CNS11643P1());
 
-        compare(new sun.awt.motif.X11CNS11643P2(),
+        compare(getCharset("sun.awt.motif.X11CNS11643P2"),
                 new X11CNS11643P2());
 
-        compare(new sun.awt.motif.X11CNS11643P3(),
+        compare(getCharset("sun.awt.motif.X11CNS11643P3"),
                 new X11CNS11643P3());
 
     }
--- a/jdk/test/sun/security/krb5/auto/SSL.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/security/krb5/auto/SSL.java	Wed Jul 05 17:17:57 2017 +0200
@@ -25,6 +25,16 @@
  * @test
  * @bug 6894643 6913636
  * @summary Test JSSE Kerberos ciphersuite
+ * @run main SSL TLS_KRB5_WITH_RC4_128_SHA
+ * @run main SSL TLS_KRB5_WITH_RC4_128_MD5
+ * @run main SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA
+ * @run main SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5
+ * @run main SSL TLS_KRB5_WITH_DES_CBC_SHA
+ * @run main SSL TLS_KRB5_WITH_DES_CBC_MD5
+ * @run main SSL TLS_KRB5_EXPORT_WITH_RC4_40_SHA
+ * @run main SSL TLS_KRB5_EXPORT_WITH_RC4_40_MD5
+ * @run main SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
+ * @run main SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
  */
 import java.io.*;
 import java.net.InetAddress;
@@ -37,7 +47,7 @@
 
 public class SSL {
 
-    private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
+    private static String krb5Cipher;
     private static final int LOOP_LIMIT = 1;
     private static int loopCount = 0;
     private static volatile String server;
@@ -45,6 +55,8 @@
 
     public static void main(String[] args) throws Exception {
 
+        krb5Cipher = args[0];
+
         KDC kdc = KDC.create(OneKDC.REALM);
         // Run this after KDC, so our own DNS service can be started
         try {
@@ -117,7 +129,7 @@
             SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(server, port);
 
             // Enable only a KRB5 cipher suite.
-            String enabledSuites[] = {KRB5_CIPHER};
+            String enabledSuites[] = {krb5Cipher};
             sslSocket.setEnabledCipherSuites(enabledSuites);
             // Should check for exception if enabledSuites is not supported
 
@@ -155,7 +167,7 @@
             port = sslServerSocket.getLocalPort();
 
             // Enable only a KRB5 cipher suite.
-            String enabledSuites[] = {KRB5_CIPHER};
+            String enabledSuites[] = {krb5Cipher};
             sslServerSocket.setEnabledCipherSuites(enabledSuites);
             // Should check for exception if enabledSuites is not supported
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/etype/ETypeOrder.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 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 6844907
+ * @summary krb5 etype order should be from strong to weak
+ */
+
+import sun.security.krb5.internal.crypto.EType;
+
+public class ETypeOrder {
+    public static void main(String[] args) throws Exception {
+
+        // File does not exist, so that the system-default one won't be used
+        System.setProperty("java.security.krb5.conf", "no_such_file");
+        int[] etypes = EType.getBuiltInDefaults();
+
+        // Reference order, note that 2 is not implemented in Java
+        int correct[] = { 18, 17, 16, 23, 1, 3, 2 };
+
+        int match = 0;
+        loopi: for (int i=0; i<etypes.length; i++) {
+            for (; match < correct.length; match++) {
+                if (etypes[i] == correct[match]) {
+                    System.out.println("Find " + etypes[i] + " at #" + match);
+                    continue loopi;
+                }
+            }
+            throw new Exception("No match or bad order for " + etypes[i]);
+        }
+    }
+}
--- a/jdk/test/sun/security/krb5/ktab/HighestKvno.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/sun/security/krb5/ktab/HighestKvno.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2010, 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
@@ -227,9 +227,6 @@
         if (keys[0].getKeyVersionNumber() != 5) {
             throw new Exception("Highest not first");
         }
-        if (ktab.readServiceKey(pn).getKeyVersionNumber() != 5) {
-            throw new Exception("Highest not chosen");
-        }
         new File("kt").delete();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs12/PKCS12SameKeyId.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010, 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 6958026
+ * @summary Problem with PKCS12 keystore
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.AlgorithmParameters;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import sun.security.pkcs.EncryptedPrivateKeyInfo;
+import sun.security.tools.KeyTool;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.X500Name;
+
+public class PKCS12SameKeyId {
+
+    private static final String JKSFILE = "PKCS12SameKeyId.jks";
+    private static final String P12FILE = "PKCS12SameKeyId.p12";
+    private static final char[] PASSWORD = "changeit".toCharArray();
+    private static final int SIZE = 10;
+
+    public static void main(String[] args) throws Exception {
+
+        // Prepare a JKS keystore with many entries
+        new File(JKSFILE).delete();
+        for (int i=0; i<SIZE; i++) {
+            System.err.print(".");
+            String cmd = "-keystore " + JKSFILE
+                    + " -storepass changeit -keypass changeit "
+                    + "-genkeypair -alias p" + i + " -dname CN=" + i;
+            KeyTool.main(cmd.split(" "));
+        }
+
+        // Prepare EncryptedPrivateKeyInfo parameters, copied from various
+        // places in PKCS12KeyStore.java
+        AlgorithmParameters algParams =
+                AlgorithmParameters.getInstance("PBEWithSHA1AndDESede");
+        algParams.init(new PBEParameterSpec("12345678".getBytes(), 1024));
+        AlgorithmId algid = new AlgorithmId(
+                new ObjectIdentifier("1.2.840.113549.1.12.1.3"), algParams);
+
+        PBEKeySpec keySpec = new PBEKeySpec(PASSWORD);
+        SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+        SecretKey skey = skFac.generateSecret(keySpec);
+
+        Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
+        cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
+
+        // Pre-calculated keys and certs and aliases
+        byte[][] keys = new byte[SIZE][];
+        Certificate[][] certChains = new Certificate[SIZE][];
+        String[] aliases = new String[SIZE];
+
+        // Reads from JKS keystore and pre-calculate
+        KeyStore ks = KeyStore.getInstance("jks");
+        ks.load(new FileInputStream(JKSFILE), PASSWORD);
+        for (int i=0; i<SIZE; i++) {
+            aliases[i] = "p" + i;
+            byte[] enckey = cipher.doFinal(
+                    ks.getKey(aliases[i], PASSWORD).getEncoded());
+            keys[i] = new EncryptedPrivateKeyInfo(algid, enckey).getEncoded();
+            certChains[i] = ks.getCertificateChain(aliases[i]);
+        }
+
+        // Write into PKCS12 keystore. Use this overloaded version of
+        // setKeyEntry() to be as fast as possible, so that they would
+        // have same localKeyId.
+        KeyStore p12 = KeyStore.getInstance("pkcs12");
+        p12.load(null, PASSWORD);
+        for (int i=0; i<SIZE; i++) {
+            p12.setKeyEntry(aliases[i], keys[i], certChains[i]);
+        }
+        p12.store(new FileOutputStream(P12FILE), PASSWORD);
+
+        // Check private keys still match certs
+        p12 = KeyStore.getInstance("pkcs12");
+        p12.load(new FileInputStream(P12FILE), PASSWORD);
+        for (int i=0; i<SIZE; i++) {
+            String a = "p" + i;
+            X509Certificate x = (X509Certificate)p12.getCertificate(a);
+            X500Name name = (X500Name)x.getSubjectDN();
+            if (!name.getCommonName().equals(""+i)) {
+                throw new Exception(a + "'s cert is " + name);
+            }
+        }
+    }
+}
--- a/jdk/test/tools/launcher/Arrrghs.java	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java	Wed Jul 05 17:17:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, 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 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881
+ * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938
  * @summary Argument parsing validation.
  * @compile -XDignore.symbol.file Arrrghs.java TestHelper.java
  * @run main Arrrghs
@@ -223,6 +223,20 @@
         tr.checkPositive();
         tr.isNotZeroOutput();
         System.out.println(tr);
+
+        // 6753938, test for non-negative exit value for an incorrectly formed
+        // command line,  '% java'
+        tr = TestHelper.doExec(TestHelper.javaCmd);
+        tr.checkNegative();
+        tr.isNotZeroOutput();
+        System.out.println(tr);
+
+        // 6753938, test for non-negative exit value for an incorrectly formed
+        // command line,  '% java -Xcomp'
+        tr = TestHelper.doExec(TestHelper.javaCmd, "-Xcomp");
+        tr.checkNegative();
+        tr.isNotZeroOutput();
+        System.out.println(tr);
     }
 
     /*
--- a/jdk/test/tools/launcher/Makefile.SolarisRunpath	Tue Jul 20 22:17:28 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-# Copyright (c) 2007, 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.
-
-#
-
-# This is a not quite automated Makefile to generate the Solaris
-# binaries used for the SolarisRunpath.sh test.  First,
-# libraryCaller.java program must be compiled.  Next, javah is called
-# on the class file to generate the needed header file for the jni
-# code.  Then, 2 Solaris executables are generated in separate
-# directories, a default one meant to be pointed to by LD_LIBRARY_PATH
-# (this function returns 0) and another one for the data model
-# specific LD_LIBRARY_PATH (this function returns the size of integers
-# in the data model, 32 or 64).  A better makefile would run, say
-# isainfo -v, and generated binaries for all supported data models.
-# To do this a mapping would be needed from data models to
-# architecture dependent compiler options; e.g. 64 bit on sparc =>
-# -xarch=v9.  Also, the settings for JINCLUDE, JAVAC, and JAVAH should
-# come from the current build.  The C compiler should be the one
-# approved for the build.  To be extra safe, the binaries should be
-# generated on the oldest Solaris release supported by the current
-# Java build.
-
-# Include directory in JRE or JDK install; e.g.
-JINCLUDE=/java/re/jdk/1.4.1/latest/binaries/solaris-sparc/include
-
-# Path to javac executable; e.g.
-JAVAC=/java/re/jdk/1.4.1/promoted/fcs/b21/binaries/solaris-sparc/bin/javac
-
-# Path to javah executable; e.g.
-JAVAH=/java/re/jdk/1.4.1/promoted/fcs/b21/binaries/solaris-sparc/bin/javah
-
-# Path to C compiler; e.g.
-CC=/java/devtools/sparc/SUNWspro/SC6.1/bin/cc
-
-
-ARCH=`uname -p`
-
-# 32-bit Solaris Options
-DM=32
-# Default architecture is fine for both sparc and x86 32-bit builds
-OPTIONS=
-
-# 64-bit Solaris Options
-#DM=64
-#OPTIONS=-xarch=v9
-
-
-all: libraryCaller.java libraryCaller.c
-	$(JAVAC) libraryCaller.java;					\
-	$(JAVAH) libraryCaller;						\
-	$(CC) -G -I$(JINCLUDE) -I$(JINCLUDE)/solaris -DRETURN_VALUE=0 	\
-		$(OPTIONS) libraryCaller.c 				\
-		-o lib/$(ARCH)/lib$(DM)/liblibrary.so;			\
-	$(CC) -G -I$(JINCLUDE) -I$(JINCLUDE)/solaris -DRETURN_VALUE=$(DM)\
-		$(OPTIONS) libraryCaller.c 				\
-		-o lib/$(ARCH)/lib$(DM)/lib$(DM)/liblibrary.so;
--- a/jdk/test/tools/launcher/UnicodeTest.sh	Tue Jul 20 22:17:28 2010 -0700
+++ b/jdk/test/tools/launcher/UnicodeTest.sh	Wed Jul 05 17:17:57 2017 +0200
@@ -54,7 +54,11 @@
 
 echo "creating test source files"
 "$JAVAC" -d . "${TESTSRC}"/UnicodeTest.java
-CLASS_NAME=`"$JAVA" UnicodeTest | sed -e 's@\\r@@g' `
+if [ "`uname -s | grep CYGWIN`" != "" ] ; then
+  CLASS_NAME=`"$JAVA" UnicodeTest | sed -e 's@\\r@@g' `
+else
+  CLASS_NAME=`"$JAVA" UnicodeTest`
+fi
 
 if [ "$CLASS_NAME" = "" ]
 then
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/VerifyExceptions.java	Wed Jul 05 17:17:57 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, 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 6856415
+ * @summary Checks to ensure that proper exceptions are thrown by java
+ * @compile -XDignore.symbol.file VerifyExceptions.java TestHelper.java
+ * @run main VerifyExceptions
+ */
+
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+
+public class VerifyExceptions {
+
+    static void test6856415() {
+        // No pkcs library on win-x64, so we bail out.
+        if (TestHelper.is64Bit && TestHelper.isWindows) {
+            return;
+        }
+        StringBuilder sb = new StringBuilder();
+        sb.append("public static void main(String... args) {\n");
+        sb.append("java.security.Provider p = new sun.security.pkcs11.SunPKCS11(args[0]);\n");
+        sb.append("java.security.Security.insertProviderAt(p, 1);\n");
+        sb.append("}");
+        File testJar = new File("Foo.jar");
+        testJar.delete();
+        try {
+            TestHelper.createJar(testJar, sb.toString());
+        } catch (FileNotFoundException fnfe) {
+            throw new RuntimeException(fnfe);
+        }
+        TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javacCmd,
+                "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak");
+        tr.checkNegative();
+        tr.contains("Exception in thread \"main\" java.security.AccessControlException: access denied (\"java.lang.RuntimePermission\" \"accessClassInPackage.sun.security.pkcs11\")\")");
+    }
+
+    public static void main(String... args) {
+        test6856415();
+    }
+}
Binary file jdk/test/tools/launcher/lib/i386/lib32/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/i386/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib32/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib64/lib64/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib64/liblibrary.so has changed