Merge
authorduke
Wed, 05 Jul 2017 17:02:54 +0200
changeset 4135 08d5964ec7d4
parent 4134 430015834eb3 (current diff)
parent 4129 658d1b92c389 (diff)
child 4140 9c3e48ab69a6
Merge
jdk/make/tools/fontchecker/Makefile
jdk/make/tools/src/build/tools/fontchecker/FontCheckDummy.java
jdk/make/tools/src/build/tools/fontchecker/FontChecker.java
jdk/make/tools/src/build/tools/fontchecker/FontCheckerConstants.java
jdk/make/tools/src/build/tools/fontchecker/FontFileFilter.java
jdk/make/tools/src/build/tools/fontchecker/README.txt
jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java
jdk/src/share/classes/java/nio/Direct-X-Buffer-bin.java
jdk/src/share/classes/java/nio/Direct-X-Buffer.java
jdk/src/share/classes/java/nio/Heap-X-Buffer.java
jdk/src/share/classes/java/nio/X-Buffer-bin.java
jdk/src/share/classes/java/nio/X-Buffer.java
jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java
jdk/src/share/classes/sun/misc/Version-template.java
jdk/src/share/classes/sun/tools/jconsole/Version-template.java
jdk/test/java/nio/Buffer/Basic-X.java
jdk/test/java/nio/Buffer/CopyDirect-X-Memory.java
--- a/.hgtags-top-repo	Fri Nov 06 17:26:01 2009 -0800
+++ b/.hgtags-top-repo	Wed Jul 05 17:02:54 2017 +0200
@@ -49,3 +49,4 @@
 0d7e03b426df27c21dcc44ffb9178eacd1b04f10 jdk7-b72
 3ac6dcf7823205546fbbc3d4ea59f37358d0b0d4 jdk7-b73
 2c88089b6e1c053597418099a14232182c387edc jdk7-b74
+d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75
--- a/README-builds.html	Fri Nov 06 17:26:01 2009 -0800
+++ b/README-builds.html	Wed Jul 05 17:02:54 2017 +0200
@@ -545,7 +545,11 @@
                 </li>
                 <li>
                     <strong>Windows:</strong>
-                    Make sure you start your build inside a bash/sh/ksh shell.
+                    Make sure you start your build inside a bash/sh/ksh shell
+                    and are using a <tt>make.exe</tt> utility built for that
+                    environment (a cygwin <tt>make.exe</tt> is not the same
+                    as a <tt>make.exe</tt> built for something like
+                    <a href="http://www.mkssoftware.com/">MKS</a>). 
                     <br>
                     <b>WARNING:</b> Watch out for make version 3.81, it may
                     not work due to a lack of support for MS-DOS drive letter paths
@@ -826,7 +830,8 @@
                 All OpenJDK builds require access to the previously released 
                 JDK 6, this is often called a bootstrap JDK.
                 The JDK 6 binaries can be downloaded from Sun's 
-                <a href="http://java.sun.com/javase/1.6.0/download.html" target="_blank">JDK 6 download site</a>.
+                <a href="http://java.sun.com/javase/downloads/index.jsp"
+		target="_blank">JDK 6 download site</a>.
                 For build performance reasons
                 is very important that this bootstrap JDK be made available on the
                 local disk of the machine doing the build.
--- a/corba/.hgtags	Fri Nov 06 17:26:01 2009 -0800
+++ b/corba/.hgtags	Wed Jul 05 17:02:54 2017 +0200
@@ -49,3 +49,4 @@
 c793a31209263fbb867c23c752599d85c21abb73 jdk7-b72
 b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73
 5d0cf59a3203b9f57aceebc33ae656b884987955 jdk7-b74
+0fb137085952c8e47878e240d1cb40f14de463c4 jdk7-b75
--- a/corba/make/common/Defs-linux.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/corba/make/common/Defs-linux.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -99,8 +99,16 @@
 LDFLAGS_COMMON_sparcv9  += -m64 -mcpu=v9
 CFLAGS_REQUIRED_sparc   += -m32 -mcpu=v9
 LDFLAGS_COMMON_sparc    += -m32 -mcpu=v9
-CFLAGS_REQUIRED         =  $(CFLAGS_REQUIRED_$(ARCH))
-LDFLAGS_COMMON          += $(LDFLAGS_COMMON_$(ARCH))
+ifeq ($(ZERO_BUILD), true)
+  CFLAGS_REQUIRED       =  $(ZERO_ARCHFLAG)
+  ifeq ($(ZERO_ENDIANNESS), little)
+    CFLAGS_REQUIRED     += -D_LITTLE_ENDIAN
+  endif
+  LDFLAGS_COMMON        += $(ZERO_ARCHFLAG)
+else
+  CFLAGS_REQUIRED       =  $(CFLAGS_REQUIRED_$(ARCH))
+  LDFLAGS_COMMON        += $(LDFLAGS_COMMON_$(ARCH))
+endif
 
 # Add in platform specific optimizations for all opt levels
 CC_HIGHEST_OPT += $(_OPT_$(ARCH))
@@ -196,7 +204,7 @@
 
 EXTRA_LIBS += -lc
 
-LDFLAGS_DEFS_OPTION  = -z defs
+LDFLAGS_DEFS_OPTION  = -Xlinker -z -Xlinker defs
 LDFLAGS_COMMON  += $(LDFLAGS_DEFS_OPTION)
 
 #
--- a/corba/make/common/shared/Compiler-gcc.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/corba/make/common/shared/Compiler-gcc.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -70,6 +70,11 @@
   else
     CXX            = $(COMPILER_PATH)g++
   endif
+  ifeq ($(ZERO_BUILD), true)
+    # zero
+    REQUIRED_CC_VER = 3.2
+    REQUIRED_GCC_VER = 3.2.*
+  else
   ifneq ("$(findstring sparc,$(ARCH))", "")
     # sparc or sparcv9
     REQUIRED_CC_VER = 4.0
@@ -88,6 +93,7 @@
   endif
   endif
   endif
+  endif
   # Option used to create a shared library
   SHARED_LIBRARY_FLAG = -shared -mimpure-text
   SUN_COMP_VER := $(shell $(CC) --verbose 2>&1 )
--- a/hotspot/.hgtags	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/.hgtags	Wed Jul 05 17:02:54 2017 +0200
@@ -49,3 +49,4 @@
 a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
 faf94d94786b621f8e13cbcc941ca69c6d967c3f jdk7-b73
 f4b900403d6e4b0af51447bd13bbe23fe3a1dac7 jdk7-b74
+d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75
--- a/hotspot/agent/make/saenv.sh	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/make/saenv.sh	Wed Jul 05 17:02:54 2017 +0200
@@ -48,8 +48,16 @@
      CPU=i386
    fi
 else
-   LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so
-   export LD_AUDIT_32
+   # configure audit helper library if SA_ALTROOT is set
+   if [ -n "$SA_ALTROOT" ]; then
+     LD_AUDIT_32=$STARTDIR/../src/os/solaris/proc/`uname -p`/libsaproc_audit.so
+     export LD_AUDIT_32
+     if [ ! -f $LD_AUDIT_32 ]; then
+       echo "SA_ALTROOT is set and can't find libsaproc_audit.so."
+       echo "Make sure to build it with 'make natives'."
+       exit 1
+     fi
+   fi
    SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/`uname -p`:$STARTDIR/solaris/`uname -p`
    OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
    CPU=sparc
--- a/hotspot/agent/make/saenv64.sh	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/make/saenv64.sh	Wed Jul 05 17:02:54 2017 +0200
@@ -43,8 +43,16 @@
   fi
 fi
 
-LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so
-export LD_AUDIT_64
+# configure audit helper library if SA_ALTROOT is set
+if [ -n "$SA_ALTROOT" ]; then
+  LD_AUDIT_64=$STARTDIR/../src/os/solaris/proc/$CPU/libsaproc_audit.so
+  export LD_AUDIT_64
+  if [ ! -f $LD_AUDIT_64 ]; then
+      echo "SA_ALTROOT is set and can't find libsaproc_audit.so."
+      echo "Make sure to build it with 'make natives'."
+      exit 1
+  fi
+fi
 SA_LIBPATH=$STARTDIR/../src/os/solaris/proc/$CPU:$STARTDIR/solaris/$CPU
 
 OPTIONS="-Dsa.library.path=$SA_LIBPATH -Dsun.jvm.hotspot.debugger.useProcDebugger"
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Wed Jul 05 17:02:54 2017 +0200
@@ -926,6 +926,28 @@
                 }
             }
         },
+        new Command("dumpcodecache", "dumpcodecache", false) {
+            public void doit(Tokens t) {
+                if (t.countTokens() != 0) {
+                    usage();
+                } else {
+                    final PrintStream fout = out;
+                    final HTMLGenerator gen = new HTMLGenerator(false);
+                    CodeCacheVisitor v = new CodeCacheVisitor() {
+                            public void prologue(Address start, Address end) {
+                            }
+                            public void visit(CodeBlob blob) {
+                                fout.println(gen.genHTML(blob.instructionsBegin()));
+                            }
+                            public void epilogue() {
+                            }
+
+
+                        };
+                    VM.getVM().getCodeCache().iterate(v);
+                }
+            }
+        },
         new Command("where", "where { -a | id }", false) {
             public void doit(Tokens t) {
                 if (t.countTokens() != 1) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java	Wed Jul 05 17:02:54 2017 +0200
@@ -173,7 +173,8 @@
     CodeBlob lastBlob = null;
     while (ptr != null && ptr.lessThan(end)) {
       try {
-        CodeBlob blob = findBlobUnsafe(ptr);
+        // Use findStart to get a pointer inside blob other findBlob asserts
+        CodeBlob blob = findBlobUnsafe(heap.findStart(ptr));
         if (blob != null) {
           visitor.visit(blob);
           if (blob == lastBlob) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Wed Jul 05 17:02:54 2017 +0200
@@ -42,7 +42,7 @@
   /** To support simple linked-list chaining of nmethods */
   private static AddressField  osrLinkField;
   private static AddressField  scavengeRootLinkField;
-  private static CIntegerField scavengeRootStateField;
+  private static JByteField    scavengeRootStateField;
 
   /** Offsets for different nmethod parts */
   private static CIntegerField exceptionOffsetField;
@@ -92,7 +92,7 @@
     entryBCIField               = type.getCIntegerField("_entry_bci");
     osrLinkField                = type.getAddressField("_osr_link");
     scavengeRootLinkField       = type.getAddressField("_scavenge_root_link");
-    scavengeRootStateField      = type.getCIntegerField("_scavenge_root_state");
+    scavengeRootStateField      = type.getJByteField("_scavenge_root_state");
 
     exceptionOffsetField        = type.getCIntegerField("_exception_offset");
     deoptOffsetField            = type.getCIntegerField("_deoptimize_offset");
@@ -274,7 +274,7 @@
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(pd != null, "scope must be present");
     }
-    return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute());
+    return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
   }
 
   /** This is only for use by the debugging system, and is only
@@ -306,11 +306,11 @@
   public ScopeDesc getScopeDescNearDbg(Address pc) {
     PCDesc pd = getPCDescNearDbg(pc);
     if (pd == null) return null;
-    return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute());
+    return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
   }
 
-  public Map/*<Address, PcDesc>*/ getSafepoints() {
-    Map safepoints = new HashMap(); // Map<Address, PcDesc>
+  public Map/*<Address, PCDesc>*/ getSafepoints() {
+    Map safepoints = new HashMap(); // Map<Address, PCDesc>
     sun.jvm.hotspot.debugger.Address p = null;
     for (p = scopesPCsBegin(); p.lessThan(scopesPCsEnd());
          p = p.addOffsetTo(pcDescSize)) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java	Wed Jul 05 17:02:54 2017 +0200
@@ -36,6 +36,7 @@
 public class PCDesc extends VMObject {
   private static CIntegerField pcOffsetField;
   private static CIntegerField scopeDecodeOffsetField;
+  private static CIntegerField objDecodeOffsetField;
   private static CIntegerField pcFlagsField;
 
   static {
@@ -51,6 +52,7 @@
 
     pcOffsetField          = type.getCIntegerField("_pc_offset");
     scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset");
+    objDecodeOffsetField   = type.getCIntegerField("_obj_decode_offset");
     pcFlagsField           = type.getCIntegerField("_flags");
   }
 
@@ -68,6 +70,10 @@
     return ((int) scopeDecodeOffsetField.getValue(addr));
   }
 
+  public int getObjDecodeOffset() {
+    return ((int) objDecodeOffsetField.getValue(addr));
+  }
+
   public Address getRealPC(NMethod code) {
     return code.instructionsBegin().addOffsetTo(getPCOffset());
   }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java	Wed Jul 05 17:02:54 2017 +0200
@@ -51,11 +51,10 @@
   /** Scalar replaced bjects pool */
   private List    objects; // ArrayList<ScopeValue>
 
-
-  public ScopeDesc(NMethod code, int decodeOffset, boolean reexecute) {
+  private ScopeDesc(NMethod code, int decodeOffset, List objects, boolean reexecute) {
     this.code = code;
     this.decodeOffset = decodeOffset;
-    this.objects      = decodeObjectValues(DebugInformationRecorder.SERIALIZED_NULL);
+    this.objects      = objects;
     this.reexecute    = reexecute;
 
     // Decode header
@@ -108,7 +107,7 @@
     return decodeMonitorValues(monitorsDecodeOffset);
   }
 
-  /** Returns a List&lt;MonitorValue&gt; */
+  /** Returns a List&lt;ObjectValue&gt; */
   public List getObjects() {
     return objects;
   }
@@ -119,7 +118,7 @@
       return null;
     }
 
-    return new ScopeDesc(code, senderDecodeOffset, false);
+    return new ScopeDesc(code, senderDecodeOffset, objects, false);
   }
 
   /** Returns where the scope was decoded */
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Wed Jul 05 17:02:54 2017 +0200
@@ -807,6 +807,9 @@
             Interpreter interp = VM.getVM().getInterpreter();
             if (interp.contains(pc)) {
                InterpreterCodelet codelet = interp.getCodeletContaining(pc);
+               if (codelet == null) {
+                  return "Unknown location in the Interpreter: " + pc;
+               }
                return genHTML(codelet);
             }
             return genHTML(blob);
@@ -969,16 +972,24 @@
    }
 
    protected String genSafepointInfo(NMethod nm, PCDesc pcDesc) {
-      ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm));
-      Formatter buf = new Formatter(genHTML);
-      Formatter tabs = new Formatter(genHTML);
+       ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm));
+       Formatter buf = new Formatter(genHTML);
+       Formatter tabs = new Formatter(genHTML);
+       tabs.append(tab + tab + tab); // Initial indent for debug info
+
+       buf.beginTag("pre");
+       genScope(buf, tabs, sd);
 
-      buf.beginTag("pre");
-      genScope(buf, tabs, sd);
-      buf.endTag("pre");
-      buf.append(genOopMapInfo(nm, pcDesc));
+       // Reset indent for scalar replaced objects
+       tabs = new Formatter(genHTML);
+       tabs.append(tab + tab + tab); // Initial indent for debug info
 
-      return buf.toString();
+       genScObjInfo(buf, tabs, sd);
+       buf.endTag("pre");
+
+       buf.append(genOopMapInfo(nm, pcDesc));
+
+       return buf.toString();
    }
 
     protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) {
@@ -1022,8 +1033,95 @@
             buf.append(genHTMLForMonitors(sd, monitors));
         }
 
+        buf.br();
         tabs.append(tab);
-        buf.br();
+    }
+
+    protected void genScObjInfo(Formatter buf, Formatter tabs, ScopeDesc sd) {
+        if (sd == null) {
+            return;
+        }
+
+        List objects = sd.getObjects();
+        if (objects == null) {
+            return;
+        }
+        int length = objects.size();
+        for (int i = 0; i < length; i++) {
+            buf.append(tabs);
+            ObjectValue ov = (ObjectValue)objects.get(i);
+            buf.append("ScObj" + i);
+            ScopeValue sv = ov.getKlass();
+            if (Assert.ASSERTS_ENABLED) {
+                Assert.that(sv.isConstantOop(), "scalar replaced object klass must be constant oop");
+            }
+            ConstantOopReadValue klv = (ConstantOopReadValue)sv;
+            OopHandle klHandle = klv.getValue();
+            if (Assert.ASSERTS_ENABLED) {
+                Assert.that(klHandle != null, "scalar replaced object klass must be not NULL");
+            }
+            Oop obj = VM.getVM().getObjectHeap().newOop(klHandle);
+            if (obj instanceof InstanceKlass) {
+                InstanceKlass kls = (InstanceKlass) obj;
+                buf.append(" " + kls.getName().asString() + "={");
+                int flen = ov.fieldsSize();
+
+                TypeArray klfields = kls.getFields();
+                int klen = (int) klfields.getLength();
+
+                ConstantPool cp = kls.getConstants();
+                int findex = 0;
+                for (int index = 0; index < klen; index += kls.NEXT_OFFSET) {
+                    int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET);
+                    int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET);
+                    AccessFlags access = new AccessFlags(accsFlags);
+                    if (!access.isStatic()) {
+                        ScopeValue svf = ov.getFieldAt(findex++);
+                        String    fstr = scopeValueAsString(sd, svf);
+                        Symbol f_name  = cp.getSymbolAt(nameIndex);
+                        buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")");
+                    }
+                }
+                buf.append(" }");
+            } else {
+                buf.append(" ");
+                int flen = ov.fieldsSize();
+                if (obj instanceof TypeArrayKlass) {
+                    TypeArrayKlass kls = (TypeArrayKlass) obj;
+                    buf.append(kls.getElementTypeName() + "[" + flen + "]");
+                } else if (obj instanceof ObjArrayKlass) {
+                    ObjArrayKlass kls = (ObjArrayKlass) obj;
+                    Klass elobj = kls.getBottomKlass();
+                    if (elobj instanceof InstanceKlass) {
+                        buf.append(elobj.getName().asString());
+                    } else if (elobj instanceof TypeArrayKlass) {
+                        TypeArrayKlass elkls = (TypeArrayKlass) elobj;
+                        buf.append(elkls.getElementTypeName());
+                    } else {
+                        if (Assert.ASSERTS_ENABLED) {
+                            Assert.that(false, "unknown scalar replaced object klass!");
+                        }
+                    }
+                    buf.append("[" + flen + "]");
+                    int ndim = (int) kls.getDimension();
+                    while (--ndim > 0) {
+                        buf.append("[]");
+                    }
+                } else {
+                    if (Assert.ASSERTS_ENABLED) {
+                        Assert.that(false, "unknown scalar replaced object klass!");
+                    }
+                }
+                buf.append("={");
+                for (int findex = 0; findex < flen; findex++) {
+                    ScopeValue svf = ov.getFieldAt(findex);
+                    String fstr = scopeValueAsString(sd, svf);
+                    buf.append(" [" + findex + "]=(#" + fstr + ")");
+                }
+                buf.append(" }");
+            }
+            buf.br();
+        }
     }
 
    protected String genHTMLForOopMap(OopMap map) {
@@ -1037,8 +1135,6 @@
             tmpBuf.beginTag("tr");
             tmpBuf.beginTag("td");
             tmpBuf.append(type);
-            tmpBuf.endTag("td");
-            tmpBuf.endTag("tr");
             for (; ! oms.isDone(); oms.next()) {
                OopMapValue omv = oms.getCurrent();
                if (omv == null) {
@@ -1048,7 +1144,7 @@
                VMReg vmReg = omv.getReg();
                int reg = vmReg.getValue();
                if (reg < stack0) {
-                  tmpBuf.append(VMRegImpl.getRegisterName(vmReg.getValue()));
+                  tmpBuf.append(VMRegImpl.getRegisterName(reg));
                } else {
                   tmpBuf.append('[');
                   tmpBuf.append(Integer.toString((reg - stack0) * 4));
@@ -1058,7 +1154,13 @@
                   tmpBuf.append(" = ");
                   VMReg vmContentReg = omv.getContentReg();
                   int contentReg = vmContentReg.getValue();
-                  tmpBuf.append(VMRegImpl.getRegisterName(vmContentReg.getValue()));
+                  if (contentReg < stack0) {
+                     tmpBuf.append(VMRegImpl.getRegisterName(contentReg));
+                  } else {
+                     tmpBuf.append('[');
+                     tmpBuf.append(Integer.toString((contentReg - stack0) * 4));
+                     tmpBuf.append(']');
+                  }
                }
                tmpBuf.append(spaces);
             }
@@ -1072,19 +1174,19 @@
 
       OopMapValueIterator omvIterator = new OopMapValueIterator();
       OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE);
-      buf.append(omvIterator.iterate(oms, "Oop:", false));
+      buf.append(omvIterator.iterate(oms, "Oops:", false));
+
+      oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
+      buf.append(omvIterator.iterate(oms, "narrowOops:", false));
 
       oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
-      buf.append(omvIterator.iterate(oms, "Value:", false));
-
-      oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
-      buf.append(omvIterator.iterate(oms, "Oop:", false));
+      buf.append(omvIterator.iterate(oms, "Values:", false));
 
       oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
       buf.append(omvIterator.iterate(oms, "Callee saved:",  true));
 
       oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE);
-      buf.append(omvIterator.iterate(oms, "Derived oop:", true));
+      buf.append(omvIterator.iterate(oms, "Derived oops:", true));
 
       buf.endTag("table");
       return buf.toString();
@@ -1093,6 +1195,8 @@
 
    protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
       OopMapSet mapSet = nmethod.getOopMaps();
+      if (mapSet == null || (mapSet.getSize() <= 0))
+        return "";
       int pcOffset = pcDesc.getPCOffset();
       OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
       if (map == null) {
@@ -1106,6 +1210,7 @@
      Formatter buf = new Formatter(genHTML);
      buf.beginTag("pre");
      buf.append("OopMap: ");
+     buf.br();
      buf.append(genHTMLForOopMap(map));
      buf.endTag("pre");
 
@@ -1154,7 +1259,7 @@
       return buf.toString();
    }
 
-   private String scopeValueAsString(ScopeValue sv) {
+   private String scopeValueAsString(ScopeDesc sd, ScopeValue sv) {
       Formatter buf = new Formatter(genHTML);
       if (sv.isConstantInt()) {
          buf.append("int ");
@@ -1187,6 +1292,11 @@
          } else {
             buf.append("null");
          }
+      } else if (sv.isObject()) {
+         ObjectValue ov = (ObjectValue)sv;
+         buf.append("#ScObj" + sd.getObjects().indexOf(ov));
+      } else {
+         buf.append("unknown scope value " + sv);
       }
       return buf.toString();
    }
@@ -1219,7 +1329,7 @@
          }
 
          buf.append(", ");
-         buf.append(scopeValueAsString(sv));
+         buf.append(scopeValueAsString(sd, sv));
          buf.append(") ");
       }
 
@@ -1246,7 +1356,7 @@
          buf.append("(owner = ");
          ScopeValue owner = mv.owner();
          if (owner != null) {
-            buf.append(scopeValueAsString(owner));
+            buf.append(scopeValueAsString(sd, owner));
          } else {
             buf.append("null");
          }
@@ -1324,11 +1434,11 @@
                   buf.append(instr.asString(currentPc, symFinder));
                }
 
+               buf.br();
                if (isSafepoint && !prevWasCall) {
-                  buf.append(genSafepointInfo(nmethod, pcDesc));
+                 buf.append(genSafepointInfo(nmethod, pcDesc));
                }
 
-               buf.br();
                prevWasCall = instr.isCall();
             }
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Wed Jul 05 17:02:54 2017 +0200
@@ -1047,7 +1047,7 @@
    } else {
       // some type names have ':'. replace to make it as a 
       // JavaScript identifier
-      tmp.name = tmp.name.replace(':', '_');
+      tmp.name = tmp.name.replace(':', '_').replace('<', '_').replace('>', '_').replace('*', '_').replace(' ', '_');
       eval("function read" + tmp.name + "(addr) {" +
            "   return readVMType('" + tmp.name + "', addr);}"); 
       eval("function print" + tmp.name + "(addr) {" + 
--- a/hotspot/make/hotspot_version	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/make/hotspot_version	Wed Jul 05 17:02:54 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=17
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=04
+HS_BUILD_NUMBER=05
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -3213,9 +3213,8 @@
   Register        Oreturn0           = O0;
   Register        Oreturn1           = O1;
   Register        O2UnrollBlock      = O2;
-  Register        O3tmp              = O3;
-  Register        I5exception_tmp    = I5;
-  Register        G4exception_tmp    = G4_scratch;
+  Register        L0deopt_mode       = L0;
+  Register        G4deopt_mode       = G4_scratch;
   int             frame_size_words;
   Address         saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS);
 #if !defined(_LP64) && defined(COMPILER2)
@@ -3265,7 +3264,7 @@
 
   map = RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
   __ ba(false, cont);
-  __ delayed()->mov(Deoptimization::Unpack_deopt, I5exception_tmp);
+  __ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode);
 
   int exception_offset = __ offset() - start;
 
@@ -3316,7 +3315,7 @@
 #endif
 
   __ ba(false, cont);
-  __ delayed()->mov(Deoptimization::Unpack_exception, I5exception_tmp);;
+  __ delayed()->mov(Deoptimization::Unpack_exception, L0deopt_mode);;
 
   //
   // Reexecute entry, similar to c2 uncommon trap
@@ -3326,7 +3325,7 @@
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
-  __ mov(Deoptimization::Unpack_reexecute, I5exception_tmp);
+  __ mov(Deoptimization::Unpack_reexecute, L0deopt_mode);
 
   __ bind(cont);
 
@@ -3349,14 +3348,14 @@
   // NOTE: we know that only O0/O1 will be reloaded by restore_result_registers
   // so this move will survive
 
-  __ mov(I5exception_tmp, G4exception_tmp);
+  __ mov(L0deopt_mode, G4deopt_mode);
 
   __ mov(O0, O2UnrollBlock->after_save());
 
   RegisterSaver::restore_result_registers(masm);
 
   Label noException;
-  __ cmp(G4exception_tmp, Deoptimization::Unpack_exception);   // Was exception pending?
+  __ cmp(G4deopt_mode, Deoptimization::Unpack_exception);   // Was exception pending?
   __ br(Assembler::notEqual, false, Assembler::pt, noException);
   __ delayed()->nop();
 
@@ -3390,10 +3389,10 @@
   }
 #endif
   __ set_last_Java_frame(SP, noreg);
-  __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4exception_tmp);
+  __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4deopt_mode);
 #else
   // LP64 uses g4 in set_last_Java_frame
-  __ mov(G4exception_tmp, O1);
+  __ mov(G4deopt_mode, O1);
   __ set_last_Java_frame(SP, G0);
   __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O1);
 #endif
@@ -3446,7 +3445,6 @@
 #endif
   MacroAssembler* masm               = new MacroAssembler(&buffer);
   Register        O2UnrollBlock      = O2;
-  Register        O3tmp              = O3;
   Register        O2klass_index      = O2;
 
   //
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 17:02:54 2017 +0200
@@ -9419,8 +9419,9 @@
   // x |= (x >> 8);
   // x |= (x >> 16);
   // return (WORDBITS - popc(x));
-  format %{ "SRL     $src,1,$dst\t! count leading zeros (int)\n\t"
-            "OR      $src,$tmp,$dst\n\t"
+  format %{ "SRL     $src,1,$tmp\t! count leading zeros (int)\n\t"
+            "SRL     $src,0,$dst\t! 32-bit zero extend\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
             "SRL     $dst,2,$tmp\n\t"
             "OR      $dst,$tmp,$dst\n\t"
             "SRL     $dst,4,$tmp\n\t"
@@ -9437,7 +9438,8 @@
     Register Rsrc = $src$$Register;
     Register Rtmp = $tmp$$Register;
     __ srl(Rsrc, 1, Rtmp);
-    __ or3(Rsrc, Rtmp, Rdst);
+    __ srl(Rsrc, 0, Rdst);
+    __ or3(Rdst, Rtmp, Rdst);
     __ srl(Rdst, 2, Rtmp);
     __ or3(Rdst, Rtmp, Rdst);
     __ srl(Rdst, 4, Rtmp);
@@ -9465,7 +9467,7 @@
   // x |= (x >> 16);
   // x |= (x >> 32);
   // return (WORDBITS - popc(x));
-  format %{ "SRLX    $src,1,$dst\t! count leading zeros (long)\n\t"
+  format %{ "SRLX    $src,1,$tmp\t! count leading zeros (long)\n\t"
             "OR      $src,$tmp,$dst\n\t"
             "SRLX    $dst,2,$tmp\n\t"
             "OR      $dst,$tmp,$dst\n\t"
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -8214,6 +8214,15 @@
   }
 }
 
+// Used for storing NULLs.
+void MacroAssembler::store_heap_oop_null(Address dst) {
+  if (UseCompressedOops) {
+    movl(dst, (int32_t)NULL_WORD);
+  } else {
+    movslq(dst, (int32_t)NULL_WORD);
+  }
+}
+
 // Algorithm must match oop.inline.hpp encode_heap_oop.
 void MacroAssembler::encode_heap_oop(Register r) {
   assert (UseCompressedOops, "should be compressed");
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -1682,6 +1682,17 @@
 
   void load_heap_oop(Register dst, Address src);
   void store_heap_oop(Address dst, Register src);
+
+  // This dummy is to prevent a call to store_heap_oop from
+  // converting a zero (like NULL) into a Register by giving
+  // the compiler two choices it can't resolve
+
+  void store_heap_oop(Address dst, void* dummy);
+
+  // Used for storing NULL. All other oop constants should be
+  // stored using routines that take a jobject.
+  void store_heap_oop_null(Address dst);
+
   void encode_heap_oop(Register r);
   void decode_heap_oop(Register r);
   void encode_heap_oop_not_null(Register r);
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -271,9 +271,15 @@
 void trace_method_handle_stub(const char* adaptername,
                               oopDesc* mh,
                               intptr_t* entry_sp,
-                              intptr_t* saved_sp) {
+                              intptr_t* saved_sp,
+                              intptr_t* saved_bp) {
   // called as a leaf from native code: do not block the JVM!
-  printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp);
+  intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
+  intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
+  printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n",
+         adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
+  if (last_sp != saved_sp)
+    printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
 }
 #endif //PRODUCT
 
@@ -293,6 +299,10 @@
   Register rbx_temp    = rbx;
   Register rdx_temp    = rdx;
 
+  // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls)
+  // and gen_c2i_adapter (from compiled calls):
+  Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi);
+
   guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
 
   // some handy addresses
@@ -315,6 +325,8 @@
     assert(tag_offset = wordSize, "stack grows as expected");
   }
 
+  const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
+
   if (have_entry(ek)) {
     __ nop();                   // empty stubs make SG sick
     return;
@@ -328,45 +340,65 @@
     __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi);
     __ lea(rax, Address(rsp, wordSize*6)); // entry_sp
     // arguments:
+    __ push(rbp);               // interpreter frame pointer
     __ push(rsi);               // saved_sp
     __ push(rax);               // entry_sp
     __ push(rcx);               // mh
     __ push(rcx);
     __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek));
-    __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4);
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5);
     __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax);
   }
 #endif //PRODUCT
 
   switch ((int) ek) {
-  case _check_mtype:
+  case _raise_exception:
     {
-      // this stub is special, because it requires a live mtype argument
-      Register rax_mtype = rax;
+      // Not a real MH entry, but rather shared code for raising an exception.
+      // Extra local arguments are pushed on stack, as required type at TOS+8,
+      // failing object (or NULL) at TOS+4, failing bytecode type at TOS.
+      // Beyond those local arguments are the PC, of course.
+      Register rdx_code = rdx_temp;
+      Register rcx_fail = rcx_recv;
+      Register rax_want = rax_argslot;
+      Register rdi_pc   = rdi;
+      __ pop(rdx_code);  // TOS+0
+      __ pop(rcx_fail);  // TOS+4
+      __ pop(rax_want);  // TOS+8
+      __ pop(rdi_pc);    // caller PC
 
-      // emit WrongMethodType path first, to enable jccb back-branch
-      Label wrong_method_type;
-      __ bind(wrong_method_type);
-      __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type]));
-      __ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
-      __ hlt();
+      __ mov(rsp, rsi);   // cut the stack back to where the caller started
 
-      interp_entry = __ pc();
-      __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
-      // now rax_mtype is dead; subsequent stubs will use it as a temp
-
-      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-    }
-    break;
+      // Repush the arguments as if coming from the interpreter.
+      if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_INT));
+      __ push(rdx_code);
+      if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_OBJECT));
+      __ push(rcx_fail);
+      if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_OBJECT));
+      __ push(rax_want);
 
-  case _wrong_method_type:
-    {
-      // this stub is special, because it requires a live mtype argument
-      Register rax_mtype = rax;
+      Register rbx_method = rbx_temp;
+      Label no_method;
+      // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
+      __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
+      __ testptr(rbx_method, rbx_method);
+      __ jcc(Assembler::zero, no_method);
+      int jobject_oop_offset = 0;
+      __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset));  // dereference the jobject
+      __ testptr(rbx_method, rbx_method);
+      __ jcc(Assembler::zero, no_method);
+      __ verify_oop(rbx_method);
+      __ push(rdi_pc);          // and restore caller PC
+      __ jmp(rbx_method_fie);
 
-      interp_entry = __ pc();
-      __ push(rax_mtype);       // required mtype
-      __ push(rcx_recv);        // random mh (1st stacked argument)
+      // If we get here, the Java runtime did not do its job of creating the exception.
+      // Do something that is at least causes a valid throw from the interpreter.
+      __ bind(no_method);
+      __ pop(rax_want);
+      if (TaggedStackInterpreter)  __ pop(rcx_fail);
+      __ pop(rcx_fail);
+      __ push(rax_want);
+      __ push(rcx_fail);
       __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
     }
     break;
@@ -442,7 +474,7 @@
       __ load_klass(rax_klass, rcx_recv);
       __ verify_oop(rax_klass);
 
-      Register rcx_temp   = rcx_recv;
+      Register rdi_temp   = rdi;
       Register rbx_method = rbx_index;
 
       // get interface klass
@@ -451,7 +483,7 @@
       __ lookup_interface_method(rax_klass, rdx_intf,
                                  // note: next two args must be the same:
                                  rbx_index, rbx_method,
-                                 rcx_temp,
+                                 rdi_temp,
                                  no_such_interface);
 
       __ verify_oop(rbx_method);
@@ -461,7 +493,10 @@
       __ bind(no_such_interface);
       // Throw an exception.
       // For historical reasons, it will be IncompatibleClassChangeError.
-      __ should_not_reach_here(); // %%% FIXME NYI
+      __ pushptr(Address(rdx_intf, java_mirror_offset));  // required interface
+      __ push(rcx_recv);        // bad receiver
+      __ push((int)Bytecodes::_invokeinterface);  // who is complaining?
+      __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
     }
     break;
 
@@ -524,6 +559,7 @@
     break;
 
   case _adapter_retype_only:
+  case _adapter_retype_raw:
     // immediately jump to the next MH layer:
     __ movptr(rcx_recv, rcx_mh_vmtarget);
     __ verify_oop(rcx_recv);
@@ -545,10 +581,6 @@
       __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
       __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
 
-      // get the new MH:
-      __ movptr(rcx_recv, rcx_mh_vmtarget);
-      // (now we are done with the old MH)
-
       Label done;
       __ movptr(rdx_temp, vmarg);
       __ testl(rdx_temp, rdx_temp);
@@ -558,17 +590,23 @@
       // live at this point:
       // - rbx_klass:  klass required by the target method
       // - rdx_temp:   argument klass to test
-      // - rcx_recv:   method handle to invoke (after cast succeeds)
+      // - rcx_recv:   adapter method handle
       __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
 
       // If we get here, the type check failed!
       // Call the wrong_method_type stub, passing the failing argument type in rax.
       Register rax_mtype = rax_argslot;
-      __ push(rbx_klass);       // missed klass (required type)
-      __ push(rdx_temp);        // bad actual type (1st stacked argument)
-      __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
+      __ movl(rax_argslot, rcx_amh_vmargslot);  // reload argslot field
+      __ movptr(rdx_temp, vmarg);
+
+      __ pushptr(rcx_amh_argument); // required class
+      __ push(rdx_temp);            // bad object
+      __ push((int)Bytecodes::_checkcast);  // who is complaining?
+      __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
 
       __ bind(done);
+      // get the new MH:
+      __ movptr(rcx_recv, rcx_mh_vmtarget);
       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
     }
     break;
@@ -1107,11 +1145,17 @@
 
       __ bind(bad_array_klass);
       UNPUSH_RSI_RDI;
-      __ stop("bad array klass NYI");
+      __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type
+      __ pushptr(vmarg);                // bad array
+      __ push((int)Bytecodes::_aaload); // who is complaining?
+      __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
 
       __ bind(bad_array_length);
       UNPUSH_RSI_RDI;
-      __ stop("bad array length NYI");
+      __ push(rcx_recv);        // AMH requiring a certain length
+      __ pushptr(vmarg);        // bad array
+      __ push((int)Bytecodes::_arraylength); // who is complaining?
+      __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
 
 #undef UNPUSH_RSI_RDI
     }
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -92,8 +92,7 @@
   return entry;
 }
 
-// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
-// pc at TOS (just for debugging)
+// Arguments are: required type at TOS+4, failing object (or NULL) at TOS.
 address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
   address entry = __ pc();
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -139,7 +139,7 @@
         }
         __ g1_write_barrier_pre(rdx, r8, rbx, val != noreg);
         if (val == noreg) {
-          __ store_heap_oop(Address(rdx, 0), NULL_WORD);
+          __ store_heap_oop_null(Address(rdx, 0));
         } else {
           __ store_heap_oop(Address(rdx, 0), val);
           __ g1_write_barrier_post(rdx, val, r8, rbx);
@@ -152,7 +152,7 @@
     case BarrierSet::CardTableExtension:
       {
         if (val == noreg) {
-          __ store_heap_oop(obj, NULL_WORD);
+          __ store_heap_oop_null(obj);
         } else {
           __ store_heap_oop(obj, val);
           // flatten object address if needed
@@ -168,7 +168,7 @@
     case BarrierSet::ModRef:
     case BarrierSet::Other:
       if (val == noreg) {
-        __ store_heap_oop(obj, NULL_WORD);
+        __ store_heap_oop_null(obj);
       } else {
         __ store_heap_oop(obj, val);
       }
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -903,19 +903,20 @@
   // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
   enum {
     OP_RETYPE_ONLY   = 0x0, // no argument changes; straight retype
-    OP_CHECK_CAST    = 0x1, // ref-to-ref conversion; requires a Class argument
-    OP_PRIM_TO_PRIM  = 0x2, // converts from one primitive to another
-    OP_REF_TO_PRIM   = 0x3, // unboxes a wrapper to produce a primitive
-    OP_PRIM_TO_REF   = 0x4, // boxes a primitive into a wrapper (NYI)
-    OP_SWAP_ARGS     = 0x5, // swap arguments (vminfo is 2nd arg)
-    OP_ROT_ARGS      = 0x6, // rotate arguments (vminfo is displaced arg)
-    OP_DUP_ARGS      = 0x7, // duplicates one or more arguments (at TOS)
-    OP_DROP_ARGS     = 0x8, // remove one or more argument slots
-    OP_COLLECT_ARGS  = 0x9, // combine one or more arguments into a varargs (NYI)
-    OP_SPREAD_ARGS   = 0xA, // expand in place a varargs array (of known size)
-    OP_FLYBY         = 0xB, // operate first on reified argument list (NYI)
-    OP_RICOCHET      = 0xC, // run an adapter chain on the return value (NYI)
-    CONV_OP_LIMIT    = 0xD, // limit of CONV_OP enumeration
+    OP_RETYPE_RAW    = 0x1, // straight retype, trusted (void->int, Object->T)
+    OP_CHECK_CAST    = 0x2, // ref-to-ref conversion; requires a Class argument
+    OP_PRIM_TO_PRIM  = 0x3, // converts from one primitive to another
+    OP_REF_TO_PRIM   = 0x4, // unboxes a wrapper to produce a primitive
+    OP_PRIM_TO_REF   = 0x5, // boxes a primitive into a wrapper (NYI)
+    OP_SWAP_ARGS     = 0x6, // swap arguments (vminfo is 2nd arg)
+    OP_ROT_ARGS      = 0x7, // rotate arguments (vminfo is displaced arg)
+    OP_DUP_ARGS      = 0x8, // duplicates one or more arguments (at TOS)
+    OP_DROP_ARGS     = 0x9, // remove one or more argument slots
+    OP_COLLECT_ARGS  = 0xA, // combine one or more arguments into a varargs (NYI)
+    OP_SPREAD_ARGS   = 0xB, // expand in place a varargs array (of known size)
+    OP_FLYBY         = 0xC, // operate first on reified argument list (NYI)
+    OP_RICOCHET      = 0xD, // run an adapter chain on the return value (NYI)
+    CONV_OP_LIMIT    = 0xE, // limit of CONV_OP enumeration
 
     CONV_OP_MASK     = 0xF00, // this nybble contains the conversion op field
     CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -1963,7 +1963,7 @@
   WKID meth_group_end   = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
   initialize_wk_klasses_until(meth_group_start, scan, CHECK);
   if (EnableMethodHandles) {
-    initialize_wk_klasses_through(meth_group_start, scan, CHECK);
+    initialize_wk_klasses_through(meth_group_end, scan, CHECK);
   }
   if (_well_known_klasses[meth_group_start] == NULL) {
     // Skip the rest of the method handle classes, if MethodHandle is not loaded.
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -667,39 +667,6 @@
 // Called at the first checkpoint.
 //
 
-#define PRINT_REACHABLE_AT_INITIAL_MARK 0
-#if PRINT_REACHABLE_AT_INITIAL_MARK
-static FILE* reachable_file = NULL;
-
-class PrintReachableClosure: public OopsInGenClosure {
-  CMBitMap* _bm;
-  int _level;
-public:
-  PrintReachableClosure(CMBitMap* bm) :
-    _bm(bm), _level(0) {
-    guarantee(reachable_file != NULL, "pre-condition");
-  }
-  void do_oop(oop* p) {
-    oop obj = *p;
-    HeapWord* obj_addr = (HeapWord*)obj;
-    if (obj == NULL) return;
-    fprintf(reachable_file, "%d: "PTR_FORMAT" -> "PTR_FORMAT" (%d)\n",
-            _level, p, (void*) obj, _bm->isMarked(obj_addr));
-    if (!_bm->isMarked(obj_addr)) {
-      _bm->mark(obj_addr);
-      _level++;
-      obj->oop_iterate(this);
-      _level--;
-    }
-  }
-};
-#endif // PRINT_REACHABLE_AT_INITIAL_MARK
-
-#define SEND_HEAP_DUMP_TO_FILE 0
-#if SEND_HEAP_DUMP_TO_FILE
-static FILE* heap_dump_file = NULL;
-#endif // SEND_HEAP_DUMP_TO_FILE
-
 void ConcurrentMark::clearNextBitmap() {
    guarantee(!G1CollectedHeap::heap()->mark_in_progress(), "Precondition.");
 
@@ -737,32 +704,9 @@
 
   _has_aborted = false;
 
-  // Find all the reachable objects...
-#if PRINT_REACHABLE_AT_INITIAL_MARK
-  guarantee(reachable_file == NULL, "Protocol");
-  char fn_buf[100];
-  sprintf(fn_buf, "/tmp/reachable.txt.%d", os::current_process_id());
-  reachable_file = fopen(fn_buf, "w");
-  // clear the mark bitmap (no grey objects to start with)
-  _nextMarkBitMap->clearAll();
-  PrintReachableClosure prcl(_nextMarkBitMap);
-  g1h->process_strong_roots(true,    // activate StrongRootsScope
-                            false,   // fake perm gen collection
-                            SharedHeap::SO_AllClasses,
-                            &prcl, // Regular roots
-                            NULL,  // do not visit active blobs
-                            &prcl    // Perm Gen Roots
-                            );
-  // The root iteration above "consumed" dirty cards in the perm gen.
-  // Therefore, as a shortcut, we dirty all such cards.
-  g1h->rem_set()->invalidate(g1h->perm_gen()->used_region(), false);
-  fclose(reachable_file);
-  reachable_file = NULL;
-  // clear the mark bitmap again.
-  _nextMarkBitMap->clearAll();
-  COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
-  COMPILER2_PRESENT(DerivedPointerTable::clear());
-#endif // PRINT_REACHABLE_AT_INITIAL_MARK
+  if (G1PrintReachableAtInitialMark) {
+    print_reachable(true, "before");
+  }
 
   // Initialise marking structures. This has to be done in a STW phase.
   reset();
@@ -1965,15 +1909,21 @@
 #endif
 }
 
+#ifndef PRODUCT
+
 class ReachablePrinterOopClosure: public OopClosure {
 private:
   G1CollectedHeap* _g1h;
   CMBitMapRO*      _bitmap;
   outputStream*    _out;
+  bool             _use_prev_marking;
 
 public:
-  ReachablePrinterOopClosure(CMBitMapRO* bitmap, outputStream* out) :
-    _bitmap(bitmap), _g1h(G1CollectedHeap::heap()), _out(out) { }
+  ReachablePrinterOopClosure(CMBitMapRO*   bitmap,
+                             outputStream* out,
+                             bool          use_prev_marking) :
+    _g1h(G1CollectedHeap::heap()),
+    _bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
 
   void do_oop(narrowOop* p) { do_oop_work(p); }
   void do_oop(      oop* p) { do_oop_work(p); }
@@ -1988,14 +1938,23 @@
     else {
       HeapRegion* hr  = _g1h->heap_region_containing(obj);
       guarantee(hr != NULL, "invariant");
-      if (hr->obj_allocated_since_prev_marking(obj)) {
+      bool over_tams = false;
+      if (_use_prev_marking) {
+        over_tams = hr->obj_allocated_since_prev_marking(obj);
+      } else {
+        over_tams = hr->obj_allocated_since_next_marking(obj);
+      }
+
+      if (over_tams) {
         str = "over TAMS";
-        if (_bitmap->isMarked((HeapWord*) obj))
+        if (_bitmap->isMarked((HeapWord*) obj)) {
           str2 = " AND MARKED";
-      } else if (_bitmap->isMarked((HeapWord*) obj))
+        }
+      } else if (_bitmap->isMarked((HeapWord*) obj)) {
         str = "marked";
-      else
+      } else {
         str = "#### NOT MARKED ####";
+      }
     }
 
     _out->print_cr("    "PTR_FORMAT" contains "PTR_FORMAT" %s%s",
@@ -2005,16 +1964,19 @@
 
 class ReachablePrinterClosure: public BitMapClosure {
 private:
-  CMBitMapRO* _bitmap;
+  CMBitMapRO*   _bitmap;
   outputStream* _out;
+  bool          _use_prev_marking;
 
 public:
-  ReachablePrinterClosure(CMBitMapRO* bitmap, outputStream* out) :
-    _bitmap(bitmap), _out(out) { }
+  ReachablePrinterClosure(CMBitMapRO*   bitmap,
+                          outputStream* out,
+                          bool          use_prev_marking) :
+    _bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
 
   bool do_bit(size_t offset) {
     HeapWord* addr = _bitmap->offsetToHeapWord(offset);
-    ReachablePrinterOopClosure oopCl(_bitmap, _out);
+    ReachablePrinterOopClosure oopCl(_bitmap, _out, _use_prev_marking);
 
     _out->print_cr("  obj "PTR_FORMAT", offset %10d (marked)", addr, offset);
     oop(addr)->oop_iterate(&oopCl);
@@ -2026,76 +1988,111 @@
 
 class ObjInRegionReachablePrinterClosure : public ObjectClosure {
 private:
-  CMBitMapRO* _bitmap;
+  CMBitMapRO*   _bitmap;
   outputStream* _out;
+  bool          _use_prev_marking;
 
 public:
+  ObjInRegionReachablePrinterClosure(CMBitMapRO*   bitmap,
+                                     outputStream* out,
+                                     bool          use_prev_marking) :
+    _bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
+
   void do_object(oop o) {
-    ReachablePrinterOopClosure oopCl(_bitmap, _out);
+    ReachablePrinterOopClosure oopCl(_bitmap, _out, _use_prev_marking);
 
     _out->print_cr("  obj "PTR_FORMAT" (over TAMS)", (void*) o);
     o->oop_iterate(&oopCl);
     _out->print_cr("");
   }
-
-  ObjInRegionReachablePrinterClosure(CMBitMapRO* bitmap, outputStream* out) :
-    _bitmap(bitmap), _out(out) { }
 };
 
 class RegionReachablePrinterClosure : public HeapRegionClosure {
 private:
-  CMBitMapRO* _bitmap;
+  CMBitMapRO*   _bitmap;
   outputStream* _out;
+  bool          _use_prev_marking;
 
 public:
   bool doHeapRegion(HeapRegion* hr) {
     HeapWord* b = hr->bottom();
     HeapWord* e = hr->end();
     HeapWord* t = hr->top();
-    HeapWord* p = hr->prev_top_at_mark_start();
+    HeapWord* p = NULL;
+    if (_use_prev_marking) {
+      p = hr->prev_top_at_mark_start();
+    } else {
+      p = hr->next_top_at_mark_start();
+    }
     _out->print_cr("** ["PTR_FORMAT", "PTR_FORMAT"] top: "PTR_FORMAT" "
-                   "PTAMS: "PTR_FORMAT, b, e, t, p);
+                   "TAMS: "PTR_FORMAT, b, e, t, p);
     _out->print_cr("");
 
-    ObjInRegionReachablePrinterClosure ocl(_bitmap, _out);
+    ObjInRegionReachablePrinterClosure ocl(_bitmap, _out, _use_prev_marking);
     hr->object_iterate_mem_careful(MemRegion(p, t), &ocl);
 
     return false;
   }
 
-  RegionReachablePrinterClosure(CMBitMapRO* bitmap,
-                                outputStream* out) :
-    _bitmap(bitmap), _out(out) { }
+  RegionReachablePrinterClosure(CMBitMapRO*   bitmap,
+                                outputStream* out,
+                                bool          use_prev_marking) :
+    _bitmap(bitmap), _out(out), _use_prev_marking(use_prev_marking) { }
 };
 
-void ConcurrentMark::print_prev_bitmap_reachable() {
-  outputStream* out = gclog_or_tty;
-
-#if SEND_HEAP_DUMP_TO_FILE
-  guarantee(heap_dump_file == NULL, "Protocol");
-  char fn_buf[100];
-  sprintf(fn_buf, "/tmp/dump.txt.%d", os::current_process_id());
-  heap_dump_file = fopen(fn_buf, "w");
-  fileStream fstream(heap_dump_file);
-  out = &fstream;
-#endif // SEND_HEAP_DUMP_TO_FILE
-
-  RegionReachablePrinterClosure rcl(_prevMarkBitMap, out);
-  out->print_cr("--- ITERATING OVER REGIONS WITH PTAMS < TOP");
+void ConcurrentMark::print_reachable(bool use_prev_marking, const char* str) {
+  gclog_or_tty->print_cr("== Doing reachable object dump... ");
+
+  if (G1PrintReachableBaseFile == NULL) {
+    gclog_or_tty->print_cr("  #### error: no base file defined");
+    return;
+  }
+
+  if (strlen(G1PrintReachableBaseFile) + 1 + strlen(str) >
+      (JVM_MAXPATHLEN - 1)) {
+    gclog_or_tty->print_cr("  #### error: file name too long");
+    return;
+  }
+
+  char file_name[JVM_MAXPATHLEN];
+  sprintf(file_name, "%s.%s", G1PrintReachableBaseFile, str);
+  gclog_or_tty->print_cr("  dumping to file %s", file_name);
+
+  fileStream fout(file_name);
+  if (!fout.is_open()) {
+    gclog_or_tty->print_cr("  #### error: could not open file");
+    return;
+  }
+
+  outputStream* out = &fout;
+
+  CMBitMapRO* bitmap = NULL;
+  if (use_prev_marking) {
+    bitmap = _prevMarkBitMap;
+  } else {
+    bitmap = _nextMarkBitMap;
+  }
+
+  out->print_cr("-- USING %s", (use_prev_marking) ? "PTAMS" : "NTAMS");
+  out->cr();
+
+  RegionReachablePrinterClosure rcl(bitmap, out, use_prev_marking);
+  out->print_cr("--- ITERATING OVER REGIONS WITH TAMS < TOP");
+  out->cr();
   _g1h->heap_region_iterate(&rcl);
-  out->print_cr("");
-
-  ReachablePrinterClosure cl(_prevMarkBitMap, out);
-  out->print_cr("--- REACHABLE OBJECTS ON THE BITMAP");
-  _prevMarkBitMap->iterate(&cl);
-  out->print_cr("");
-
-#if SEND_HEAP_DUMP_TO_FILE
-  fclose(heap_dump_file);
-  heap_dump_file = NULL;
-#endif // SEND_HEAP_DUMP_TO_FILE
+  out->cr();
+
+  ReachablePrinterClosure cl(bitmap, out, use_prev_marking);
+  out->print_cr("--- ITERATING OVER MARKED OBJECTS ON THE BITMAP");
+  out->cr();
+  bitmap->iterate(&cl);
+  out->cr();
+
+  gclog_or_tty->print_cr("  done");
 }
 
+#endif // PRODUCT
+
 // This note is for drainAllSATBBuffers and the code in between.
 // In the future we could reuse a task to do this work during an
 // evacuation pause (since now tasks are not active and can be claimed
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -612,10 +612,11 @@
   // we do nothing.
   void markAndGrayObjectIfNecessary(oop p);
 
-  // This iterates over the bitmap of the previous marking and prints
-  // out all objects that are marked on the bitmap and indicates
-  // whether what they point to is also marked or not.
-  void print_prev_bitmap_reachable();
+  // This iterates over the marking bitmap (either prev or next) and
+  // prints out all objects that are marked on the bitmap and indicates
+  // whether what they point to is also marked or not. It also iterates
+  // the objects over TAMS (either prev or next).
+  void print_reachable(bool use_prev_marking, const char* str);
 
   // Clear the next marking bitmap (will be called concurrently).
   void clearNextBitmap();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -2371,8 +2371,9 @@
       gclog_or_tty->print_cr("Heap:");
       print_on(gclog_or_tty, true /* extended */);
       gclog_or_tty->print_cr("");
-      if (VerifyDuringGC && G1VerifyConcMarkPrintReachable) {
-        concurrent_mark()->print_prev_bitmap_reachable();
+      if (VerifyDuringGC && G1VerifyDuringGCPrintReachable) {
+        concurrent_mark()->print_reachable(use_prev_marking,
+                                           "failed-verification");
       }
       gclog_or_tty->flush();
     }
@@ -3135,7 +3136,7 @@
          _evac_failure_scan_stack->length() == 0,
          "Postcondition");
   assert(!_drain_in_progress, "Postcondition");
-  // Don't have to delete, since the scan stack is a resource object.
+  delete _evac_failure_scan_stack;
   _evac_failure_scan_stack = NULL;
 }
 
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -1516,7 +1516,8 @@
       (end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0;
     update_recent_gc_times(end_time_sec, elapsed_ms);
     _recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms;
-    assert(recent_avg_pause_time_ratio() < 1.00, "All GC?");
+    // using 1.01 to account for floating point inaccuracies
+    assert(recent_avg_pause_time_ratio() < 1.01, "All GC?");
   }
 
   if (G1PolicyVerbose > 1) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -55,8 +55,14 @@
   develop(intx, G1MarkingVerboseLevel, 0,                                   \
           "Level (0-4) of verboseness of the marking code")                 \
                                                                             \
-  develop(bool, G1VerifyConcMarkPrintReachable, false,                      \
-          "If conc mark verification fails, print reachable objects")       \
+  develop(bool, G1PrintReachableAtInitialMark, false,                       \
+          "Reachable object dump at the initial mark pause")                \
+                                                                            \
+  develop(bool, G1VerifyDuringGCPrintReachable, false,                      \
+          "If conc mark verification fails, dump reachable objects")        \
+                                                                            \
+  develop(ccstr, G1PrintReachableBaseFile, NULL,                            \
+          "The base file name for the reachable object dumps")              \
                                                                             \
   develop(bool, G1TraceMarkStackOverflow, false,                            \
           "If true, extra debugging code for CM restart for ovflw.")        \
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -135,7 +135,6 @@
   _occupied_entries(0), _occupied_cards(0),
   _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)),
   _buckets(NEW_C_HEAP_ARRAY(int, capacity)),
-  _next_deleted(NULL), _deleted(false),
   _free_list(NullEntry), _free_region(0)
 {
   clear();
@@ -296,40 +295,6 @@
   assert(e2->num_valid_cards() > 0, "Postcondition.");
 }
 
-RSHashTable* RSHashTable::_head_deleted_list = NULL;
-
-void RSHashTable::add_to_deleted_list(RSHashTable* rsht) {
-  assert(!rsht->deleted(), "Should delete only once.");
-  rsht->set_deleted(true);
-  RSHashTable* hd = _head_deleted_list;
-  while (true) {
-    rsht->_next_deleted = hd;
-    RSHashTable* res =
-      (RSHashTable*)
-      Atomic::cmpxchg_ptr(rsht, &_head_deleted_list, hd);
-    if (res == hd) return;
-    else hd = res;
-  }
-}
-
-RSHashTable* RSHashTable::get_from_deleted_list() {
-  RSHashTable* hd = _head_deleted_list;
-  while (hd != NULL) {
-    RSHashTable* next = hd->next_deleted();
-    RSHashTable* res =
-      (RSHashTable*)
-      Atomic::cmpxchg_ptr(next, &_head_deleted_list, hd);
-    if (res == hd) {
-      hd->set_next_deleted(NULL);
-      hd->set_deleted(false);
-      return hd;
-    } else {
-      hd = res;
-    }
-  }
-  return NULL;
-}
-
 CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
   CardIdx_t res;
   while (_bl_ind != RSHashTable::NullEntry) {
@@ -442,15 +407,6 @@
     sprt->cleanup();
     sprt = get_from_expanded_list();
   }
-  // Now delete all deleted RSHashTables.
-  RSHashTable* rsht = RSHashTable::get_from_deleted_list();
-  while (rsht != NULL) {
-#if SPARSE_PRT_VERBOSE
-    gclog_or_tty->print_cr("About to delete RSHT " PTR_FORMAT ".", rsht);
-#endif
-    delete rsht;
-    rsht = RSHashTable::get_from_deleted_list();
-  }
 }
 
 
@@ -511,8 +467,10 @@
 }
 
 void SparsePRT::cleanup() {
-  // Make sure that the current and next tables agree.  (Another mechanism
-  // takes care of deleting now-unused tables.)
+  // Make sure that the current and next tables agree.
+  if (_cur != _next) {
+    delete _cur;
+  }
   _cur = _next;
   set_expanded(false);
 }
@@ -535,7 +493,8 @@
       _next->add_entry(e);
     }
   }
-  if (last != _cur)
-    RSHashTable::add_to_deleted_list(last);
+  if (last != _cur) {
+    delete last;
+  }
   add_to_expanded_list(this);
 }
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -102,13 +102,6 @@
   int  _free_region;
   int  _free_list;
 
-  static RSHashTable* _head_deleted_list;
-  RSHashTable* _next_deleted;
-  RSHashTable* next_deleted() { return _next_deleted; }
-  void set_next_deleted(RSHashTable* rsht) { _next_deleted = rsht; }
-  bool _deleted;
-  void set_deleted(bool b) { _deleted = b; }
-
   // Requires that the caller hold a lock preventing parallel modifying
   // operations, and that the the table be less than completely full.  If
   // an entry for "region_ind" is already in the table, finds it and
@@ -154,14 +147,10 @@
   size_t occupied_entries() const { return _occupied_entries; }
   size_t occupied_cards() const   { return _occupied_cards;   }
   size_t mem_size() const;
-  bool deleted() { return _deleted; }
 
   SparsePRTEntry* entry(int i) const { return &_entries[i]; }
 
   void print();
-
-  static void add_to_deleted_list(RSHashTable* rsht);
-  static RSHashTable* get_from_deleted_list();
 };
 
 // ValueObj because will be embedded in HRRS iterator.
--- a/hotspot/src/share/vm/memory/compactingPermGenGen.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/memory/compactingPermGenGen.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -352,15 +352,19 @@
 }
 
 
+// Do not use in time-critical operations due to the possibility of paging
+// in otherwise untouched or previously unread portions of the perm gen,
+// for instance, the shared spaces. NOTE: Because CompactingPermGenGen
+// derives from OneContigSpaceCardGeneration which is supposed to have a
+// single space, and does not override its object_iterate() method,
+// object iteration via that interface does not look at the objects in
+// the shared spaces when using CDS. This should be fixed; see CR 6897798.
 void CompactingPermGenGen::space_iterate(SpaceClosure* blk, bool usedOnly) {
   OneContigSpaceCardGeneration::space_iterate(blk, usedOnly);
   if (spec()->enable_shared_spaces()) {
-#ifdef PRODUCT
     // Making the rw_space walkable will page in the entire space, and
-    // is to be avoided. However, this is required for Verify options.
-    ShouldNotReachHere();
-#endif
-
+    // is to be avoided in the case of time-critical operations.
+    // However, this is required for Verify and heap dump operations.
     blk->do_space(ro_space());
     blk->do_space(rw_space());
   }
--- a/hotspot/src/share/vm/memory/compactingPermGenGen.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/memory/compactingPermGenGen.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -29,6 +29,9 @@
 class PermanentGenerationSpec;
 
 // This is the "generation" view of a CompactingPermGen.
+// NOTE: the shared spaces used for CDS are here handled in
+// a somewhat awkward and potentially buggy fashion, see CR 6801625.
+// This infelicity should be fixed, see CR 6897789.
 class CompactingPermGenGen: public OneContigSpaceCardGeneration {
   friend class VMStructs;
   // Abstractly, this is a subtype that gets access to protected fields.
@@ -47,7 +50,7 @@
   OffsetTableContigSpace* _ro_space;
   OffsetTableContigSpace* _rw_space;
 
-  // With shared spaces there is a dicotomy in the use of the
+  // With shared spaces there is a dichotomy in the use of the
   // _virtual_space of the generation.  There is a portion of the
   // _virtual_space that is used for the unshared part of the
   // permanent generation and a portion that is reserved for the shared part.
--- a/hotspot/src/share/vm/memory/generation.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/memory/generation.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -606,6 +606,13 @@
 void OneContigSpaceCardGeneration::prepare_for_verify() {}
 
 
+// Override for a card-table generation with one contiguous
+// space. NOTE: For reasons that are lost in the fog of history,
+// this code is used when you iterate over perm gen objects,
+// even when one uses CDS, where the perm gen has a couple of
+// other spaces; this is because CompactingPermGenGen derives
+// from OneContigSpaceCardGeneration. This should be cleaned up,
+// see CR 6897789..
 void OneContigSpaceCardGeneration::object_iterate(ObjectClosure* blk) {
   _the_space->object_iterate(blk);
 }
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -1900,7 +1900,7 @@
   }
 }
 
-char* instanceKlass::signature_name() const {
+const char* instanceKlass::signature_name() const {
   const char* src = (const char*) (name()->as_C_string());
   const int src_length = (int)strlen(src);
   char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3);
@@ -2259,6 +2259,10 @@
     st->print(BULLET"fake entry for array: ");
     array_klass->print_value_on(st);
     st->cr();
+  } else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
+    st->print(BULLET"signature: ");
+    java_dyn_MethodType::print_signature(obj, st);
+    st->cr();
   }
 }
 
@@ -2284,6 +2288,9 @@
       const char* tname = type2name(java_lang_Class::primitive_type(obj));
       st->print("%s", tname ? tname : "type?");
     }
+  } else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
+    st->print(" = ");
+    java_dyn_MethodType::print_signature(obj, st);
   } else if (java_lang_boxing_object::is_instance(obj)) {
     st->print(" = ");
     java_lang_boxing_object::print(obj, st);
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -722,7 +722,7 @@
 #endif // SERIALGC
 
   // Naming
-  char* signature_name() const;
+  const char* signature_name() const;
 
   // Iterators
   int oop_oop_iterate(oop obj, OopClosure* blk) {
--- a/hotspot/src/share/vm/oops/klass.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/oops/klass.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -496,11 +496,13 @@
       return result;
     }
   }
+  if (name() == NULL)  return "<unknown>";
   return name()->as_klass_external_name();
 }
 
 
-char* Klass::signature_name() const {
+const char* Klass::signature_name() const {
+  if (name() == NULL)  return "<unknown>";
   return name()->as_C_string();
 }
 
--- a/hotspot/src/share/vm/oops/klass.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/oops/klass.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -546,7 +546,7 @@
   // For arrays, this returns the name of the element with a leading '['.
   // For classes, this returns the name with a leading 'L' and a trailing ';'
   //     and the package separators as '/'.
-  virtual char* signature_name() const;
+  virtual const char* signature_name() const;
 
   // garbage collection support
   virtual void oop_follow_contents(oop obj) = 0;
--- a/hotspot/src/share/vm/oops/markOop.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/oops/markOop.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -31,8 +31,9 @@
     st->print("locked(0x%lx)->", value());
     markOop(*(markOop*)value())->print_on(st);
   } else {
-    assert(is_unlocked(), "just checking");
+    assert(is_unlocked() || has_bias_pattern(), "just checking");
     st->print("mark(");
+    if (has_bias_pattern())  st->print("biased,");
     st->print("hash %#lx,", hash());
     st->print("age %d)", age());
   }
--- a/hotspot/src/share/vm/oops/methodOop.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/oops/methodOop.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -881,7 +881,7 @@
   assert((oop)p == method_type(), "pointer chase is correct");
 #endif
 
-  if (TraceMethodHandles)
+  if (TraceMethodHandles && (Verbose || WizardMode))
     m->print_on(tty);
 
   return m;
--- a/hotspot/src/share/vm/opto/callnode.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -421,21 +421,23 @@
         iklass = cik->as_instance_klass();
       } else if (cik->is_type_array_klass()) {
         cik->as_array_klass()->base_element_type()->print_name_on(st);
-        st->print("[%d]=", spobj->n_fields());
+        st->print("[%d]", spobj->n_fields());
       } else if (cik->is_obj_array_klass()) {
-        ciType* cie = cik->as_array_klass()->base_element_type();
-        int ndim = 1;
-        while (cie->is_obj_array_klass()) {
-          ndim += 1;
-          cie = cie->as_array_klass()->base_element_type();
+        ciKlass* cie = cik->as_obj_array_klass()->base_element_klass();
+        if (cie->is_instance_klass()) {
+          cie->print_name_on(st);
+        } else if (cie->is_type_array_klass()) {
+          cie->as_array_klass()->base_element_type()->print_name_on(st);
+        } else {
+          ShouldNotReachHere();
         }
-        cie->print_name_on(st);
+        st->print("[%d]", spobj->n_fields());
+        int ndim = cik->as_array_klass()->dimension() - 1;
         while (ndim-- > 0) {
           st->print("[]");
         }
-        st->print("[%d]=", spobj->n_fields());
       }
-      st->print("{");
+      st->print("={");
       uint nf = spobj->n_fields();
       if (nf > 0) {
         uint first_ind = spobj->first_index();
--- a/hotspot/src/share/vm/prims/jni.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -2116,7 +2116,7 @@
   DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
   objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
   if (a->is_within_bounds(index)) {
-    jobject ret = JNIHandles::make_local(env, a->obj_at(index));
+    ret = JNIHandles::make_local(env, a->obj_at(index));
     return ret;
   } else {
     char buf[jintAsStringSize];
@@ -2150,14 +2150,14 @@
 
 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \
 \
-  DT_RETURN_MARK_DECL_FOR(Result, New##Result##Array, Return);\
+  DT_RETURN_MARK_DECL(New##Result##Array, Return);\
 \
 JNI_ENTRY(Return, \
           jni_New##Result##Array(JNIEnv *env, jsize len)) \
   JNIWrapper("New" XSTR(Result) "Array"); \
   DTRACE_PROBE2(hotspot_jni, New##Result##Array__entry, env, len);\
   Return ret = NULL;\
-  DT_RETURN_MARK_FOR(Result, New##Result##Array, Return, (const Return&)ret);\
+  DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
 \
   oop obj= oopFactory::Allocator(len, CHECK_0); \
   ret = (Return) JNIHandles::make_local(env, obj); \
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -33,8 +33,7 @@
 
 MethodHandleEntry* MethodHandles::_entries[MethodHandles::_EK_LIMIT] = {NULL};
 const char*        MethodHandles::_entry_names[_EK_LIMIT+1] = {
-  "check_mtype",
-  "wrong_method_type",          // what happens when there is a type mismatch
+  "raise_exception",
   "invokestatic",               // how a MH emulates invokestatic
   "invokespecial",              // ditto for the other invokes...
   "invokevirtual",
@@ -48,6 +47,7 @@
 
   // starting at _adapter_mh_first:
   "adapter_retype_only",       // these are for AMH...
+  "adapter_retype_raw",
   "adapter_check_cast",
   "adapter_prim_to_prim",
   "adapter_ref_to_prim",
@@ -82,6 +82,8 @@
   NULL
 };
 
+jobject MethodHandles::_raise_exception_method;
+
 #ifdef ASSERT
 bool MethodHandles::spot_check_entry_names() {
   assert(!strcmp(entry_name(_invokestatic_mh), "invokestatic"), "");
@@ -157,7 +159,8 @@
 }
 
 methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) {
-  assert(mh->klass() == SystemDictionary::BoundMethodHandle_klass(), "");
+  assert(sun_dyn_BoundMethodHandle::is_instance(mh), "");
+  assert(mh->klass() != SystemDictionary::AdapterMethodHandle_klass(), "");
   for (oop bmh = mh;;) {
     // Bound MHs can be stacked to bind several arguments.
     oop target = java_dyn_MethodHandle::vmtarget(bmh);
@@ -174,10 +177,9 @@
       } else {
         // Optimized case:  binding a receiver to a non-dispatched DMH
         // short-circuits directly to the methodOop.
+        // (It might be another argument besides a receiver also.)
         assert(target->is_method(), "must be a simple method");
         methodOop m = (methodOop) target;
-        DEBUG_ONLY(int argslot = sun_dyn_BoundMethodHandle::vmargslot(bmh));
-        assert(argslot == m->size_of_parameters() - 1, "must be initial argument (receiver)");
         decode_flags_result |= MethodHandles::_dmf_binds_method;
         return m;
       }
@@ -214,6 +216,9 @@
     return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result);
   } else if (mhk == SystemDictionary::AdapterMethodHandle_klass()) {
     return decode_AdapterMethodHandle(mh, receiver_limit_result, decode_flags_result);
+  } else if (sun_dyn_BoundMethodHandle::is_subclass(mhk)) {
+    // could be a JavaMethodHandle (but not an adapter MH)
+    return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result);
   } else {
     assert(false, "cannot parse this MH");
     return NULL;              // random MH?
@@ -366,7 +371,13 @@
   oop vmtarget = sun_dyn_MemberName::vmtarget(mname);
   int vmindex  = sun_dyn_MemberName::vmindex(mname);
   if (vmindex == VM_INDEX_UNINITIALIZED)  return NULL; // not resolved
-  return decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result);
+  methodOop m = decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result);
+  oop clazz = sun_dyn_MemberName::clazz(mname);
+  if (clazz != NULL && java_lang_Class::is_instance(clazz)) {
+    klassOop klass = java_lang_Class::as_klassOop(clazz);
+    if (klass != NULL)  receiver_limit_result = klass;
+  }
+  return m;
 }
 
 // An unresolved member name is a mere symbolic reference.
@@ -789,6 +800,30 @@
   THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), msg);
 }
 
+static const char* always_null_names[] = {
+  "java/lang/Void",
+  "java/lang/Null",
+  //"java/lang/Nothing",
+  "sun/dyn/empty/Empty",
+  NULL
+};
+
+static bool is_always_null_type(klassOop klass) {
+  if (!Klass::cast(klass)->oop_is_instance())  return false;
+  instanceKlass* ik = instanceKlass::cast(klass);
+  // Must be on the boot class path:
+  if (ik->class_loader() != NULL)  return false;
+  // Check the name.
+  symbolOop name = ik->name();
+  for (int i = 0; ; i++) {
+    const char* test_name = always_null_names[i];
+    if (test_name == NULL)  break;
+    if (name->equals(test_name, (int) strlen(test_name)))
+      return true;
+  }
+  return false;
+}
+
 bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) {
   if (src == dst || dst == SystemDictionary::object_klass())
     return false;                               // quickest checks
@@ -805,6 +840,12 @@
     //srck = Klass::cast(SystemDictionary::object_klass());
     return true;
   }
+  if (is_always_null_type(src)) {
+    // some source types are known to be never instantiated;
+    // they represent references which are always null
+    // such null references never fail to convert safely
+    return false;
+  }
   return !srck->is_subclass_of(dstk->as_klassOop());
 }
 
@@ -814,9 +855,15 @@
 
 bool MethodHandles::same_basic_type_for_arguments(BasicType src,
                                                   BasicType dst,
+                                                  bool raw,
                                                   bool for_return) {
-  // return values can always be forgotten:
-  if (for_return && dst == T_VOID)  return true;
+  if (for_return) {
+    // return values can always be forgotten:
+    if (dst == T_VOID)  return true;
+    if (src == T_VOID)  return raw && (dst == T_INT);
+    // We allow caller to receive a garbage int, which is harmless.
+    // This trick is pulled by trusted code (see VerifyType.canPassRaw).
+  }
   assert(src != T_VOID && dst != T_VOID, "should not be here");
   if (src == dst)  return true;
   if (type2size[src] != type2size[dst])  return false;
@@ -929,8 +976,8 @@
   const char* err = NULL;
 
   int first_ptype_pos = m_needs_receiver ? 1 : 0;
-  if (has_bound_recv && err == NULL) {
-    first_ptype_pos -= 1;
+  if (has_bound_recv) {
+    first_ptype_pos -= 1;  // ptypes do not include the bound argument; start earlier in them
     if (m_needs_receiver && bound_recv_type.is_null())
       { err = "bound receiver is not an object"; goto die; }
   }
@@ -939,10 +986,10 @@
     objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype());
     if (ptypes->length() < first_ptype_pos)
       { err = "receiver argument is missing"; goto die; }
-    if (first_ptype_pos == -1)
+    if (has_bound_recv)
       err = check_method_receiver(m(), bound_recv_type->as_klassOop());
     else
-      err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(0)));
+      err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(first_ptype_pos-1)));
     if (err != NULL)  goto die;
   }
 
@@ -983,7 +1030,8 @@
                                                     int insert_argnum, oop insert_type,
                                                     int change_argnum, oop change_type,
                                                     int delete_argnum,
-                                                    oop dst_mtype, int dst_beg, int dst_end) {
+                                                    oop dst_mtype, int dst_beg, int dst_end,
+                                                    bool raw) {
   objArrayOop src_ptypes = java_dyn_MethodType::ptypes(src_mtype);
   objArrayOop dst_ptypes = java_dyn_MethodType::ptypes(dst_mtype);
 
@@ -1042,7 +1090,7 @@
     if (src_type != dst_type) {
       if (src_type == NULL)  return "not enough arguments";
       if (dst_type == NULL)  return "too many arguments";
-      err = check_argument_type_change(src_type, dst_type, dst_idx);
+      err = check_argument_type_change(src_type, dst_type, dst_idx, raw);
       if (err != NULL)  return err;
     }
   }
@@ -1051,7 +1099,7 @@
   oop src_rtype = java_dyn_MethodType::rtype(src_mtype);
   oop dst_rtype = java_dyn_MethodType::rtype(dst_mtype);
   if (src_rtype != dst_rtype) {
-    err = check_return_type_change(dst_rtype, src_rtype); // note reversal!
+    err = check_return_type_change(dst_rtype, src_rtype, raw); // note reversal!
     if (err != NULL)  return err;
   }
 
@@ -1061,38 +1109,45 @@
 
 
 const char* MethodHandles::check_argument_type_change(BasicType src_type,
-                                                     klassOop src_klass,
-                                                     BasicType dst_type,
-                                                     klassOop dst_klass,
-                                                     int argnum) {
+                                                      klassOop src_klass,
+                                                      BasicType dst_type,
+                                                      klassOop dst_klass,
+                                                      int argnum,
+                                                      bool raw) {
   const char* err = NULL;
+  bool for_return = (argnum < 0);
 
   // just in case:
   if (src_type == T_ARRAY)  src_type = T_OBJECT;
   if (dst_type == T_ARRAY)  dst_type = T_OBJECT;
 
   // Produce some nice messages if VerifyMethodHandles is turned on:
-  if (!same_basic_type_for_arguments(src_type, dst_type, (argnum < 0))) {
+  if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) {
     if (src_type == T_OBJECT) {
+      if (raw && dst_type == T_INT && is_always_null_type(src_klass))
+        return NULL;    // OK to convert a null pointer to a garbage int
       err = ((argnum >= 0)
              ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s"
              : "type mismatch: returning a %s, but caller expects primitive %s");
     } else if (dst_type == T_OBJECT) {
-      err = ((argnum < 0)
+      err = ((argnum >= 0)
              ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s"
              : "type mismatch: returning a primitive %s, but caller expects %s");
     } else {
-      err = ((argnum < 0)
+      err = ((argnum >= 0)
              ? "type mismatch: passing a %s for method argument #%d, which expects %s"
              : "type mismatch: returning a %s, but caller expects %s");
     }
-  } else if (src_type == T_OBJECT && class_cast_needed(src_klass, dst_klass)) {
+  } else if (src_type == T_OBJECT && dst_type == T_OBJECT &&
+             class_cast_needed(src_klass, dst_klass)) {
     if (!class_cast_needed(dst_klass, src_klass)) {
-      err = ((argnum < 0)
+      if (raw)
+        return NULL;    // reverse cast is OK; the MH target is trusted to enforce it
+      err = ((argnum >= 0)
              ? "cast required: passing a %s for method argument #%d, which expects %s"
              : "cast required: returning a %s, but caller expects %s");
     } else {
-      err = ((argnum < 0)
+      err = ((argnum >= 0)
              ? "reference mismatch: passing a %s for method argument #%d, which expects %s"
              : "reference mismatch: returning a %s, but caller expects %s");
     }
@@ -1429,10 +1484,10 @@
       assert(this_pushes == slots_pushed, "BMH pushes one or two stack slots");
       assert(slots_pushed <= MethodHandlePushLimit, "");
     } else {
-      int prev_pushes = decode_MethodHandle_stack_pushes(target());
-      assert(this_pushes == slots_pushed + prev_pushes, "BMH stack motion must be correct");
+      int target_pushes = decode_MethodHandle_stack_pushes(target());
+      assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct");
       // do not blow the stack; use a Java-based adapter if this limit is exceeded
-      if (slots_pushed + prev_pushes > MethodHandlePushLimit)
+      if (slots_pushed + target_pushes > MethodHandlePushLimit)
         err = "too many bound parameters";
     }
   }
@@ -1588,6 +1643,11 @@
   if (err == NULL) {
     // Check that the src/dest types are supplied if needed.
     switch (ek) {
+    case _adapter_check_cast:
+      if (src != T_OBJECT || dest != T_OBJECT) {
+        err = "adapter requires object src/dest conversion subfields";
+      }
+      break;
     case _adapter_prim_to_prim:
       if (!is_java_primitive(src) || !is_java_primitive(dest) || src == dest) {
         err = "adapter requires primitive src/dest conversion subfields"; break;
@@ -1616,9 +1676,9 @@
           err = "adapter requires src/dest conversion subfields for swap"; break;
         }
         int swap_size = type2size[src];
-        oop src_mtype  = sun_dyn_AdapterMethodHandle::type(target());
-        oop dest_mtype = sun_dyn_AdapterMethodHandle::type(mh());
-        int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(src_mtype);
+        oop src_mtype  = sun_dyn_AdapterMethodHandle::type(mh());
+        oop dest_mtype = sun_dyn_AdapterMethodHandle::type(target());
+        int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(target());
         int src_slot   = argslot;
         int dest_slot  = vminfo;
         bool rotate_up = (src_slot > dest_slot); // upward rotation
@@ -1729,22 +1789,22 @@
     // Make sure this adapter does not push too deeply.
     int slots_pushed = stack_move / stack_move_unit();
     int this_vmslots = java_dyn_MethodHandle::vmslots(mh());
-    int prev_vmslots = java_dyn_MethodHandle::vmslots(target());
-    if (slots_pushed != (this_vmslots - prev_vmslots)) {
+    int target_vmslots = java_dyn_MethodHandle::vmslots(target());
+    if (slots_pushed != (target_vmslots - this_vmslots)) {
       err = "stack_move inconsistent with previous and current MethodType vmslots";
     } else if (slots_pushed > 0)  {
       // verify stack_move against MethodHandlePushLimit
-      int prev_pushes = decode_MethodHandle_stack_pushes(target());
+      int target_pushes = decode_MethodHandle_stack_pushes(target());
       // do not blow the stack; use a Java-based adapter if this limit is exceeded
-      if (slots_pushed + prev_pushes > MethodHandlePushLimit) {
+      if (slots_pushed + target_pushes > MethodHandlePushLimit) {
         err = "adapter pushes too many parameters";
       }
     }
 
     // While we're at it, check that the stack motion decoder works:
-    DEBUG_ONLY(int prev_pushes = decode_MethodHandle_stack_pushes(target()));
+    DEBUG_ONLY(int target_pushes = decode_MethodHandle_stack_pushes(target()));
     DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh()));
-    assert(this_pushes == slots_pushed + prev_pushes, "AMH stack motion must be correct");
+    assert(this_pushes == slots_pushed + target_pushes, "AMH stack motion must be correct");
   }
 
   if (err == NULL && vminfo != 0) {
@@ -1761,7 +1821,11 @@
   if (err == NULL) {
     switch (ek) {
     case _adapter_retype_only:
-      err = check_method_type_passthrough(src_mtype(), dst_mtype());
+      err = check_method_type_passthrough(src_mtype(), dst_mtype(), false);
+      break;
+
+    case _adapter_retype_raw:
+      err = check_method_type_passthrough(src_mtype(), dst_mtype(), true);
       break;
 
     case _adapter_check_cast:
@@ -1821,6 +1885,7 @@
   // Now it's time to finish the case analysis and pick a MethodHandleEntry.
   switch (ek_orig) {
   case _adapter_retype_only:
+  case _adapter_retype_raw:
   case _adapter_check_cast:
   case _adapter_dup_args:
   case _adapter_drop_args:
@@ -1888,8 +1953,7 @@
   case _adapter_rot_args:
     {
       int swap_slots = type2size[src];
-      oop mtype      = sun_dyn_AdapterMethodHandle::type(mh());
-      int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mtype);
+      int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mh());
       int src_slot   = argslot;
       int dest_slot  = vminfo;
       int rotate     = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1;
@@ -2133,7 +2197,7 @@
     guarantee(MethodHandlePushLimit >= 2 && MethodHandlePushLimit <= 0xFF,
               "MethodHandlePushLimit parameter must be in valid range");
     return MethodHandlePushLimit;
-  case MethodHandles::GC_JVM_STACK_MOVE_LIMIT:
+  case MethodHandles::GC_JVM_STACK_MOVE_UNIT:
     // return number of words per slot, signed according to stack direction
     return MethodHandles::stack_move_unit();
   }
@@ -2144,7 +2208,7 @@
 #ifndef PRODUCT
 #define EACH_NAMED_CON(template) \
     template(MethodHandles,GC_JVM_PUSH_LIMIT) \
-    template(MethodHandles,GC_JVM_STACK_MOVE_LIMIT) \
+    template(MethodHandles,GC_JVM_STACK_MOVE_UNIT) \
     template(MethodHandles,ETF_HANDLE_OR_METHOD_NAME) \
     template(MethodHandles,ETF_DIRECT_HANDLE) \
     template(MethodHandles,ETF_METHOD_NAME) \
@@ -2157,6 +2221,7 @@
     template(sun_dyn_MemberName,MN_SEARCH_INTERFACES) \
     template(sun_dyn_MemberName,VM_INDEX_UNINITIALIZED) \
     template(sun_dyn_AdapterMethodHandle,OP_RETYPE_ONLY) \
+    template(sun_dyn_AdapterMethodHandle,OP_RETYPE_RAW) \
     template(sun_dyn_AdapterMethodHandle,OP_CHECK_CAST) \
     template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_PRIM) \
     template(sun_dyn_AdapterMethodHandle,OP_REF_TO_PRIM) \
@@ -2345,10 +2410,12 @@
   // note: this explicit warning-producing stuff will be replaced by auto-detection of the JSR 292 classes
 
   if (!EnableMethodHandles) {
-    warning("JSR 292 method handles are disabled in this JVM.  Use -XX:+EnableMethodHandles to enable.");
+    warning("JSR 292 method handles are disabled in this JVM.  Use -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles to enable.");
     return;  // bind nothing
   }
 
+  bool enable_MH = true;
+
   {
     ThreadToNativeFromVM ttnfv(thread);
 
@@ -2356,14 +2423,33 @@
     if (env->ExceptionOccurred()) {
       MethodHandles::set_enabled(false);
       warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
+      enable_MH = false;
       env->ExceptionClear();
-    } else {
-      MethodHandles::set_enabled(true);
     }
   }
 
+  if (enable_MH) {
+    KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass();
+    if (MHI_klass.not_null()) {
+      symbolHandle raiseException_name = oopFactory::new_symbol_handle("raiseException", CHECK);
+      symbolHandle raiseException_sig  = oopFactory::new_symbol_handle("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
+      methodOop raiseException_method  = instanceKlass::cast(MHI_klass->as_klassOop())
+                    ->find_method(raiseException_name(), raiseException_sig());
+      if (raiseException_method != NULL && raiseException_method->is_static()) {
+        MethodHandles::set_raise_exception_method(raiseException_method);
+      } else {
+        warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
+        enable_MH = false;
+      }
+    }
+  }
+
+  if (enable_MH) {
+    MethodHandles::set_enabled(true);
+  }
+
   if (!EnableInvokeDynamic) {
-    warning("JSR 292 invokedynamic is disabled in this JVM.  Use -XX:+EnableInvokeDynamic to enable.");
+    warning("JSR 292 invokedynamic is disabled in this JVM.  Use -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic to enable.");
     return;  // bind nothing
   }
 
--- a/hotspot/src/share/vm/prims/methodHandles.hpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp	Wed Jul 05 17:02:54 2017 +0200
@@ -32,8 +32,7 @@
   // See also  javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}.
  public:
   enum EntryKind {
-    _check_mtype,               // how a caller calls a MH
-    _wrong_method_type,         // what happens when there is a type mismatch
+    _raise_exception,           // stub for error generation from other stubs
     _invokestatic_mh,           // how a MH emulates invokestatic
     _invokespecial_mh,          // ditto for the other invokes...
     _invokevirtual_mh,
@@ -47,6 +46,7 @@
 
     _adapter_mh_first,     // adapter sequence goes here...
     _adapter_retype_only   = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY,
+    _adapter_retype_raw    = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW,
     _adapter_check_cast    = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST,
     _adapter_prim_to_prim  = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM,
     _adapter_ref_to_prim   = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM,
@@ -113,6 +113,8 @@
   static bool _enabled;
   static MethodHandleEntry* _entries[_EK_LIMIT];
   static const char*        _entry_names[_EK_LIMIT+1];
+  static jobject            _raise_exception_method;
+
   static bool ek_valid(EntryKind ek)            { return (uint)ek < (uint)_EK_LIMIT; }
   static bool conv_op_valid(int op)             { return (uint)op < (uint)CONV_OP_LIMIT; }
 
@@ -131,6 +133,16 @@
     _entries[ek] = me;
   }
 
+  static methodOop raise_exception_method() {
+    oop rem = JNIHandles::resolve(_raise_exception_method);
+    assert(rem == NULL || rem->is_method(), "");
+    return (methodOop) rem;
+  }
+  static void set_raise_exception_method(methodOop rem) {
+    assert(_raise_exception_method == NULL, "");
+    _raise_exception_method = JNIHandles::make_global(Handle(rem));
+  }
+
   static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
                                  int stack_move = 0, int vminfo = 0) {
     assert(conv_op_valid(conv_op), "oob");
@@ -243,7 +255,7 @@
   enum {
     // format of query to getConstant:
     GC_JVM_PUSH_LIMIT = 0,
-    GC_JVM_STACK_MOVE_LIMIT = 1,
+    GC_JVM_STACK_MOVE_UNIT = 1,
 
     // format of result from getTarget / encode_target:
     ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
@@ -261,7 +273,8 @@
                                               int insert_argnum, oop insert_type,
                                               int change_argnum, oop change_type,
                                               int delete_argnum,
-                                              oop dst_mtype, int dst_beg, int dst_end);
+                                              oop dst_mtype, int dst_beg, int dst_end,
+                                              bool raw = false);
   static const char* check_method_type_insertion(oop src_mtype,
                                                  int insert_argnum, oop insert_type,
                                                  oop dst_mtype) {
@@ -278,29 +291,29 @@
                                     change_argnum, change_type,
                                     -1, dst_mtype, 0, -1);
   }
-  static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) {
+  static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype, bool raw) {
     oop no_ref = NULL;
     return check_method_type_change(src_mtype, 0, -1,
                                     -1, no_ref, -1, no_ref, -1,
-                                    dst_mtype, 0, -1);
+                                    dst_mtype, 0, -1, raw);
   }
 
   // These checkers operate on pairs of argument or return types:
   static const char* check_argument_type_change(BasicType src_type, klassOop src_klass,
                                                 BasicType dst_type, klassOop dst_klass,
-                                                int argnum);
+                                                int argnum, bool raw = false);
 
   static const char* check_argument_type_change(oop src_type, oop dst_type,
-                                                int argnum) {
+                                                int argnum, bool raw = false) {
     klassOop src_klass = NULL, dst_klass = NULL;
     BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass);
     BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass);
     return check_argument_type_change(src_bt, src_klass,
-                                      dst_bt, dst_klass, argnum);
+                                      dst_bt, dst_klass, argnum, raw);
   }
 
-  static const char* check_return_type_change(oop src_type, oop dst_type) {
-    return check_argument_type_change(src_type, dst_type, -1);
+  static const char* check_return_type_change(oop src_type, oop dst_type, bool raw = false) {
+    return check_argument_type_change(src_type, dst_type, -1, raw);
   }
 
   static const char* check_return_type_change(BasicType src_type, klassOop src_klass,
@@ -357,9 +370,10 @@
                                               TRAPS);
 
   static bool same_basic_type_for_arguments(BasicType src, BasicType dst,
+                                            bool raw = false,
                                             bool for_return = false);
-  static bool same_basic_type_for_returns(BasicType src, BasicType dst) {
-    return same_basic_type_for_arguments(src, dst, true);
+  static bool same_basic_type_for_returns(BasicType src, BasicType dst, bool raw = false) {
+    return same_basic_type_for_arguments(src, dst, raw, true);
   }
 
   enum {                        // arg_mask values
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -594,6 +594,7 @@
                                                                                                                                      \
   nonstatic_field(PcDesc,                      _pc_offset,                                    int)                                   \
   nonstatic_field(PcDesc,                      _scope_decode_offset,                          int)                                   \
+  nonstatic_field(PcDesc,                      _obj_decode_offset,                            int)                                   \
   nonstatic_field(PcDesc,                      _flags,                        PcDesc::PcDescFlags)                                   \
                                                                                                                                      \
   /***************************************************/                                                                              \
--- a/hotspot/src/share/vm/services/heapDumper.cpp	Fri Nov 06 17:26:01 2009 -0800
+++ b/hotspot/src/share/vm/services/heapDumper.cpp	Wed Jul 05 17:02:54 2017 +0200
@@ -1913,8 +1913,9 @@
     if (use_default_filename) {
       char fn[32];
       sprintf(fn, "java_pid%d", os::current_process_id());
-      assert(strlen(base_path) + strlen(fn) < sizeof(base_path), "HeapDumpPath too long");
+      assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long");
       strcat(base_path, fn);
+      strcat(base_path, ".hprof");
     }
     assert(strlen(base_path) < sizeof(my_path), "Buffer too small");
     strcpy(my_path, base_path);
@@ -1927,8 +1928,6 @@
     strcat(my_path, fn);
   }
   dump_file_seq++;   // increment seq number for next time we dump
-  assert(strlen(".hprof") + strlen(my_path) < sizeof(my_path), "HeapDumpPath too long");
-  strcat(my_path, ".hprof");
 
   HeapDumper dumper(false /* no GC before heap dump */,
                     true  /* send to tty */);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6891750/Test6891750.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  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 6891750
+ * @summary deopt blob kills values in O5
+ *
+ * @run main Test6891750
+ */
+
+abstract class Base6891750 extends Thread {
+    abstract public long m();
+}
+class Other6891750 extends Base6891750 {
+    public long m() {
+        return 0;
+    }
+}
+
+public class Test6891750 extends Base6891750 {
+    Base6891750 d;
+    volatile long  value = 9;
+
+    static int limit = 400000;
+
+    Test6891750() {
+        d = this;
+
+    }
+    public long m() {
+        return value;
+    }
+
+    public long test(boolean doit) {
+        if (doit) {
+            long total0 = 0;
+            long total1 = 0;
+            long total2 = 0;
+            long total3 = 0;
+            long total4 = 0;
+            long total5 = 0;
+            long total6 = 0;
+            long total7 = 0;
+            long total8 = 0;
+            long total9 = 0;
+            for (int i = 0; i < limit; i++) {
+                total0 += d.m();
+                total1 += d.m();
+                total2 += d.m();
+                total3 += d.m();
+                total4 += d.m();
+                total5 += d.m();
+                total6 += d.m();
+                total7 += d.m();
+                total8 += d.m();
+                total9 += d.m();
+            }
+            return total0 + total1 + total2 + total3 + total4 + total5 + total6 + total7 + total8 + total9;
+        }
+        return 0;
+    }
+
+    public void run() {
+        long result = test(true);
+        for (int i = 0; i < 300; i++) {
+            long result2 = test(true);
+            if (result != result2) {
+                throw new InternalError(result + " != " + result2);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Test6891750 Test6891750 = new Test6891750();
+        // warm it up
+        for (int i = 0; i < 200000; i++) {
+            Test6891750.test(false);
+        }
+        // set in off running
+        Test6891750.start();
+        Thread.sleep(2000);
+
+        // Load a class to invalidate CHA
+        new Other6891750();
+    }
+}
--- a/jdk/.hgtags	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/.hgtags	Wed Jul 05 17:02:54 2017 +0200
@@ -49,3 +49,4 @@
 460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72
 f708138c9aca4b389872838fe6773872fce3609e jdk7-b73
 eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74
+8885b22565077236a927e824ef450742e434a230 jdk7-b75
--- a/jdk/make/common/Defs-linux.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/common/Defs-linux.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -116,8 +116,16 @@
 LDFLAGS_COMMON_sparcv9  += -m64 -mcpu=v9
 CFLAGS_REQUIRED_sparc   += -m32 -mcpu=v9
 LDFLAGS_COMMON_sparc    += -m32 -mcpu=v9
-CFLAGS_REQUIRED         =  $(CFLAGS_REQUIRED_$(ARCH))
-LDFLAGS_COMMON          += $(LDFLAGS_COMMON_$(ARCH))
+ifeq ($(ZERO_BUILD), true)
+  CFLAGS_REQUIRED       =  $(ZERO_ARCHFLAG)
+  ifeq ($(ZERO_ENDIANNESS), little)
+    CFLAGS_REQUIRED     += -D_LITTLE_ENDIAN
+  endif
+  LDFLAGS_COMMON        += $(ZERO_ARCHFLAG)
+else
+  CFLAGS_REQUIRED       =  $(CFLAGS_REQUIRED_$(ARCH))
+  LDFLAGS_COMMON        += $(LDFLAGS_COMMON_$(ARCH))
+endif
 
 # If this is a --hash-style=gnu system, use --hash-style=both
 #   The gnu .hash section won't work on some Linux systems like SuSE 10.
@@ -217,7 +225,7 @@
 
 EXTRA_LIBS += -lc
 
-LDFLAGS_DEFS_OPTION  = -z defs
+LDFLAGS_DEFS_OPTION  = -Xlinker -z -Xlinker defs
 LDFLAGS_COMMON  += $(LDFLAGS_DEFS_OPTION)
 
 #
--- a/jdk/make/common/Defs.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/common/Defs.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -667,12 +667,7 @@
 LINTFLAGS       = $(LINTFLAGS_$(VARIANT)) $(LINTFLAGS_COMMON) \
 		  $(OTHER_LINTFLAGS)
 
-# this should be moved into Defs-<platform>.gmk.....
-ifeq ($(PLATFORM), windows)
-  VERSION_DEFINES = -DRELEASE="\"$(RELEASE)\""
-else
-  VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
-endif
+VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
 
 # Note: As a rule, GNU Make rules should not appear in any of the 
 # Defs*.gmk files. These were added for Kestrel-Solaris and do address
--- a/jdk/make/common/Program.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/common/Program.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -85,7 +85,7 @@
 	endif
     endif
     ifeq ($(PLATFORM), linux)
-	LDFLAGS += -z origin
+	LDFLAGS += -Wl,-z -Wl,origin
 	LDFLAGS += -Wl,--allow-shlib-undefined
 	LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../lib/$(LIBARCH)/jli
 	LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../jre/lib/$(LIBARCH)/jli
@@ -236,13 +236,13 @@
 endif # INCREMENTAL_BUILD
 
 ifdef JAVA_ARGS
-OTHER_CPPFLAGS += -DJAVA_ARGS=$(JAVA_ARGS)
-OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
+OTHER_CPPFLAGS += -DJAVA_ARGS='$(JAVA_ARGS)'
+OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
 endif
 
 ifeq ($(PLATFORM), windows)
 ifdef RELEASE
-OTHER_CPPFLAGS += -DVERSION="$(RELEASE)"
+OTHER_CPPFLAGS += -DVERSION='"$(RELEASE)"'
 endif
 endif
 
@@ -258,14 +258,8 @@
 OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)/bin -I$(LAUNCHER_PLATFORM_SRC)/bin
 OTHER_INCLUDES += -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
 
-# this may not be necessary...
-ifeq ($(PLATFORM), windows)
-OTHER_CPPFLAGS += -DPROGNAME="\"$(PROGRAM)\""
-VERSION_DEFINES += -DFULL_VERSION="\"$(FULL_VERSION)\""
-else
 OTHER_CPPFLAGS += -DPROGNAME='"$(PROGRAM)"'
 VERSION_DEFINES += -DFULL_VERSION='"$(FULL_VERSION)"'
-endif
 
 VERSION_DEFINES += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \
 		   -DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"'
@@ -279,8 +273,14 @@
 
 #
 # How to install jvm.cfg. 
-# 
-$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(ARCH)/jvm.cfg 
+#
+ifeq ($(ZERO_BUILD), true)
+JVMCFG_ARCH = zero
+else
+JVMCFG_ARCH = $(ARCH)
+endif
+
+$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(JVMCFG_ARCH)/jvm.cfg 
 	$(install-file)
 
 #
--- a/jdk/make/common/Release.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/common/Release.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -330,7 +330,7 @@
 #
 # Specific files and directories that will be filtered out from above areas.
 #
-SOURCE_FILTERs = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
+SOURCE_FILTERs = $(SCM_DIRs) ',*'
 SOURCE_FILES_filter = $(SOURCE_FILTERs:%=-name % -prune -o)
 
 #
--- a/jdk/make/common/Rules.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/common/Rules.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -63,7 +63,7 @@
 # If AUTO_FILES_PROPERTIES_DIRS used, automatically find properties files
 #
 ifdef AUTO_FILES_PROPERTIES_DIRS
-  AUTO_FILES_PROPERTIES_FILTERS1  = $(SCM_DIRs) 'X-*' '*-X-*' ',*'
+  AUTO_FILES_PROPERTIES_FILTERS1  = $(SCM_DIRs) ',*'
   AUTO_FILES_PROPERTIES_FILTERS1 += $(AUTO_PROPERTIES_PRUNE)
   FILES_properties_find_filters1 = $(AUTO_FILES_PROPERTIES_FILTERS1:%=-name % -prune -o)
   FILES_properties_auto1 := \
@@ -111,7 +111,7 @@
 
 ifdef AUTO_FILES_JAVA_DIRS
   # Filter out these files or directories
-  AUTO_FILES_JAVA_SOURCE_FILTERS1  = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
+  AUTO_FILES_JAVA_SOURCE_FILTERS1  = $(SCM_DIRs) ',*'
   AUTO_FILES_JAVA_SOURCE_FILTERS2  = 
   AUTO_FILES_JAVA_SOURCE_FILTERS1 += $(AUTO_JAVA_PRUNE)
   AUTO_FILES_JAVA_SOURCE_FILTERS2 += $(AUTO_JAVA_PRUNE)
--- a/jdk/make/java/instrument/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/instrument/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -109,7 +109,7 @@
     LDFLAGS += -R \$$ORIGIN/jli
   endif
   ifeq ($(PLATFORM), linux)
-    LDFLAGS += -z origin
+    LDFLAGS += -Wl,-z -Wl,origin
     LDFLAGS += -Wl,--allow-shlib-undefined
     LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/jli
   endif
--- a/jdk/make/java/java/FILES_java.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/java/FILES_java.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -286,11 +286,18 @@
     java/util/concurrent/ExecutorService.java \
     java/util/concurrent/ExecutorCompletionService.java \
     java/util/concurrent/Executors.java \
+    java/util/concurrent/ForkJoinPool.java \
+    java/util/concurrent/ForkJoinTask.java \
+    java/util/concurrent/ForkJoinWorkerThread.java \
     java/util/concurrent/Future.java \
     java/util/concurrent/FutureTask.java \
     java/util/concurrent/LinkedBlockingDeque.java \
     java/util/concurrent/LinkedBlockingQueue.java \
+    java/util/concurrent/LinkedTransferQueue.java \
+    java/util/concurrent/Phaser.java \
     java/util/concurrent/PriorityBlockingQueue.java \
+    java/util/concurrent/RecursiveAction.java \
+    java/util/concurrent/RecursiveTask.java \
     java/util/concurrent/RejectedExecutionException.java \
     java/util/concurrent/RejectedExecutionHandler.java \
     java/util/concurrent/RunnableFuture.java \
@@ -301,9 +308,11 @@
     java/util/concurrent/Semaphore.java \
     java/util/concurrent/SynchronousQueue.java \
     java/util/concurrent/ThreadFactory.java \
+    java/util/concurrent/ThreadLocalRandom.java \
     java/util/concurrent/ThreadPoolExecutor.java \
     java/util/concurrent/TimeUnit.java \
     java/util/concurrent/TimeoutException.java \
+    java/util/concurrent/TransferQueue.java \
     java/util/concurrent/atomic/AtomicBoolean.java \
     java/util/concurrent/atomic/AtomicInteger.java \
     java/util/concurrent/atomic/AtomicIntegerArray.java \
--- a/jdk/make/java/jli/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/jli/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -48,11 +48,15 @@
 LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin
 LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin
 
+ifeq ($(ZERO_BUILD), true)
+ERGO_FAMILY=zero
+else
 ifeq ($(ARCH_FAMILY), amd64)
 ERGO_FAMILY=i586
 else
 ERGO_FAMILY=$(ARCH_FAMILY)
 endif
+endif
 
 
 #
--- a/jdk/make/java/main/java/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/main/java/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -57,7 +57,7 @@
 #
 include $(BUILDDIR)/common/Program.gmk
 OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
-OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
+OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
 
 ifeq ($(PLATFORM), solaris)
 LDFLAGS += -R$(OPENWIN_LIB)
--- a/jdk/make/java/main/javaw/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/main/javaw/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -62,4 +62,5 @@
 #
 include $(BUILDDIR)/common/Program.gmk
 OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
-OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
+OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
+
--- a/jdk/make/java/nio/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/nio/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -335,6 +335,15 @@
 SCS_SRC=$(SNIO_SRC)/cs
 SFS_SRC=$(SNIO_SRC)/fs
 
+# Template files
+HEAP_X_BUF_TEMPLATE=$(BUF_SRC)/Heap-X-Buffer.java.template
+BYTE_X_BUF_TEMPLATE=$(BUF_SRC)/ByteBufferAs-X-Buffer.java.template
+X_BUF_TEMPLATE=$(BUF_SRC)/X-Buffer.java.template
+X_BUF_BIN_TEMPLATE=$(BUF_SRC)/X-Buffer-bin.java.template
+DIRECT_X_BUF_TEMPLATE=$(BUF_SRC)/Direct-X-Buffer.java.template
+DIRECT_X_BUF_BIN_TEMPLATE=$(BUF_SRC)/Direct-X-Buffer-bin.java.template
+CHARSET_X_CODER_TEMPLATE=$(CS_SRC)/Charset-X-Coder.java.template
+
 BUF_GEN=$(NIO_GEN)
 CH_GEN=$(NIO_GEN)/channels
 CS_GEN=$(NIO_GEN)/charset
@@ -357,39 +366,39 @@
 
 # Public abstract buffer classes
 #
-$(BUF_GEN)/ByteBuffer.java: $(BUF_SRC)/X-Buffer.java \
-			    $(BUF_SRC)/X-Buffer-bin.java \
+$(BUF_GEN)/ByteBuffer.java: $(X_BUF_TEMPLATE) \
+			    $(X_BUF_BIN_TEMPLATE) \
 			    $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte BIN=1 SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/CharBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/CharBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ShortBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ShortBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/IntBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/IntBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/LongBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/LongBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/FloatBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/FloatBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DoubleBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DoubleBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -397,72 +406,72 @@
 
 # Buffers whose contents are heap-allocated
 # 
-$(BUF_GEN)/HeapByteBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapByteBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapByteBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapByteBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapCharBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapCharBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapCharBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapCharBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapShortBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapShortBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapShortBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapShortBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapIntBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapIntBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapIntBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapIntBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapLongBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapLongBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapLongBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapLongBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapFloatBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapFloatBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapFloatBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapFloatBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapDoubleBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapDoubleBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapDoubleBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapDoubleBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -470,15 +479,15 @@
 
 # Direct byte buffer
 # 
-$(BUF_GEN)/DirectByteBuffer.java: $(BUF_SRC)/Direct-X-Buffer.java \
-				  $(BUF_SRC)/Direct-X-Buffer.java \
+$(BUF_GEN)/DirectByteBuffer.java: $(DIRECT_X_BUF_TEMPLATE) \
+				  $(DIRECT_X_BUF_TEMPLATE) \
 				  $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte BIN=1 SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectByteBuffer%.java: $(BUF_SRC)/Direct-X-Buffer.java \
-				   $(BUF_SRC)/Direct-X-Buffer.java \
+$(BUF_GEN)/DirectByteBuffer%.java: $(DIRECT_X_BUF_TEMPLATE) \
+				   $(DIRECT_X_BUF_TEMPLATE) \
 				   $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
@@ -487,62 +496,62 @@
 
 # Unswapped views of direct byte buffers
 #
-$(BUF_GEN)/DirectCharBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectCharBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -550,62 +559,62 @@
 
 # Swapped views of direct byte buffers
 #
-$(BUF_GEN)/DirectCharBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectCharBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -613,62 +622,62 @@
 
 # Big-endian views of byte buffers
 #
-$(BUF_GEN)/ByteBufferAsCharBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsCharBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -676,62 +685,62 @@
 
 # Little-endian views of byte buffers
 #
-$(BUF_GEN)/ByteBufferAsCharBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsCharBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -745,13 +754,13 @@
 
 GEN_CODER_CMD = SPP="$(SPP_CMD)" SED="$(SED)" NAWK="$(NAWK)" SH="$(SH)" $(SH) $(GEN_CODER_SH)
 
-$(CS_GEN)/CharsetDecoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH)
+$(CS_GEN)/CharsetDecoder.java: $(CHARSET_X_CODER_TEMPLATE) $(GEN_CODER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	$(GEN_CODER_CMD) decoder $< $@.temp
 	$(MV) $@.temp $@
 
-$(CS_GEN)/CharsetEncoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH)
+$(CS_GEN)/CharsetEncoder.java: $(CHARSET_X_CODER_TEMPLATE) $(GEN_CODER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	$(GEN_CODER_CMD) encoder $< $@.temp
--- a/jdk/make/java/nio/genBuffer.sh	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/nio/genBuffer.sh	Wed Jul 05 17:02:54 2017 +0200
@@ -154,7 +154,7 @@
   mv $DST $DST.tmp
   sed -e '/#BIN/,$d' <$DST.tmp >$DST
   rm -f $DST.tmp
-  binops=`dirname $SRC`/`basename $SRC .java`-bin.java
+  binops=`dirname $SRC`/`basename $SRC .java.template`-bin.java.template
   genBinOps char character 1 two one $binops >>$DST
   genBinOps short short 1 two one $binops >>$DST
   genBinOps int integer 2 four three $binops >>$DST
--- a/jdk/make/java/redist/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/redist/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -94,11 +94,13 @@
   endif
 endif # INCLUDE_SA
 
-# Hotspot client is only available on 32-bit builds
+# Hotspot client is only available on 32-bit non-Zero builds
+ifneq ($(ZERO_BUILD), true)
 ifeq ($(ARCH_DATA_MODEL), 32)
   IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME) \
                  $(LIB_LOCATION)/$(CLIENT_LOCATION)/Xusage.txt
 endif
+endif
 
 ifeq ($(PLATFORM), windows)
 #  Windows     vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv  Windows
@@ -171,6 +173,7 @@
   IMPORT_LIST += $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME)
 endif 
 
+ifneq ($(ZERO_BUILD), true)
 ifeq ($(ARCH_DATA_MODEL), 32)
 
 IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME)
@@ -201,6 +204,8 @@
 
 endif # 32bit
 
+endif # ZERO_BUILD
+
 #  NOT Windows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ NOT Windows
 
 endif # PLATFORM
--- a/jdk/make/java/version/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/java/version/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -33,7 +33,7 @@
 all build: $(GENSRCDIR)/sun/misc/Version.java
 
 $(GENSRCDIR)/sun/misc/Version.java: \
-		$(SHARE_SRC)/classes/sun/misc/Version-template.java
+		$(SHARE_SRC)/classes/sun/misc/Version.java.template
 	$(prep-target)
 	$(RM) $@.temp
 	$(SED) -e 's/@@launcher_name@@/$(LAUNCHER_NAME)/g' \
--- a/jdk/make/javax/sound/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/javax/sound/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -128,7 +128,7 @@
 
 # for dynamic inclusion of extra sound libs: these
 # JNI libs will be loaded from Platform.java
-CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS="\"$(EXTRA_SOUND_JNI_LIBS)\""
+CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
 
 # integrate MIDI i/o in jsound lib
 ifeq ($(INCLUDE_MIDI),TRUE)
--- a/jdk/make/javax/sound/SoundDefs.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/javax/sound/SoundDefs.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -55,21 +55,25 @@
 
 endif # PLATFORM solaris
 
-ifeq ($(ARCH), i586)
-  CPPFLAGS += -DX_ARCH=X_I586
-endif # ARCH i586
-
-ifeq ($(ARCH), sparc)
-  CPPFLAGS += -DX_ARCH=X_SPARC
-endif # ARCH sparc
+ifeq ($(ZERO_BUILD), true)
+  CPPFLAGS += -DX_ARCH=X_ZERO
+else
+  ifeq ($(ARCH), i586)
+    CPPFLAGS += -DX_ARCH=X_I586
+  endif # ARCH i586
 
-ifeq ($(ARCH), sparcv9)
-  CPPFLAGS += -DX_ARCH=X_SPARCV9
-endif # ARCH sparcv9
+  ifeq ($(ARCH), sparc)
+    CPPFLAGS += -DX_ARCH=X_SPARC
+  endif # ARCH sparc
 
-ifeq ($(ARCH), amd64)
-  CPPFLAGS += -DX_ARCH=X_AMD64
-endif # ARCH amd64
+  ifeq ($(ARCH), sparcv9)
+    CPPFLAGS += -DX_ARCH=X_SPARCV9
+  endif # ARCH sparcv9
+
+  ifeq ($(ARCH), amd64)
+    CPPFLAGS += -DX_ARCH=X_AMD64
+  endif # ARCH amd64
+endif
 
 
 # files needed for MIDI i/o
--- a/jdk/make/jdk_generic_profile.sh	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/jdk_generic_profile.sh	Wed Jul 05 17:02:54 2017 +0200
@@ -339,3 +339,82 @@
 PATH="${path4sdk}"
 export PATH
 
+# Export variables required for Zero
+if [ "${ZERO_BUILD}" = true ] ; then
+  # ZERO_LIBARCH is the name of the architecture-specific
+  # subdirectory under $JAVA_HOME/jre/lib
+  arch=$(uname -m)
+  case "${arch}" in
+    x86_64)  ZERO_LIBARCH=amd64     ;;
+    i?86)    ZERO_LIBARCH=i386      ;;
+    sparc64) ZERO_LIBARCH=sparcv9   ;;
+    arm*)    ZERO_LIBARCH=arm       ;;
+    *)       ZERO_LIBARCH="$(arch)"
+  esac
+  export ZERO_LIBARCH
+
+  # ARCH_DATA_MODEL is the number of bits in a pointer
+  case "${ZERO_LIBARCH}" in
+    i386|ppc|s390|sparc|arm)
+      ARCH_DATA_MODEL=32
+      ;;
+    amd64|ppc64|s390x|sparcv9|ia64|alpha)
+      ARCH_DATA_MODEL=64
+      ;;
+    *)
+      echo "ERROR: Unable to determine ARCH_DATA_MODEL for ${ZERO_LIBARCH}"
+      exit 1
+  esac
+  export ARCH_DATA_MODEL
+
+  # ZERO_ENDIANNESS is the endianness of the processor
+  case "${ZERO_LIBARCH}" in
+    i386|amd64|ia64)
+      ZERO_ENDIANNESS=little
+      ;;
+    ppc*|s390*|sparc*|alpha)
+      ZERO_ENDIANNESS=big
+      ;;
+    *)
+      echo "ERROR: Unable to determine ZERO_ENDIANNESS for ${ZERO_LIBARCH}"
+      exit 1
+  esac
+  export ZERO_ENDIANNESS
+
+  # ZERO_ARCHDEF is used to enable architecture-specific code
+  case "${ZERO_LIBARCH}" in
+    i386)   ZERO_ARCHDEF=IA32  ;;
+    ppc*)   ZERO_ARCHDEF=PPC   ;;
+    s390*)  ZERO_ARCHDEF=S390  ;;
+    sparc*) ZERO_ARCHDEF=SPARC ;;
+    *)      ZERO_ARCHDEF=$(echo "${ZERO_LIBARCH}" | tr a-z A-Z)
+  esac
+  export ZERO_ARCHDEF
+
+  # ZERO_ARCHFLAG tells the compiler which mode to build for
+  case "${ZERO_LIBARCH}" in
+    s390)
+      ZERO_ARCHFLAG="-m31"
+      ;;
+    *)
+      ZERO_ARCHFLAG="-m${ARCH_DATA_MODEL}"
+  esac
+  export ZERO_ARCHFLAG
+
+  # LIBFFI_CFLAGS and LIBFFI_LIBS tell the compiler how to compile and
+  # link against libffi
+  pkgconfig=$(which pkg-config 2>/dev/null)
+  if [ -x "${pkgconfig}" ] ; then
+    if [ "${LIBFFI_CFLAGS}" = "" ] ; then
+      LIBFFI_CFLAGS=$("${pkgconfig}" --cflags libffi)
+    fi
+    if [ "${LIBFFI_LIBS}" = "" ] ; then
+      LIBFFI_LIBS=$("${pkgconfig}" --libs libffi)
+    fi
+  fi
+  if [ "${LIBFFI_LIBS}" = "" ] ; then
+      LIBFFI_LIBS="-lffi"
+  fi
+  export LIBFFI_CFLAGS
+  export LIBFFI_LIBS
+fi
--- a/jdk/make/launchers/Makefile.launcher	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/launchers/Makefile.launcher	Wed Jul 05 17:02:54 2017 +0200
@@ -137,15 +137,15 @@
   #   PROGRAM, JAVA_ARGS, and APP_CLASSPATH are used in src/share/bin/java.c
   #   SA is currently not available on windows (for any ARCH), or linux-ia64:
   ifneq ($(ARCH), ia64)
-    JDB_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\" }"
-    OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JDB_CLASSPATH)
+    JDB_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
+    OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JDB_CLASSPATH)'
   endif
 endif
 
 # jconsole only
 ifeq ($(PROGRAM),jconsole)
-  JCONSOLE_CLASSPATH = "{ \"/lib/jconsole.jar\", \"/lib/tools.jar\", \"/classes\" }"
-  OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JCONSOLE_CLASSPATH)
+  JCONSOLE_CLASSPATH = { "/lib/jconsole.jar", "/lib/tools.jar", "/classes" }
+  OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JCONSOLE_CLASSPATH)'
   ifeq ($(PLATFORM), windows)
     OTHER_CPPFLAGS += -DJAVAW
     LDLIBS_COMMON  += user32.lib
@@ -163,8 +163,8 @@
 
 # SA tools need special app classpath
 ifeq ($(SA_TOOL),true)
-  SA_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\"}"
-  OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(SA_CLASSPATH)
+  SA_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
+  OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(SA_CLASSPATH)'
 endif
 
 # Wildcards
@@ -173,11 +173,11 @@
 endif
 
 # Always tell native code what the main class is
-OTHER_CPPFLAGS += -DMAIN_CLASS=\"$(MAIN_CLASS)\"
+OTHER_CPPFLAGS += -DMAIN_CLASS='"$(MAIN_CLASS)"'
 
 # Construct initializer for initial arguments to java
 ALL_ARGS = -J-ms8m $(MAIN_JAVA_ARGS) $(MAIN_CLASS) $(MAIN_ARGS)
-JAVA_ARGS = "{ $(ALL_ARGS:%=\"%\",)  }"
+JAVA_ARGS = { $(ALL_ARGS:%="%",)  }
 
 # Always report launcher info
 build: launcher_info
--- a/jdk/make/netbeans/jconsole/build.properties	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/netbeans/jconsole/build.properties	Wed Jul 05 17:02:54 2017 +0200
@@ -33,7 +33,7 @@
     com/sun/tools/jconsole/ \
     sun/tools/jconsole/
 excludes=\
-    sun/tools/jconsole/Version-template.java
+    sun/tools/jconsole/Version.java.template
 jtreg.tests=\
     sun/tools/jconsole/
 javadoc.packagenames=\
--- a/jdk/make/netbeans/jconsole/build.xml	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/netbeans/jconsole/build.xml	Wed Jul 05 17:02:54 2017 +0200
@@ -35,7 +35,7 @@
 
     <target name="-pre-compile">
         <copy
-            file="${root}/src/share/classes/sun/tools/jconsole/Version-template.java"
+            file="${root}/src/share/classes/sun/tools/jconsole/Version.java.template"
             tofile="${gensrc.dir}/sun/tools/jconsole/Version.java"/>
         <replace
             file="${gensrc.dir}/sun/tools/jconsole/Version.java"
--- a/jdk/make/sun/jconsole/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/sun/jconsole/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -70,7 +70,7 @@
 build: $(FILES_png) $(FILES_gif) $(TEMPDIR)/manifest $(JARFILE)
 
 $(GENSRCDIR)/sun/tools/jconsole/Version.java: \
-                $(SHARE_SRC)/classes/sun/tools/jconsole/Version-template.java
+                $(SHARE_SRC)/classes/sun/tools/jconsole/Version.java.template
 	$(MKDIR) -p $(@D)
 	$(SED) -e 's/@@jconsole_version@@/$(FULL_VERSION)/g' $< > $@
 
--- a/jdk/make/sun/nio/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/sun/nio/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -44,14 +44,6 @@
 include FILES_java.gmk
 AUTO_FILES_JAVA_DIRS = sun/nio/cs/ext
 
-# Exclude a few sources on windows
-ifeq ($(PLATFORM), windows)
-  AUTO_JAVA_PRUNE = sun/nio/cs/ext/COMPOUND_TEXT.java         \
-                    sun/nio/cs/ext/COMPOUND_TEXT_Decoder.java \
-                    sun/nio/cs/ext/COMPOUND_TEXT_Encoder.java \
-                    sun/nio/cs/ext/CompoundTextSupport.java
-endif # PLATFORM
-
 # For Cygwin, command line arguments that are paths must be converted to
 # windows style paths. These paths cannot be used as targets, however, because 
 # the ":" in them  will interfere with GNU Make rules, generating "multiple
--- a/jdk/make/tools/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/make/tools/Makefile	Wed Jul 05 17:02:54 2017 +0200
@@ -38,7 +38,6 @@
   compile_properties        \
   dir_diff                  \
   dtdbuilder                \
-  fontchecker               \
   freetypecheck             \
   generate_break_iterator   \
   GenerateCharacter         \
--- a/jdk/make/tools/fontchecker/Makefile	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#
-# Copyright 1998-2005 Sun Microsystems, Inc.  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.  Sun designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Sun 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 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.
-#
-
-#
-# Makefile for building the fontchecker tool
-#
-
-BUILDDIR = ../..
-PACKAGE = build.tools.fontchecker
-PRODUCT = tools
-PROGRAM = fontchecker
-include $(BUILDDIR)/common/Defs.gmk
-
-BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src
-BUILDTOOL_MAIN        = $(PKGDIR)/FontChecker.java
-
-#
-# Build tool jar rules.
-#
-include $(BUILDDIR)/common/BuildToolJar.gmk
-
--- a/jdk/make/tools/src/build/tools/fontchecker/FontCheckDummy.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-package build.tools.fontchecker;
-
-import java.awt.*;
-import java.awt.image.*;
-import java.io.*;
-
-/**
- * FontCheckDummy (not unlike Crash Test Dummy).
- *
- * <PRE>
- * FontCheckDummy is the "child" process. Its task is to verify
- * integrity of system fonts. Since unexpected crashes are known
- * to occur when certain fonts are manipulated, the process is
- * "monitored" by the parent process, which might have to restart
- * the "child" if it crashes.
- * </PRE>
- *
- * @author Ilya Bagrak
- */
-public class FontCheckDummy implements FontCheckerConstants {
-
-    /**
-     * Input stream from parent process.
-     */
-    private BufferedReader is;
-
-    /**
-     * Output stream to parent process.
-     */
-    private BufferedOutputStream os;
-
-    /**
-     * Image on which font characters will be drawn.
-     */
-    private BufferedImage bi;
-
-    /**
-     * graphics object on which characters will be drawn.
-     */
-    private Graphics graphics;
-
-    /**
-     * This constructor wraps the process's standard output and input streams
-     * to enable easier communication with parent process. It also initializes
-     * the graphics object used for drawing font characters.
-     * <BR><BR>
-     * @see FontCheckerConstants
-     */
-    public FontCheckDummy() {
-        is = new BufferedReader(new InputStreamReader(System.in));
-        os = new BufferedOutputStream(System.out);
-        /* make suffficient space for 12 point font */
-        bi = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
-        graphics = bi.getGraphics();
-        try {
-            os.write(CHILD_STARTED_OK);
-            os.flush();
-        } catch (IOException e) {
-            System.exit(-1);
-        }
-    }
-
-    /**
-     * Initializes an instance of Font from given font path.
-     * <BR>
-     * This methods attempts to create an instance of font from
-     * a string that represents path to the font file.
-     * <BR><BR>
-     * @param fontPath string representing path to font file
-     * @param flag indicating whether or not checking of non-TrueType fonts
-     * is necessary
-     */
-    private void testFont(String fontPath, boolean checkNonTTF) {
-
-        FontFileFilter fff = new FontFileFilter(checkNonTTF);
-        File fontFile = new File(fontPath);
-        if (!fontFile.canRead()) {
-            try {
-                os.write(ERR_FONT_NOT_FOUND);
-                os.flush();
-            } catch (IOException e) {
-                System.exit(-1);
-            }
-        }
-        Font font = null;
-        try {
-            File file = new File(fontPath);
-            font = Font.createFont(fff.getFontType(fontPath), file);
-        } catch (FontFormatException e1) {
-        } catch (IOException e2) {
-        }
-        if (font == null) {
-             return;
-        }
-        font = font.deriveFont(Font.PLAIN, 12);
-        String name = font.getFontName();
-        String family = font.getFamily();
-
-        char[] testChars = { '0' };
-        if (font.canDisplay(testChars[0])) {
-            graphics.setFont(font);
-            graphics.drawChars(testChars, 0, 1, 20, 20);
-        }
-        try {
-            os.write(ERR_FONT_OK);
-            os.flush();
-        } catch (IOException e) {
-            System.exit(-1);
-        }
-    }
-
-    /**
-     * Begins synchronous communication betweeen parent and child processes.
-     * <BR>
-     * This method begins communication between parent and child processes.
-     * FontCheckDummy reads a line of text from input stream (@see #is).
-     */
-    public void run() {
-        String command = null;
-        while (true) {
-            try {
-                command = is.readLine();
-            } catch (IOException e) {
-                System.exit(-1);
-            }
-            if (command != null && command.length() >= 1) {
-                int cmd = Integer.parseInt(command.substring(0,1));
-                if (cmd == EXITCOMMAND) {
-                    return;
-                }
-                boolean checkNonTTF = ((cmd == 1) ? true : false);
-                String fontPath = command.substring(1);
-                testFont(fontPath, checkNonTTF);
-            } else {
-                return;
-            }
-        }
-    }
-
-    public static void main(String[] args) {
-        try {
-            /* Background app. */
-            System.setProperty("java.awt.headless", "true");
-            System.setProperty("sun.java2d.noddraw", "true");
-            new FontCheckDummy().run();
-        } catch (Throwable t) {
-        }
-        System.exit(0);
-    }
-}
--- a/jdk/make/tools/src/build/tools/fontchecker/FontChecker.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,452 +0,0 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-package build.tools.fontchecker;
-
-import java.io.*;
-import java.util.*;
-import java.awt.event.*;
-import sun.font.FontManager;
-
-/**
- * FontChecker.
- *
- * <PRE>
- * This is a FontChecker program. This class is a "parent" process
- * which invokes a "child" process. The child process will test
- * series of fonts and may crash as it encounters invalid fonts.
- * The "parent" process must then interpret error codes passed to it
- * by the "child" process and restart the "child" process if necessary.
- *
- * usage: java FontChecker [-v] -o outputfile
- *
- *        -o is the name of the file to contains canonical path names of
- *           bad fonts that are identified. This file is not created if
- *           no bad fonts are found.
- *        -v verbose: prints progress messages.
- *
- * </PRE>
- *
- * @author Ilya Bagrak
- */
-public class FontChecker implements ActionListener, FontCheckerConstants {
-
-    /**
-     * Output stream to subprocess.
-     * Corresponds to the subprocess's System.in".
-     */
-    private PrintWriter procPipeOut;
-
-    /**
-     * Input stream from subprocess.
-     * Corresponds to the subprocess's System.out".
-     */
-    private BufferedInputStream procPipeIn;
-
-    /**
-     * Child process.
-     */
-    private Process childProc;
-
-    /**
-     * Name of output file to write file names of bad fonts
-     */
-    private String outputFile;
-
-    /**
-     * Reference to currently executing thread.
-     */
-    private Thread currThread;
-
-    /**
-     * Timeout timer for a single font check
-     */
-    private javax.swing.Timer timeOne;
-
-    /**
-     * Timeout timer for all font checks
-     */
-    private javax.swing.Timer timeAll;
-
-    /**
-     * max time (in milliseconds) allowed for checking a single font.
-     */
-    private static int timeoutOne = 10000;
-
-    /**
-     * max time (in milliseconds) allowed for checking all fonts.
-     */
-    private static int timeoutAll = 120000;
-
-    /**
-     * Boolean flag indicating whether FontChecker is required to
-     * check non-TrueType fonts.
-     */
-    private boolean checkNonTTF = false;
-
-    /**
-     * List of bad fonts found in the system.
-     */
-    private Vector badFonts = new Vector();
-
-    /**
-     * whether to print warnings messges etc to stdout/err
-     * default is false
-     */
-    private static boolean verbose = false;
-
-    /* Command to use to exec sub-process. */
-    private static String javaCmd = "java";
-
-    static void printlnMessage(String s) {
-        if (verbose) {
-            System.out.println(s);
-        }
-    }
-
-    /**
-     * Event handler for timer event.
-     * <BR>
-     * Stops the timer and interrupts the current thread which is
-     * still waiting on I/O from the child process.
-     * <BR><BR>
-     * @param evt timer event
-     */
-    public void actionPerformed(ActionEvent evt) {
-        if (evt.getSource() == timeOne) {
-            timeOne.stop();
-            printlnMessage("Child timed out: killing");
-            childProc.destroy();
-        } else {
-            doExit(); // went on too long (ie timeAll timed out).
-        }
-    }
-
-    /**
-     * Initializes a FontChecker.
-     * <BR>
-     * This method is usually called after an unrecoverable error has
-     * been detected and a child process has  either crashed or is in bad
-     * state. The method creates a new child process from
-     * scratch and initializes it's input/output streams.
-     */
-    public void initialize() {
-        try {
-            if (childProc != null) {
-                childProc.destroy();
-            }
-            String fileSeparator = System.getProperty("file.separator");
-            String javaHome = System.getProperty("java.home");
-            String classPath =  System.getProperty("java.class.path");
-            classPath = "\"" + classPath + "\"";
-            String opt = "-cp " + classPath + " -Dsun.java2d.fontpath=\"" +
-                javaHome + fileSeparator + "lib" + fileSeparator + "fonts\"";
-
-            /* command to exec the child process with the same JRE */
-            String cmd =
-                new String(javaHome + fileSeparator + "bin" +
-                           fileSeparator + javaCmd +
-                           " -XXsuppressExitMessage " + opt +
-                           " com.sun.java2d.fontchecker.FontCheckDummy");
-            printlnMessage("cmd="+cmd);
-            childProc = Runtime.getRuntime().exec(cmd);
-
-        } catch (IOException e) {
-            printlnMessage("can't execute child process");
-            System.exit(0);
-        } catch (SecurityException e) {
-            printlnMessage("Error: access denied");
-            System.exit(0);
-        }
-
-        /* initialize input/output streams to/from child process */
-        procPipeOut = new PrintWriter(childProc.getOutputStream());
-        procPipeIn = new BufferedInputStream(childProc.getInputStream());
-
-        try {
-            int code = procPipeIn.read();
-            if (code != CHILD_STARTED_OK) {
-                printlnMessage("bad child process start status="+code);
-                doExit();
-            }
-        } catch (IOException e) {
-            printlnMessage("can't read child process start status unknown");
-            doExit();
-        }
-    }
-
-    private void doExit() {
-        try {
-            if (procPipeOut != null) {
-                /* Tell the child to exit */
-                procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
-                procPipeOut.flush();
-                procPipeOut.close();
-            }
-        } catch (Throwable t) {
-        }
-        System.exit(0);
-    }
-
-    /**
-     * Tries to verify integrity of a font specified by a path.
-     * <BR>
-     * This method is used to test whether a font specified by the given
-     * path is valid and does not crash the system.
-     * <BR><BR>
-     * @param fontPath a string representation of font path
-     * to standard out during while this font is tried
-     * @return returns <code>true</code> if font is OK, and
-     * <code>false</code> otherwise.
-     */
-    public boolean tryFont(File fontFile) {
-        int bytesRead = 0;
-        String fontPath = fontFile.getAbsolutePath();
-
-        printlnMessage("Checking font "+fontPath);
-
-        /* store reference to the current thread, so that when the timer
-         * fires it can be interrupted
-         */
-        currThread = Thread.currentThread();
-        timeOne.restart();
-
-        /* write a string command out to child process
-         * The command is formed by appending whether to test non-TT fonts
-         * and font path to be tested
-         */
-        String command = Integer.toString(checkNonTTF ? 1 : 0) +
-                         fontPath +
-                         System.getProperty("line.separator");
-        procPipeOut.write(command);
-        procPipeOut.flush();
-
-        /* check if underlying stream has encountered an error after
-         * command has been issued
-         */
-        if (procPipeOut.checkError()){
-            printlnMessage("Error: font crashed");
-            initialize();
-            return false;
-        }
-
-        /* trying reading error code back from child process */
-        try {
-            bytesRead = procPipeIn.read();
-        } catch(InterruptedIOException e) {
-            /* A timeout timer fired before the operation completed */
-            printlnMessage("Error: timeout occured");
-            initialize();
-            return false;
-        } catch(IOException e) {
-            /* there was an error reading from the stream */
-            timeOne.stop();
-            printlnMessage("Error: font crashed");
-            initialize();
-            return false;
-        } catch (Throwable t) {
-            bytesRead = ERR_FONT_READ_EXCPT;
-        } finally {
-          timeOne.stop();
-        }
-
-        if (bytesRead == ERR_FONT_OK) {
-            printlnMessage("Font integrity verified");
-            return true;
-        } else if (bytesRead > 0) {
-
-            switch(bytesRead){
-            case ERR_FONT_NOT_FOUND:
-                printlnMessage("Error: font not found!");
-                break;
-            case ERR_FONT_BAD_FORMAT:
-                printlnMessage("Error: incorrect font format");
-                break;
-            case ERR_FONT_READ_EXCPT:
-                printlnMessage("Error: exception reading font");
-                break;
-            case ERR_FONT_DISPLAY:
-                printlnMessage("Error: can't display characters");
-                break;
-            case ERR_FONT_CRASH:
-                printlnMessage("Error: font crashed");
-                break;
-            default:
-                printlnMessage("Error: invalid error code:"+bytesRead);
-                break;
-
-            }
-        } else if (bytesRead == ERR_FONT_EOS) {
-            printlnMessage("Error: end of stream marker encountered");
-        } else {
-            printlnMessage("Error: invalid error code:"+bytesRead);
-        }
-
-        /* if we still haven't returned from this method, some error
-         * condition has occured and it is safer to re-initialize
-         */
-        initialize();
-        return false;
-    }
-
-    /**
-     * Checks the integrity of all system fonts.
-     * <BR>
-     * This method goes through every font in system's font path and verifies
-     * its integrity via the tryFont method.
-     * <BR><BR>
-     * @param restart <code>true</code> if checking of fonts should continue
-     * after the first  bad font is found, and <code>false</code> otherwise
-     * @return returns <code>true</code> if all fonts are valid,
-     * <code>false</code> otherwise
-     * @see #tryFont(String, boolean, boolean)
-     */
-    public boolean checkFonts(boolean restart) {
-
-        /* file filter to filter out none-truetype font files */
-        FontFileFilter fff = new FontFileFilter(checkNonTTF);
-        boolean checkOk = true;
-
-        /* get platform-independent font path. Note that this bypasses
-         * the normal GraphicsEnvironment initialisation. In conjunction with
-         * the headless setting above, so we want to add
-         * java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
-         * to trigger a more normal initialisation.
-         */
-        java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
-        String fontPath = FontManager.getFontPath(true);
-        StringTokenizer st =
-            new StringTokenizer(fontPath,
-                                System.getProperty("path.separator"));
-
-        /* some systems may have multiple font paths separated by
-         * platform-dependent characters, so fontPath string needs to be
-         * parsed
-         */
-        timeOne = new javax.swing.Timer(timeoutOne, this);
-        timeAll = new javax.swing.Timer(timeoutAll, this);
-        timeAll.restart();
-        while (st.hasMoreTokens()) {
-            File fontRoot = new File(st.nextToken());
-            File[] fontFiles = fontRoot.listFiles(fff);
-
-            for (int i = 0; i < fontFiles.length; i++) {
-                /* for each font file that is not a directory and passes
-                 * through the font filter run the test
-                 */
-                if (!fontFiles[i].isDirectory() &&
-                    !tryFont(fontFiles[i])) {
-
-                    checkOk = false;
-                    badFonts.add(fontFiles[i].getAbsolutePath());
-                    if (!restart) {
-                        break;
-                    }
-                }
-            }
-        }
-
-        /* Tell the child to exit */
-        procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
-        procPipeOut.flush();
-        procPipeOut.close();
-
-        return checkOk;
-    }
-
-    public static void main(String args[]){
-        try {
-            /* Background app. */
-            System.setProperty("java.awt.headless", "true");
-            System.setProperty("sun.java2d.noddraw", "true");
-
-            boolean restart = true;
-            boolean errorFlag = false;
-
-            FontChecker fc = new FontChecker();
-            int arg = 0;
-
-            while (arg < args.length && errorFlag == false) {
-                if (args[arg].equals("-v")) {
-                    verbose = true;
-                }
-                else if (args[arg].equals("-w") &&
-                         System.getProperty("os.name", "unknown").
-                         startsWith("Windows")) {
-                    javaCmd = "javaw";
-                }
-                else if (args[arg].equals("-o")) {
-                    /* set output file */
-                    if (++arg < args.length)
-                        fc.outputFile = args[arg];
-                    else {
-                        /* invalid argument format */
-                        printlnMessage("Error: invalid argument format");
-                        errorFlag = true;
-                    }
-                }
-                else {
-                    /* invalid command line argument */
-                    printlnMessage("Error: invalid argument value");
-                    errorFlag = true;
-                }
-                arg++;
-            }
-
-            if (errorFlag || fc.outputFile == null) {
-                System.exit(0);
-            }
-
-            File outfile = new File(fc.outputFile);
-            if (outfile.exists()) {
-                outfile.delete();
-            }
-
-            fc.initialize();
-
-            if (!fc.checkFonts(restart)) {
-                String[] badFonts = (String[])fc.badFonts.toArray(new String[0]);
-                if (badFonts.length > 0) {
-                    printlnMessage("Bad Fonts:");
-                    try {
-                        FileOutputStream fos =
-                            new FileOutputStream(fc.outputFile);
-                        PrintStream ps = new  PrintStream(fos);
-                        for (int i = 0; i < badFonts.length; i++) {
-                            ps.println(badFonts[i]);
-                            printlnMessage(badFonts[i]);
-                        }
-                        fos.close();
-                    } catch (IOException e) {
-                    }
-                }
-            } else {
-                printlnMessage("No bad fonts found.");
-        }
-        } catch (Throwable t) {
-        }
-        System.exit(0);
-    }
-}
--- a/jdk/make/tools/src/build/tools/fontchecker/FontCheckerConstants.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-package build.tools.fontchecker;
-
-public interface FontCheckerConstants {
-
-    /* code sent to indicate child process started OK */
-    public static final int CHILD_STARTED_OK   = 100;
-
-    /* error codes returned from child process */
-    public static final int ERR_FONT_OK         = 65;
-    public static final int ERR_FONT_NOT_FOUND  = 60;
-    public static final int ERR_FONT_BAD_FORMAT = 61;
-    public static final int ERR_FONT_READ_EXCPT = 62;
-    public static final int ERR_FONT_DISPLAY    = 64;
-    public static final int ERR_FONT_EOS        = -1;
-    /* nl char sent after child crashes */
-    public static final int ERR_FONT_CRASH      = 10;
-
-    /* 0 and 1 are reserved, and commands can only be a single digit integer */
-    public static final int EXITCOMMAND = 2;
-}
--- a/jdk/make/tools/src/build/tools/fontchecker/FontFileFilter.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright 2002-2003 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-/*
- * <PRE>
- * This class filters TrueType font files from other file
- * found in the font path.
- *
- * </PRE>
- *
- * @author Ilya Bagrak
- */
-
-package build.tools.fontchecker;
-
-import java.awt.*;
-import java.io.*;
-
-public class FontFileFilter implements java.io.FileFilter, FontCheckerConstants {
-
-    /**
-     * Boolean flag indicating whether this filter filters out
-     * non-TrueType fonts.
-     */
-    private boolean checkNonTTF;
-
-    public FontFileFilter() {
-        this(false);
-    }
-
-    public FontFileFilter(boolean checkNonTTF) {
-        super();
-        this.checkNonTTF = checkNonTTF;
-    }
-
-    /**
-     * Checks whether a file is accepted by this filter.
-     * <BR>
-     * This method checks whehter a file is accepted by this filter.
-     * This filter is made to accept all the file whose extension is
-     * either .ttf or .TTF. These files are assumed to be TrueType fonts.
-     * <BR><BR>
-     * @return returns a boolean value indicating whether or not a file is
-     * accepted
-     */
-    public boolean accept(File pathname) {
-
-        String name = pathname.getName();
-        return (name.endsWith(".ttf") ||
-                name.endsWith(".TTF") ||
-                name.endsWith(".ttc") ||
-                name.endsWith(".TTC"))  ||
-            (name.endsWith(".pfb") ||
-             name.endsWith(".PFB") ||
-             name.endsWith(".pfa") ||
-             name.endsWith(".PFA") &&
-             checkNonTTF == true);
-    }
-
-    public static int getFontType(String filename) {
-        if (filename.endsWith(".ttf") ||
-            filename.endsWith(".TTF") ||
-            filename.endsWith(".ttc") ||
-            filename.endsWith(".TTC"))
-            return Font.TRUETYPE_FONT;
-        else if (filename.endsWith(".pfb") ||
-                 filename.endsWith(".PFB") ||
-                 filename.endsWith(".pfa") ||
-                 filename.endsWith(".PFA"))
-            return Font.TYPE1_FONT;
-        else
-            return 999;
-    }
-
-}
--- a/jdk/make/tools/src/build/tools/fontchecker/README.txt	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2002-2003 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-Instructions for running FontChecker 
-------------------------------------
-
-FontChecker is a program designed to identify fonts that may cause JRE
-crashes. Such fonts may be corrupted files, or badly constructed fonts.
-Some crashes may also be due to bugs in the JRE's font code.
-This test is designed to run quickly and silently as part of the JRE
-installation process. It will only benefit users who install the JRE
-via that mechanism. It cannot guarantee to identify all "bad fonts" because
-the tests are minimal. Nor can it prevent problems due to fonts installed
-subsequently to the JRE's installation. However it does ensure that the
-vast majority of problem fonts are identified. This is important
-"RAS" functionality. It is targeted at the consumer/plugin market where
-there is substantial likelihood of end-users having installed software
-packages which may be delivered with fonts that are not up to commercial
-standards.
-
-The test is designed to be "fail safe". If the program fails to run
-properly it has no impact on the installer or on JRE execution.
-Thus there is no need to monitor successful execution of the test.
-
-The test is not a new "tool" in the sense of "javah" etc.
-The test is not designed to be user executable or visible, and should
-be unpacked by the installer into a temporary location, and executed
-once the rest of the JRE is installed (ie as a postinstall step), and
-can then be deleted from the temporary location once installation is
-complete. Not deleting the jar file before execution is complete is
-probably the sole reason that the installer may want to wait for
-the program to complete.
-
-The FontChecker application can be run directly from the jar 
-file with this command: 
-	%java -jar fontchecker.jar -o <file>
-
-The output file is a required parameter in this version of the application.
-The JRE installer should use the above form, and use it to create an
-output file which must be named "badfonts.txt" and be placed into
-the JRE's lib\fonts directory eg:-
-
-        java -jar fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
-
-Note the lower case "badfonts.txt", and the string quotes because of the spaces
-in the path name.
-The location given here is an example and needs to be calculated at install
-time as $JREHOME\lib\fonts\badfonts.txt
-The location and name are important, because the JRE at runtime will
-look for this exactly located name and file.
-This location is private to that JRE instance. It will not affect
-any other JRE installed on the system.
-
-If running from a different directory than that containing the jar file,
-use the form containing the full path to the jar file, eg :
-
-	java -jar C:\fc\fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
-
-FontChecker application accepts following command line flags. 
-usage: java -jar fontchecker.jar -o outputfile
-	                -v 
-
-       -o is the name of the file to contains canonical path names of
-          bad fonts that are identified. This file is not created if
-          no bad fonts are found.
-
-       -v verbose mode: print progress/warning messages. Not recommended
-         for installer use.
-
-       -w if running on Windows, use "javaw" to exec the sub-process.
--- a/jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-
-class ByteBufferAs$Type$Buffer$RW$$BO$                  // package-private
-    extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
-{
-
-#if[rw]
-
-    protected final ByteBuffer bb;
-    protected final int offset;
-
-#end[rw]
-
-    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb) {   // package-private
-#if[rw]
-        super(-1, 0,
-              bb.remaining() >> $LG_BYTES_PER_VALUE$,
-              bb.remaining() >> $LG_BYTES_PER_VALUE$);
-        this.bb = bb;
-        // enforce limit == capacity
-        int cap = this.capacity();
-        this.limit(cap);
-        int pos = this.position();
-        assert (pos <= cap);
-        offset = pos;
-#else[rw]
-        super(bb);
-#end[rw]
-    }
-
-    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
-                                     int mark, int pos, int lim, int cap,
-                                     int off)
-    {
-#if[rw]
-        super(mark, pos, lim, cap);
-        this.bb = bb;
-        offset = off;
-#else[rw]
-        super(bb, mark, pos, lim, cap, off);
-#end[rw]
-    }
-
-    public $Type$Buffer slice() {
-        int pos = this.position();
-        int lim = this.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-        int off = (pos << $LG_BYTES_PER_VALUE$) + offset;
-        assert (off >= 0);
-        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, off);
-    }
-
-    public $Type$Buffer duplicate() {
-        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb,
-                                                    this.markValue(),
-                                                    this.position(),
-                                                    this.limit(),
-                                                    this.capacity(),
-                                                    offset);
-    }
-
-    public $Type$Buffer asReadOnlyBuffer() {
-#if[rw]
-        return new ByteBufferAs$Type$BufferR$BO$(bb,
-                                                 this.markValue(),
-                                                 this.position(),
-                                                 this.limit(),
-                                                 this.capacity(),
-                                                 offset);
-#else[rw]
-        return duplicate();
-#end[rw]
-    }
-
-#if[rw]
-
-    protected int ix(int i) {
-        return (i << $LG_BYTES_PER_VALUE$) + offset;
-    }
-
-    public $type$ get() {
-        return Bits.get$Type$$BO$(bb, ix(nextGetIndex()));
-    }
-
-    public $type$ get(int i) {
-        return Bits.get$Type$$BO$(bb, ix(checkIndex(i)));
-    }
-
-#end[rw]
-
-    public $Type$Buffer put($type$ x) {
-#if[rw]
-        Bits.put$Type$$BO$(bb, ix(nextPutIndex()), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put(int i, $type$ x) {
-#if[rw]
-        Bits.put$Type$$BO$(bb, ix(checkIndex(i)), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer compact() {
-#if[rw]
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-
-        ByteBuffer db = bb.duplicate();
-        db.limit(ix(lim));
-        db.position(ix(0));
-        ByteBuffer sb = db.slice();
-        sb.position(pos << $LG_BYTES_PER_VALUE$);
-        sb.compact();
-        position(rem);
-        limit(capacity());
-        discardMark();
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public boolean isDirect() {
-        return bb.isDirect();
-    }
-
-    public boolean isReadOnly() {
-        return {#if[rw]?false:true};
-    }
-
-#if[char]
-
-    public String toString(int start, int end) {
-        if ((end > limit()) || (start > end))
-            throw new IndexOutOfBoundsException();
-        try {
-            int len = end - start;
-            char[] ca = new char[len];
-            CharBuffer cb = CharBuffer.wrap(ca);
-            CharBuffer db = this.duplicate();
-            db.position(start);
-            db.limit(end);
-            cb.put(db);
-            return new String(ca);
-        } catch (StringIndexOutOfBoundsException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-
-    // --- Methods to support CharSequence ---
-
-    public CharBuffer subSequence(int start, int end) {
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        pos = (pos <= lim ? pos : lim);
-        int len = lim - pos;
-
-        if ((start < 0) || (end > len) || (start > end))
-            throw new IndexOutOfBoundsException();
-        return new ByteBufferAsCharBuffer$RW$$BO$(bb,
-                                                  -1,
-                                                  pos + start,
-                                                  pos + end,
-                                                  capacity(),
-                                                  offset);
-    }
-
-#end[char]
-
-
-    public ByteOrder order() {
-#if[boB]
-        return ByteOrder.BIG_ENDIAN;
-#end[boB]
-#if[boL]
-        return ByteOrder.LITTLE_ENDIAN;
-#end[boL]
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+
+class ByteBufferAs$Type$Buffer$RW$$BO$                  // package-private
+    extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
+{
+
+#if[rw]
+
+    protected final ByteBuffer bb;
+    protected final int offset;
+
+#end[rw]
+
+    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb) {   // package-private
+#if[rw]
+        super(-1, 0,
+              bb.remaining() >> $LG_BYTES_PER_VALUE$,
+              bb.remaining() >> $LG_BYTES_PER_VALUE$);
+        this.bb = bb;
+        // enforce limit == capacity
+        int cap = this.capacity();
+        this.limit(cap);
+        int pos = this.position();
+        assert (pos <= cap);
+        offset = pos;
+#else[rw]
+        super(bb);
+#end[rw]
+    }
+
+    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
+                                     int mark, int pos, int lim, int cap,
+                                     int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        this.bb = bb;
+        offset = off;
+#else[rw]
+        super(bb, mark, pos, lim, cap, off);
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = (pos << $LG_BYTES_PER_VALUE$) + offset;
+        assert (off >= 0);
+        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, off);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb,
+                                                    this.markValue(),
+                                                    this.position(),
+                                                    this.limit(),
+                                                    this.capacity(),
+                                                    offset);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new ByteBufferAs$Type$BufferR$BO$(bb,
+                                                 this.markValue(),
+                                                 this.position(),
+                                                 this.limit(),
+                                                 this.capacity(),
+                                                 offset);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    protected int ix(int i) {
+        return (i << $LG_BYTES_PER_VALUE$) + offset;
+    }
+
+    public $type$ get() {
+        return Bits.get$Type$$BO$(bb, ix(nextGetIndex()));
+    }
+
+    public $type$ get(int i) {
+        return Bits.get$Type$$BO$(bb, ix(checkIndex(i)));
+    }
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        Bits.put$Type$$BO$(bb, ix(nextPutIndex()), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        Bits.put$Type$$BO$(bb, ix(checkIndex(i)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        ByteBuffer db = bb.duplicate();
+        db.limit(ix(lim));
+        db.position(ix(0));
+        ByteBuffer sb = db.slice();
+        sb.position(pos << $LG_BYTES_PER_VALUE$);
+        sb.compact();
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return bb.isDirect();
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new ByteBufferAsCharBuffer$RW$$BO$(bb,
+                                                  -1,
+                                                  pos + start,
+                                                  pos + end,
+                                                  capacity(),
+                                                  offset);
+    }
+
+#end[char]
+
+
+    public ByteOrder order() {
+#if[boB]
+        return ByteOrder.BIG_ENDIAN;
+#end[boB]
+#if[boL]
+        return ByteOrder.LITTLE_ENDIAN;
+#end[boL]
+    }
+
+}
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer-bin.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright 2000-2003 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-class XXX {
-
-#begin
-
-#if[rw]
-
-    private $type$ get$Type$(long a) {
-        if (unaligned) {
-            $memtype$ x = unsafe.get$Memtype$(a);
-            return $fromBits$(nativeByteOrder ? x : Bits.swap(x));
-        }
-        return Bits.get$Type$(a, bigEndian);
-    }
-
-    public $type$ get$Type$() {
-        return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
-    }
-
-    public $type$ get$Type$(int i) {
-        return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
-    }
-
-#end[rw]
-
-    private ByteBuffer put$Type$(long a, $type$ x) {
-#if[rw]
-        if (unaligned) {
-            $memtype$ y = $toBits$(x);
-            unsafe.put$Memtype$(a, (nativeByteOrder ? y : Bits.swap(y)));
-        } else {
-            Bits.put$Type$(a, x, bigEndian);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public ByteBuffer put$Type$($type$ x) {
-#if[rw]
-        put$Type$(ix(nextPutIndex($BYTES_PER_VALUE$)), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public ByteBuffer put$Type$(int i, $type$ x) {
-#if[rw]
-        put$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer as$Type$Buffer() {
-        int off = this.position();
-        int lim = this.limit();
-        assert (off <= lim);
-        int rem = (off <= lim ? lim - off : 0);
-
-        int size = rem >> $LG_BYTES_PER_VALUE$;
-        if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
-            return (bigEndian
-                    ? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
-                                                                       -1,
-                                                                       0,
-                                                                       size,
-                                                                       size,
-                                                                       off))
-                    : ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$L(this,
-                                                                       -1,
-                                                                       0,
-                                                                       size,
-                                                                       size,
-                                                                       off)));
-        } else {
-            return (nativeByteOrder
-                    ? ($Type$Buffer)(new Direct$Type$Buffer$RW$U(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off))
-                    : ($Type$Buffer)(new Direct$Type$Buffer$RW$S(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off)));
-        }
-    }
-
-#end
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer-bin.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+class XXX {
+
+#begin
+
+#if[rw]
+
+    private $type$ get$Type$(long a) {
+        if (unaligned) {
+            $memtype$ x = unsafe.get$Memtype$(a);
+            return $fromBits$(nativeByteOrder ? x : Bits.swap(x));
+        }
+        return Bits.get$Type$(a, bigEndian);
+    }
+
+    public $type$ get$Type$() {
+        return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
+    }
+
+    public $type$ get$Type$(int i) {
+        return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
+    }
+
+#end[rw]
+
+    private ByteBuffer put$Type$(long a, $type$ x) {
+#if[rw]
+        if (unaligned) {
+            $memtype$ y = $toBits$(x);
+            unsafe.put$Memtype$(a, (nativeByteOrder ? y : Bits.swap(y)));
+        } else {
+            Bits.put$Type$(a, x, bigEndian);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ByteBuffer put$Type$($type$ x) {
+#if[rw]
+        put$Type$(ix(nextPutIndex($BYTES_PER_VALUE$)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ByteBuffer put$Type$(int i, $type$ x) {
+#if[rw]
+        put$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer as$Type$Buffer() {
+        int off = this.position();
+        int lim = this.limit();
+        assert (off <= lim);
+        int rem = (off <= lim ? lim - off : 0);
+
+        int size = rem >> $LG_BYTES_PER_VALUE$;
+        if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
+            return (bigEndian
+                    ? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
+                                                                       -1,
+                                                                       0,
+                                                                       size,
+                                                                       size,
+                                                                       off))
+                    : ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$L(this,
+                                                                       -1,
+                                                                       0,
+                                                                       size,
+                                                                       size,
+                                                                       off)));
+        } else {
+            return (nativeByteOrder
+                    ? ($Type$Buffer)(new Direct$Type$Buffer$RW$U(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                    : ($Type$Buffer)(new Direct$Type$Buffer$RW$S(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+        }
+    }
+
+#end
+
+}
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,464 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-import sun.misc.Cleaner;
-import sun.misc.Unsafe;
-import sun.nio.ch.DirectBuffer;
-
-
-class Direct$Type$Buffer$RW$$BO$
-#if[rw]
-    extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
-#else[rw]
-    extends Direct$Type$Buffer$BO$
-#end[rw]
-    implements DirectBuffer
-{
-
-#if[rw]
-
-    // Cached unsafe-access object
-    protected static final Unsafe unsafe = Bits.unsafe();
-
-    // Cached array base offset
-    private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
-
-    // Cached unaligned-access capability
-    protected static final boolean unaligned = Bits.unaligned();
-
-    // Base address, used in all indexing calculations
-    // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
-    //    protected long address;
-
-    // If this buffer is a view of another buffer then we keep a reference to
-    // that buffer so that its memory isn't freed before we're done with it
-    protected Object viewedBuffer = null;
-
-    public Object viewedBuffer() {
-        return viewedBuffer;
-    }
-
-#if[byte]
-
-    private static class Deallocator
-        implements Runnable
-    {
-
-        private static Unsafe unsafe = Unsafe.getUnsafe();
-
-        private long address;
-        private long size;
-        private int capacity;
-
-        private Deallocator(long address, long size, int capacity) {
-            assert (address != 0);
-            this.address = address;
-            this.size = size;
-            this.capacity = capacity;
-        }
-
-        public void run() {
-            if (address == 0) {
-                // Paranoia
-                return;
-            }
-            unsafe.freeMemory(address);
-            address = 0;
-            Bits.unreserveMemory(size, capacity);
-        }
-
-    }
-
-    private final Cleaner cleaner;
-
-    public Cleaner cleaner() { return cleaner; }
-
-#else[byte]
-
-    public Cleaner cleaner() { return null; }
-
-#end[byte]
-
-#end[rw]
-
-#if[byte]
-
-    // Primary constructor
-    //
-    Direct$Type$Buffer$RW$(int cap) {                   // package-private
-#if[rw]
-        super(-1, 0, cap, cap, false);
-        int ps = Bits.pageSize();
-        int size = cap + ps;
-        Bits.reserveMemory(size, cap);
-
-        long base = 0;
-        try {
-            base = unsafe.allocateMemory(size);
-        } catch (OutOfMemoryError x) {
-            Bits.unreserveMemory(size, cap);
-            throw x;
-        }
-        unsafe.setMemory(base, size, (byte) 0);
-        if (base % ps != 0) {
-            // Round up to page boundary
-            address = base + ps - (base & (ps - 1));
-        } else {
-            address = base;
-        }
-        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
-#else[rw]
-        super(cap);
-#end[rw]
-    }
-
-#if[rw]
-
-    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
-    //
-    private Direct$Type$Buffer(long addr, int cap) {
-        super(-1, 0, cap, cap, false);
-        address = addr;
-        cleaner = null;
-    }
-
-#end[rw]
-
-    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
-    //
-    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
-#if[rw]
-        super(-1, 0, cap, cap, true);
-        address = addr;
-        viewedBuffer = null;
-        cleaner = Cleaner.create(this, unmapper);
-#else[rw]
-        super(cap, addr, unmapper);
-#end[rw]
-    }
-
-#end[byte]
-
-    // For duplicates and slices
-    //
-    Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
-                               int mark, int pos, int lim, int cap,
-                               int off)
-    {
-#if[rw]
-        super(mark, pos, lim, cap);
-        address = db.address() + off;
-        viewedBuffer = db;
-#if[byte]
-        cleaner = null;
-#end[byte]
-#else[rw]
-        super(db, mark, pos, lim, cap, off);
-#end[rw]
-    }
-
-    public $Type$Buffer slice() {
-        int pos = this.position();
-        int lim = this.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-        int off = (pos << $LG_BYTES_PER_VALUE$);
-        assert (off >= 0);
-        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
-    }
-
-    public $Type$Buffer duplicate() {
-        return new Direct$Type$Buffer$RW$$BO$(this,
-                                              this.markValue(),
-                                              this.position(),
-                                              this.limit(),
-                                              this.capacity(),
-                                              0);
-    }
-
-    public $Type$Buffer asReadOnlyBuffer() {
-#if[rw]
-        return new Direct$Type$BufferR$BO$(this,
-                                           this.markValue(),
-                                           this.position(),
-                                           this.limit(),
-                                           this.capacity(),
-                                           0);
-#else[rw]
-        return duplicate();
-#end[rw]
-    }
-
-#if[rw]
-
-    public long address() {
-        return address;
-    }
-
-    private long ix(int i) {
-        return address + (i << $LG_BYTES_PER_VALUE$);
-    }
-
-    public $type$ get() {
-        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
-    }
-
-    public $type$ get(int i) {
-        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
-    }
-
-    public $Type$Buffer get($type$[] dst, int offset, int length) {
-#if[rw]
-        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
-            checkBounds(offset, length, dst.length);
-            int pos = position();
-            int lim = limit();
-            assert (pos <= lim);
-            int rem = (pos <= lim ? lim - pos : 0);
-            if (length > rem)
-                throw new BufferUnderflowException();
-
-#if[!byte]
-            if (order() != ByteOrder.nativeOrder())
-                Bits.copyTo$Memtype$Array(ix(pos), dst,
-                                          offset << $LG_BYTES_PER_VALUE$,
-                                          length << $LG_BYTES_PER_VALUE$);
-            else
-#end[!byte]
-                Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
-                                 offset << $LG_BYTES_PER_VALUE$,
-                                 length << $LG_BYTES_PER_VALUE$);
-            position(pos + length);
-        } else {
-            super.get(dst, offset, length);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-#end[rw]
-
-    public $Type$Buffer put($type$ x) {
-#if[rw]
-        unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put(int i, $type$ x) {
-#if[rw]
-        unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($Type$Buffer src) {
-#if[rw]
-        if (src instanceof Direct$Type$Buffer$BO$) {
-            if (src == this)
-                throw new IllegalArgumentException();
-            Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
-
-            int spos = sb.position();
-            int slim = sb.limit();
-            assert (spos <= slim);
-            int srem = (spos <= slim ? slim - spos : 0);
-
-            int pos = position();
-            int lim = limit();
-            assert (pos <= lim);
-            int rem = (pos <= lim ? lim - pos : 0);
-
-            if (srem > rem)
-                throw new BufferOverflowException();
-            unsafe.copyMemory(sb.ix(spos), ix(pos), srem << $LG_BYTES_PER_VALUE$);
-            sb.position(spos + srem);
-            position(pos + srem);
-        } else if (src.hb != null) {
-
-            int spos = src.position();
-            int slim = src.limit();
-            assert (spos <= slim);
-            int srem = (spos <= slim ? slim - spos : 0);
-
-            put(src.hb, src.offset + spos, srem);
-            src.position(spos + srem);
-
-        } else {
-            super.put(src);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($type$[] src, int offset, int length) {
-#if[rw]
-        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
-            checkBounds(offset, length, src.length);
-            int pos = position();
-            int lim = limit();
-            assert (pos <= lim);
-            int rem = (pos <= lim ? lim - pos : 0);
-            if (length > rem)
-                throw new BufferOverflowException();
-
-#if[!byte]
-            if (order() != ByteOrder.nativeOrder())
-                Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$,
-                                            ix(pos), length << $LG_BYTES_PER_VALUE$);
-            else
-#end[!byte]
-                Bits.copyFromArray(src, arrayBaseOffset, offset << $LG_BYTES_PER_VALUE$,
-                                   ix(pos), length << $LG_BYTES_PER_VALUE$);
-            position(pos + length);
-        } else {
-            super.put(src, offset, length);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer compact() {
-#if[rw]
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-
-        unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
-        position(rem);
-        limit(capacity());
-        discardMark();
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public boolean isDirect() {
-        return true;
-    }
-
-    public boolean isReadOnly() {
-        return {#if[rw]?false:true};
-    }
-
-
-#if[char]
-
-    public String toString(int start, int end) {
-        if ((end > limit()) || (start > end))
-            throw new IndexOutOfBoundsException();
-        try {
-            int len = end - start;
-            char[] ca = new char[len];
-            CharBuffer cb = CharBuffer.wrap(ca);
-            CharBuffer db = this.duplicate();
-            db.position(start);
-            db.limit(end);
-            cb.put(db);
-            return new String(ca);
-        } catch (StringIndexOutOfBoundsException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-
-    // --- Methods to support CharSequence ---
-
-    public CharBuffer subSequence(int start, int end) {
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        pos = (pos <= lim ? pos : lim);
-        int len = lim - pos;
-
-        if ((start < 0) || (end > len) || (start > end))
-            throw new IndexOutOfBoundsException();
-        return new DirectCharBuffer$RW$$BO$(this,
-                                            -1,
-                                            pos + start,
-                                            pos + end,
-                                            capacity(),
-                                            offset);
-    }
-
-#end[char]
-
-
-
-#if[!byte]
-
-    public ByteOrder order() {
-#if[boS]
-        return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
-                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
-#end[boS]
-#if[boU]
-        return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
-                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
-#end[boU]
-    }
-
-#end[!byte]
-
-
-
-#if[byte]
-
-    byte _get(int i) {                          // package-private
-        return unsafe.getByte(address + i);
-    }
-
-    void _put(int i, byte b) {                  // package-private
-#if[rw]
-        unsafe.putByte(address + i, b);
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    // #BIN
-    //
-    // Binary-data access methods  for short, char, int, long, float,
-    // and double will be inserted here
-
-#end[byte]
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+import sun.misc.Cleaner;
+import sun.misc.Unsafe;
+import sun.nio.ch.DirectBuffer;
+
+
+class Direct$Type$Buffer$RW$$BO$
+#if[rw]
+    extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
+#else[rw]
+    extends Direct$Type$Buffer$BO$
+#end[rw]
+    implements DirectBuffer
+{
+
+#if[rw]
+
+    // Cached unsafe-access object
+    protected static final Unsafe unsafe = Bits.unsafe();
+
+    // Cached array base offset
+    private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
+
+    // Cached unaligned-access capability
+    protected static final boolean unaligned = Bits.unaligned();
+
+    // Base address, used in all indexing calculations
+    // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
+    //    protected long address;
+
+    // If this buffer is a view of another buffer then we keep a reference to
+    // that buffer so that its memory isn't freed before we're done with it
+    protected Object viewedBuffer = null;
+
+    public Object viewedBuffer() {
+        return viewedBuffer;
+    }
+
+#if[byte]
+
+    private static class Deallocator
+        implements Runnable
+    {
+
+        private static Unsafe unsafe = Unsafe.getUnsafe();
+
+        private long address;
+        private long size;
+        private int capacity;
+
+        private Deallocator(long address, long size, int capacity) {
+            assert (address != 0);
+            this.address = address;
+            this.size = size;
+            this.capacity = capacity;
+        }
+
+        public void run() {
+            if (address == 0) {
+                // Paranoia
+                return;
+            }
+            unsafe.freeMemory(address);
+            address = 0;
+            Bits.unreserveMemory(size, capacity);
+        }
+
+    }
+
+    private final Cleaner cleaner;
+
+    public Cleaner cleaner() { return cleaner; }
+
+#else[byte]
+
+    public Cleaner cleaner() { return null; }
+
+#end[byte]
+
+#end[rw]
+
+#if[byte]
+
+    // Primary constructor
+    //
+    Direct$Type$Buffer$RW$(int cap) {                   // package-private
+#if[rw]
+        super(-1, 0, cap, cap, false);
+        int ps = Bits.pageSize();
+        int size = cap + ps;
+        Bits.reserveMemory(size, cap);
+
+        long base = 0;
+        try {
+            base = unsafe.allocateMemory(size);
+        } catch (OutOfMemoryError x) {
+            Bits.unreserveMemory(size, cap);
+            throw x;
+        }
+        unsafe.setMemory(base, size, (byte) 0);
+        if (base % ps != 0) {
+            // Round up to page boundary
+            address = base + ps - (base & (ps - 1));
+        } else {
+            address = base;
+        }
+        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
+#else[rw]
+        super(cap);
+#end[rw]
+    }
+
+#if[rw]
+
+    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
+    //
+    private Direct$Type$Buffer(long addr, int cap) {
+        super(-1, 0, cap, cap, false);
+        address = addr;
+        cleaner = null;
+    }
+
+#end[rw]
+
+    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
+    //
+    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
+#if[rw]
+        super(-1, 0, cap, cap, true);
+        address = addr;
+        viewedBuffer = null;
+        cleaner = Cleaner.create(this, unmapper);
+#else[rw]
+        super(cap, addr, unmapper);
+#end[rw]
+    }
+
+#end[byte]
+
+    // For duplicates and slices
+    //
+    Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
+                               int mark, int pos, int lim, int cap,
+                               int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        address = db.address() + off;
+        viewedBuffer = db;
+#if[byte]
+        cleaner = null;
+#end[byte]
+#else[rw]
+        super(db, mark, pos, lim, cap, off);
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = (pos << $LG_BYTES_PER_VALUE$);
+        assert (off >= 0);
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new Direct$Type$Buffer$RW$$BO$(this,
+                                              this.markValue(),
+                                              this.position(),
+                                              this.limit(),
+                                              this.capacity(),
+                                              0);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Direct$Type$BufferR$BO$(this,
+                                           this.markValue(),
+                                           this.position(),
+                                           this.limit(),
+                                           this.capacity(),
+                                           0);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    public long address() {
+        return address;
+    }
+
+    private long ix(int i) {
+        return address + (i << $LG_BYTES_PER_VALUE$);
+    }
+
+    public $type$ get() {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
+    }
+
+    public $type$ get(int i) {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
+    }
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+#if[rw]
+        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, dst.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferUnderflowException();
+
+#if[!byte]
+            if (order() != ByteOrder.nativeOrder())
+                Bits.copyTo$Memtype$Array(ix(pos), dst,
+                                          offset << $LG_BYTES_PER_VALUE$,
+                                          length << $LG_BYTES_PER_VALUE$);
+            else
+#end[!byte]
+                Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
+                                 offset << $LG_BYTES_PER_VALUE$,
+                                 length << $LG_BYTES_PER_VALUE$);
+            position(pos + length);
+        } else {
+            super.get(dst, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Direct$Type$Buffer$BO$) {
+            if (src == this)
+                throw new IllegalArgumentException();
+            Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
+
+            int spos = sb.position();
+            int slim = sb.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+
+            if (srem > rem)
+                throw new BufferOverflowException();
+            unsafe.copyMemory(sb.ix(spos), ix(pos), srem << $LG_BYTES_PER_VALUE$);
+            sb.position(spos + srem);
+            position(pos + srem);
+        } else if (src.hb != null) {
+
+            int spos = src.position();
+            int slim = src.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            put(src.hb, src.offset + spos, srem);
+            src.position(spos + srem);
+
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, src.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferOverflowException();
+
+#if[!byte]
+            if (order() != ByteOrder.nativeOrder())
+                Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$,
+                                            ix(pos), length << $LG_BYTES_PER_VALUE$);
+            else
+#end[!byte]
+                Bits.copyFromArray(src, arrayBaseOffset, offset << $LG_BYTES_PER_VALUE$,
+                                   ix(pos), length << $LG_BYTES_PER_VALUE$);
+            position(pos + length);
+        } else {
+            super.put(src, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return true;
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new DirectCharBuffer$RW$$BO$(this,
+                                            -1,
+                                            pos + start,
+                                            pos + end,
+                                            capacity(),
+                                            offset);
+    }
+
+#end[char]
+
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+#if[boS]
+        return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boS]
+#if[boU]
+        return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boU]
+    }
+
+#end[!byte]
+
+
+
+#if[byte]
+
+    byte _get(int i) {                          // package-private
+        return unsafe.getByte(address + i);
+    }
+
+    void _put(int i, byte b) {                  // package-private
+#if[rw]
+        unsafe.putByte(address + i, b);
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+}
--- a/jdk/src/share/classes/java/nio/Heap-X-Buffer.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,595 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-
-/**
-#if[rw]
- * A read/write Heap$Type$Buffer.
-#else[rw]
- * A read-only Heap$Type$Buffer.  This class extends the corresponding
- * read/write class, overriding the mutation methods to throw a {@link
- * ReadOnlyBufferException} and overriding the view-buffer methods to return an
- * instance of this class rather than of the superclass.
-#end[rw]
- */
-
-class Heap$Type$Buffer$RW$
-    extends {#if[ro]?Heap}$Type$Buffer
-{
-
-    // For speed these fields are actually declared in X-Buffer;
-    // these declarations are here as documentation
-    /*
-#if[rw]
-    protected final $type$[] hb;
-    protected final int offset;
-#end[rw]
-    */
-
-    Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
-#if[rw]
-        super(-1, 0, lim, cap, new $type$[cap], 0);
-        /*
-        hb = new $type$[cap];
-        offset = 0;
-        */
-#else[rw]
-        super(cap, lim);
-        this.isReadOnly = true;
-#end[rw]
-    }
-
-    Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
-#if[rw]
-        super(-1, off, off + len, buf.length, buf, 0);
-        /*
-        hb = buf;
-        offset = 0;
-        */
-#else[rw]
-        super(buf, off, len);
-        this.isReadOnly = true;
-#end[rw]
-    }
-
-    protected Heap$Type$Buffer$RW$($type$[] buf,
-                                   int mark, int pos, int lim, int cap,
-                                   int off)
-    {
-#if[rw]
-        super(mark, pos, lim, cap, buf, off);
-        /*
-        hb = buf;
-        offset = off;
-        */
-#else[rw]
-        super(buf, mark, pos, lim, cap, off);
-        this.isReadOnly = true;
-#end[rw]
-    }
-
-    public $Type$Buffer slice() {
-        return new Heap$Type$Buffer$RW$(hb,
-                                        -1,
-                                        0,
-                                        this.remaining(),
-                                        this.remaining(),
-                                        this.position() + offset);
-    }
-
-    public $Type$Buffer duplicate() {
-        return new Heap$Type$Buffer$RW$(hb,
-                                        this.markValue(),
-                                        this.position(),
-                                        this.limit(),
-                                        this.capacity(),
-                                        offset);
-    }
-
-    public $Type$Buffer asReadOnlyBuffer() {
-#if[rw]
-        return new Heap$Type$BufferR(hb,
-                                     this.markValue(),
-                                     this.position(),
-                                     this.limit(),
-                                     this.capacity(),
-                                     offset);
-#else[rw]
-        return duplicate();
-#end[rw]
-    }
-
-#if[rw]
-
-    protected int ix(int i) {
-        return i + offset;
-    }
-
-    public $type$ get() {
-        return hb[ix(nextGetIndex())];
-    }
-
-    public $type$ get(int i) {
-        return hb[ix(checkIndex(i))];
-    }
-
-    public $Type$Buffer get($type$[] dst, int offset, int length) {
-        checkBounds(offset, length, dst.length);
-        if (length > remaining())
-            throw new BufferUnderflowException();
-        System.arraycopy(hb, ix(position()), dst, offset, length);
-        position(position() + length);
-        return this;
-    }
-
-    public boolean isDirect() {
-        return false;
-    }
-
-#end[rw]
-
-    public boolean isReadOnly() {
-        return {#if[rw]?false:true};
-    }
-
-    public $Type$Buffer put($type$ x) {
-#if[rw]
-        hb[ix(nextPutIndex())] = x;
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put(int i, $type$ x) {
-#if[rw]
-        hb[ix(checkIndex(i))] = x;
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($type$[] src, int offset, int length) {
-#if[rw]
-        checkBounds(offset, length, src.length);
-        if (length > remaining())
-            throw new BufferOverflowException();
-        System.arraycopy(src, offset, hb, ix(position()), length);
-        position(position() + length);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($Type$Buffer src) {
-#if[rw]
-        if (src instanceof Heap$Type$Buffer) {
-            if (src == this)
-                throw new IllegalArgumentException();
-            Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
-            int n = sb.remaining();
-            if (n > remaining())
-                throw new BufferOverflowException();
-            System.arraycopy(sb.hb, sb.ix(sb.position()),
-                             hb, ix(position()), n);
-            sb.position(sb.position() + n);
-            position(position() + n);
-        } else if (src.isDirect()) {
-            int n = src.remaining();
-            if (n > remaining())
-                throw new BufferOverflowException();
-            src.get(hb, ix(position()), n);
-            position(position() + n);
-        } else {
-            super.put(src);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer compact() {
-#if[rw]
-        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
-        position(remaining());
-        limit(capacity());
-        discardMark();
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-
-
-#if[byte]
-
-    byte _get(int i) {                          // package-private
-        return hb[i];
-    }
-
-    void _put(int i, byte b) {                  // package-private
-#if[rw]
-        hb[i] = b;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    // char
-
-#if[rw]
-
-    public char getChar() {
-        return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
-    }
-
-    public char getChar(int i) {
-        return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putChar(char x) {
-#if[rw]
-        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putChar(int i, char x) {
-#if[rw]
-        Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public CharBuffer asCharBuffer() {
-        int size = this.remaining() >> 1;
-        int off = offset + position();
-        return (bigEndian
-                ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off))
-                : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off)));
-    }
-
-
-    // short
-
-#if[rw]
-
-    public short getShort() {
-        return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
-    }
-
-    public short getShort(int i) {
-        return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putShort(short x) {
-#if[rw]
-        Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putShort(int i, short x) {
-#if[rw]
-        Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public ShortBuffer asShortBuffer() {
-        int size = this.remaining() >> 1;
-        int off = offset + position();
-        return (bigEndian
-                ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off))
-                : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off)));
-    }
-
-
-    // int
-
-#if[rw]
-
-    public int getInt() {
-        return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
-    }
-
-    public int getInt(int i) {
-        return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putInt(int x) {
-#if[rw]
-        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putInt(int i, int x) {
-#if[rw]
-        Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public IntBuffer asIntBuffer() {
-        int size = this.remaining() >> 2;
-        int off = offset + position();
-        return (bigEndian
-                ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
-                                                             -1,
-                                                             0,
-                                                             size,
-                                                             size,
-                                                             off))
-                : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
-                                                             -1,
-                                                             0,
-                                                             size,
-                                                             size,
-                                                             off)));
-    }
-
-
-    // long
-
-#if[rw]
-
-    public long getLong() {
-        return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
-    }
-
-    public long getLong(int i) {
-        return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putLong(long x) {
-#if[rw]
-        Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putLong(int i, long x) {
-#if[rw]
-        Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public LongBuffer asLongBuffer() {
-        int size = this.remaining() >> 3;
-        int off = offset + position();
-        return (bigEndian
-                ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off))
-                : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off)));
-    }
-
-
-    // float
-
-#if[rw]
-
-    public float getFloat() {
-        return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
-    }
-
-    public float getFloat(int i) {
-        return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putFloat(float x) {
-#if[rw]
-        Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putFloat(int i, float x) {
-#if[rw]
-        Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public FloatBuffer asFloatBuffer() {
-        int size = this.remaining() >> 2;
-        int off = offset + position();
-        return (bigEndian
-                ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off))
-                : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off)));
-    }
-
-
-    // double
-
-#if[rw]
-
-    public double getDouble() {
-        return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
-    }
-
-    public double getDouble(int i) {
-        return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putDouble(double x) {
-#if[rw]
-        Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putDouble(int i, double x) {
-#if[rw]
-        Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public DoubleBuffer asDoubleBuffer() {
-        int size = this.remaining() >> 3;
-        int off = offset + position();
-        return (bigEndian
-                ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
-                                                                   -1,
-                                                                   0,
-                                                                   size,
-                                                                   size,
-                                                                   off))
-                : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
-                                                                   -1,
-                                                                   0,
-                                                                   size,
-                                                                   size,
-                                                                   off)));
-    }
-
-
-#end[byte]
-
-
-#if[char]
-
-    String toString(int start, int end) {               // package-private
-        try {
-            return new String(hb, start + offset, end - start);
-        } catch (StringIndexOutOfBoundsException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-
-    // --- Methods to support CharSequence ---
-
-    public CharBuffer subSequence(int start, int end) {
-        if ((start < 0)
-            || (end > length())
-            || (start > end))
-            throw new IndexOutOfBoundsException();
-        int pos = position();
-        return new HeapCharBuffer$RW$(hb,
-                                      -1,
-                                      pos + start,
-                                      pos + end,
-                                      capacity(),
-                                      offset);
-    }
-
-#end[char]
-
-
-#if[!byte]
-
-    public ByteOrder order() {
-        return ByteOrder.nativeOrder();
-    }
-
-#end[!byte]
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/Heap-X-Buffer.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,595 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+
+/**
+#if[rw]
+ * A read/write Heap$Type$Buffer.
+#else[rw]
+ * A read-only Heap$Type$Buffer.  This class extends the corresponding
+ * read/write class, overriding the mutation methods to throw a {@link
+ * ReadOnlyBufferException} and overriding the view-buffer methods to return an
+ * instance of this class rather than of the superclass.
+#end[rw]
+ */
+
+class Heap$Type$Buffer$RW$
+    extends {#if[ro]?Heap}$Type$Buffer
+{
+
+    // For speed these fields are actually declared in X-Buffer;
+    // these declarations are here as documentation
+    /*
+#if[rw]
+    protected final $type$[] hb;
+    protected final int offset;
+#end[rw]
+    */
+
+    Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
+#if[rw]
+        super(-1, 0, lim, cap, new $type$[cap], 0);
+        /*
+        hb = new $type$[cap];
+        offset = 0;
+        */
+#else[rw]
+        super(cap, lim);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
+#if[rw]
+        super(-1, off, off + len, buf.length, buf, 0);
+        /*
+        hb = buf;
+        offset = 0;
+        */
+#else[rw]
+        super(buf, off, len);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    protected Heap$Type$Buffer$RW$($type$[] buf,
+                                   int mark, int pos, int lim, int cap,
+                                   int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap, buf, off);
+        /*
+        hb = buf;
+        offset = off;
+        */
+#else[rw]
+        super(buf, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        this.remaining(),
+                                        this.remaining(),
+                                        this.position() + offset);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new Heap$Type$Buffer$RW$(hb,
+                                        this.markValue(),
+                                        this.position(),
+                                        this.limit(),
+                                        this.capacity(),
+                                        offset);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Heap$Type$BufferR(hb,
+                                     this.markValue(),
+                                     this.position(),
+                                     this.limit(),
+                                     this.capacity(),
+                                     offset);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    protected int ix(int i) {
+        return i + offset;
+    }
+
+    public $type$ get() {
+        return hb[ix(nextGetIndex())];
+    }
+
+    public $type$ get(int i) {
+        return hb[ix(checkIndex(i))];
+    }
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+        checkBounds(offset, length, dst.length);
+        if (length > remaining())
+            throw new BufferUnderflowException();
+        System.arraycopy(hb, ix(position()), dst, offset, length);
+        position(position() + length);
+        return this;
+    }
+
+    public boolean isDirect() {
+        return false;
+    }
+
+#end[rw]
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        hb[ix(nextPutIndex())] = x;
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        hb[ix(checkIndex(i))] = x;
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        checkBounds(offset, length, src.length);
+        if (length > remaining())
+            throw new BufferOverflowException();
+        System.arraycopy(src, offset, hb, ix(position()), length);
+        position(position() + length);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Heap$Type$Buffer) {
+            if (src == this)
+                throw new IllegalArgumentException();
+            Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
+            int n = sb.remaining();
+            if (n > remaining())
+                throw new BufferOverflowException();
+            System.arraycopy(sb.hb, sb.ix(sb.position()),
+                             hb, ix(position()), n);
+            sb.position(sb.position() + n);
+            position(position() + n);
+        } else if (src.isDirect()) {
+            int n = src.remaining();
+            if (n > remaining())
+                throw new BufferOverflowException();
+            src.get(hb, ix(position()), n);
+            position(position() + n);
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
+        position(remaining());
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+
+
+#if[byte]
+
+    byte _get(int i) {                          // package-private
+        return hb[i];
+    }
+
+    void _put(int i, byte b) {                  // package-private
+#if[rw]
+        hb[i] = b;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    // char
+
+#if[rw]
+
+    public char getChar() {
+        return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
+    }
+
+    public char getChar(int i) {
+        return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putChar(char x) {
+#if[rw]
+        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putChar(int i, char x) {
+#if[rw]
+        Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public CharBuffer asCharBuffer() {
+        int size = this.remaining() >> 1;
+        int off = offset + position();
+        return (bigEndian
+                ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off))
+                : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off)));
+    }
+
+
+    // short
+
+#if[rw]
+
+    public short getShort() {
+        return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
+    }
+
+    public short getShort(int i) {
+        return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putShort(short x) {
+#if[rw]
+        Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putShort(int i, short x) {
+#if[rw]
+        Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ShortBuffer asShortBuffer() {
+        int size = this.remaining() >> 1;
+        int off = offset + position();
+        return (bigEndian
+                ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+    }
+
+
+    // int
+
+#if[rw]
+
+    public int getInt() {
+        return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
+    }
+
+    public int getInt(int i) {
+        return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putInt(int x) {
+#if[rw]
+        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putInt(int i, int x) {
+#if[rw]
+        Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public IntBuffer asIntBuffer() {
+        int size = this.remaining() >> 2;
+        int off = offset + position();
+        return (bigEndian
+                ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
+                                                             -1,
+                                                             0,
+                                                             size,
+                                                             size,
+                                                             off))
+                : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
+                                                             -1,
+                                                             0,
+                                                             size,
+                                                             size,
+                                                             off)));
+    }
+
+
+    // long
+
+#if[rw]
+
+    public long getLong() {
+        return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
+    }
+
+    public long getLong(int i) {
+        return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putLong(long x) {
+#if[rw]
+        Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putLong(int i, long x) {
+#if[rw]
+        Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public LongBuffer asLongBuffer() {
+        int size = this.remaining() >> 3;
+        int off = offset + position();
+        return (bigEndian
+                ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off))
+                : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off)));
+    }
+
+
+    // float
+
+#if[rw]
+
+    public float getFloat() {
+        return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
+    }
+
+    public float getFloat(int i) {
+        return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putFloat(float x) {
+#if[rw]
+        Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putFloat(int i, float x) {
+#if[rw]
+        Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public FloatBuffer asFloatBuffer() {
+        int size = this.remaining() >> 2;
+        int off = offset + position();
+        return (bigEndian
+                ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+    }
+
+
+    // double
+
+#if[rw]
+
+    public double getDouble() {
+        return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
+    }
+
+    public double getDouble(int i) {
+        return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putDouble(double x) {
+#if[rw]
+        Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putDouble(int i, double x) {
+#if[rw]
+        Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public DoubleBuffer asDoubleBuffer() {
+        int size = this.remaining() >> 3;
+        int off = offset + position();
+        return (bigEndian
+                ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
+                                                                   -1,
+                                                                   0,
+                                                                   size,
+                                                                   size,
+                                                                   off))
+                : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
+                                                                   -1,
+                                                                   0,
+                                                                   size,
+                                                                   size,
+                                                                   off)));
+    }
+
+
+#end[byte]
+
+
+#if[char]
+
+    String toString(int start, int end) {               // package-private
+        try {
+            return new String(hb, start + offset, end - start);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        if ((start < 0)
+            || (end > length())
+            || (start > end))
+            throw new IndexOutOfBoundsException();
+        int pos = position();
+        return new HeapCharBuffer$RW$(hb,
+                                      -1,
+                                      pos + start,
+                                      pos + end,
+                                      capacity(),
+                                      offset);
+    }
+
+#end[char]
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+        return ByteOrder.nativeOrder();
+    }
+
+#end[!byte]
+
+}
--- a/jdk/src/share/classes/java/nio/X-Buffer-bin.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright 2000-2002 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-class XXX {
-
-#begin
-
-    /**
-     * Relative <i>get</i> method for reading $a$ $type$ value.
-     *
-     * <p> Reads the next $nbytes$ bytes at this buffer's current position,
-     * composing them into $a$ $type$ value according to the current byte order,
-     * and then increments the position by $nbytes$.  </p>
-     *
-     * @return  The $type$ value at the buffer's current position
-     *
-     * @throws  BufferUnderflowException
-     *          If there are fewer than $nbytes$ bytes
-     *          remaining in this buffer
-     */
-    public abstract $type$ get$Type$();
-
-    /**
-     * Relative <i>put</i> method for writing $a$ $type$
-     * value&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
-     * current byte order, into this buffer at the current position, and then
-     * increments the position by $nbytes$.  </p>
-     *
-     * @param  value
-     *         The $type$ value to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there are fewer than $nbytes$ bytes
-     *          remaining in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract ByteBuffer put$Type$($type$ value);
-
-    /**
-     * Absolute <i>get</i> method for reading $a$ $type$ value.
-     *
-     * <p> Reads $nbytes$ bytes at the given index, composing them into a
-     * $type$ value according to the current byte order.  </p>
-     *
-     * @param  index
-     *         The index from which the bytes will be read
-     *
-     * @return  The $type$ value at the given index
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit,
-     *          minus $nbytesButOne$
-     */
-    public abstract $type$ get$Type$(int index);
-
-    /**
-     * Absolute <i>put</i> method for writing $a$ $type$
-     * value&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
-     * current byte order, into this buffer at the given index.  </p>
-     *
-     * @param  index
-     *         The index at which the bytes will be written
-     *
-     * @param  value
-     *         The $type$ value to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit,
-     *          minus $nbytesButOne$
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract ByteBuffer put$Type$(int index, $type$ value);
-
-    /**
-     * Creates a view of this byte buffer as $a$ $type$ buffer.
-     *
-     * <p> The content of the new buffer will start at this buffer's current
-     * position.  Changes to this buffer's content will be visible in the new
-     * buffer, and vice versa; the two buffers' position, limit, and mark
-     * values will be independent.
-     *
-     * <p> The new buffer's position will be zero, its capacity and its limit
-     * will be the number of bytes remaining in this buffer divided by
-     * $nbytes$, and its mark will be undefined.  The new buffer will be direct
-     * if, and only if, this buffer is direct, and it will be read-only if, and
-     * only if, this buffer is read-only.  </p>
-     *
-     * @return  A new $type$ buffer
-     */
-    public abstract $Type$Buffer as$Type$Buffer();
-
-#end
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/X-Buffer-bin.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2002 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+class XXX {
+
+#begin
+
+    /**
+     * Relative <i>get</i> method for reading $a$ $type$ value.
+     *
+     * <p> Reads the next $nbytes$ bytes at this buffer's current position,
+     * composing them into $a$ $type$ value according to the current byte order,
+     * and then increments the position by $nbytes$.  </p>
+     *
+     * @return  The $type$ value at the buffer's current position
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than $nbytes$ bytes
+     *          remaining in this buffer
+     */
+    public abstract $type$ get$Type$();
+
+    /**
+     * Relative <i>put</i> method for writing $a$ $type$
+     * value&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
+     * current byte order, into this buffer at the current position, and then
+     * increments the position by $nbytes$.  </p>
+     *
+     * @param  value
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there are fewer than $nbytes$ bytes
+     *          remaining in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract ByteBuffer put$Type$($type$ value);
+
+    /**
+     * Absolute <i>get</i> method for reading $a$ $type$ value.
+     *
+     * <p> Reads $nbytes$ bytes at the given index, composing them into a
+     * $type$ value according to the current byte order.  </p>
+     *
+     * @param  index
+     *         The index from which the bytes will be read
+     *
+     * @return  The $type$ value at the given index
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit,
+     *          minus $nbytesButOne$
+     */
+    public abstract $type$ get$Type$(int index);
+
+    /**
+     * Absolute <i>put</i> method for writing $a$ $type$
+     * value&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
+     * current byte order, into this buffer at the given index.  </p>
+     *
+     * @param  index
+     *         The index at which the bytes will be written
+     *
+     * @param  value
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit,
+     *          minus $nbytesButOne$
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract ByteBuffer put$Type$(int index, $type$ value);
+
+    /**
+     * Creates a view of this byte buffer as $a$ $type$ buffer.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer divided by
+     * $nbytes$, and its mark will be undefined.  The new buffer will be direct
+     * if, and only if, this buffer is direct, and it will be read-only if, and
+     * only if, this buffer is read-only.  </p>
+     *
+     * @return  A new $type$ buffer
+     */
+    public abstract $Type$Buffer as$Type$Buffer();
+
+#end
+
+}
--- a/jdk/src/share/classes/java/nio/X-Buffer.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1428 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-#if[char]
-import java.io.IOException;
-#end[char]
-
-/**
- * $A$ $fulltype$ buffer.
- *
- * <p> This class defines {#if[byte]?six:four} categories of operations upon
- * $fulltype$ buffers:
- *
- * <ul>
- *
- *   <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
- *   {@link #put($type$) </code><i>put</i><code>} methods that read and write
- *   single $fulltype$s; </p></li>
- *
- *   <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from this buffer
- *   into an array; {#if[!byte]?and}</p></li>
- *
- *   <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from $a$
- *   $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
- *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
- *
-#if[byte]
- *
- *   <li><p> Absolute and relative {@link #getChar() </code><i>get</i><code>}
- *   and {@link #putChar(char) </code><i>put</i><code>} methods that read and
- *   write values of other primitive types, translating them to and from
- *   sequences of bytes in a particular byte order; </p></li>
- *
- *   <li><p> Methods for creating <i><a href="#views">view buffers</a></i>,
- *   which allow a byte buffer to be viewed as a buffer containing values of
- *   some other primitive type; and </p></li>
- *
-#end[byte]
- *
- *   <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
- *   #duplicate </code>duplicating<code>}, and {@link #slice
- *   </code>slicing<code>} $a$ $fulltype$ buffer.  </p></li>
- *
- * </ul>
- *
- * <p> $Fulltype$ buffers can be created either by {@link #allocate
- * </code><i>allocation</i><code>}, which allocates space for the buffer's
- *
-#if[byte]
- *
- * content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
- * existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
- *
-#else[byte]
- *
- * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
- * $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
- * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
- *
-#end[byte]
- *
-#if[byte]
- *
- * <a name="direct">
- * <h4> Direct <i>vs.</i> non-direct buffers </h4>
- *
- * <p> A byte buffer is either <i>direct</i> or <i>non-direct</i>.  Given a
- * direct byte buffer, the Java virtual machine will make a best effort to
- * perform native I/O operations directly upon it.  That is, it will attempt to
- * avoid copying the buffer's content to (or from) an intermediate buffer
- * before (or after) each invocation of one of the underlying operating
- * system's native I/O operations.
- *
- * <p> A direct byte buffer may be created by invoking the {@link
- * #allocateDirect(int) allocateDirect} factory method of this class.  The
- * buffers returned by this method typically have somewhat higher allocation
- * and deallocation costs than non-direct buffers.  The contents of direct
- * buffers may reside outside of the normal garbage-collected heap, and so
- * their impact upon the memory footprint of an application might not be
- * obvious.  It is therefore recommended that direct buffers be allocated
- * primarily for large, long-lived buffers that are subject to the underlying
- * system's native I/O operations.  In general it is best to allocate direct
- * buffers only when they yield a measureable gain in program performance.
- *
- * <p> A direct byte buffer may also be created by {@link
- * java.nio.channels.FileChannel#map </code>mapping<code>} a region of a file
- * directly into memory.  An implementation of the Java platform may optionally
- * support the creation of direct byte buffers from native code via JNI.  If an
- * instance of one of these kinds of buffers refers to an inaccessible region
- * of memory then an attempt to access that region will not change the buffer's
- * content and will cause an unspecified exception to be thrown either at the
- * time of the access or at some later time.
- *
- * <p> Whether a byte buffer is direct or non-direct may be determined by
- * invoking its {@link #isDirect isDirect} method.  This method is provided so
- * that explicit buffer management can be done in performance-critical code.
- *
- *
- * <a name="bin">
- * <h4> Access to binary data </h4>
- *
- * <p> This class defines methods for reading and writing values of all other
- * primitive types, except <tt>boolean</tt>.  Primitive values are translated
- * to (or from) sequences of bytes according to the buffer's current byte
- * order, which may be retrieved and modified via the {@link #order order}
- * methods.  Specific byte orders are represented by instances of the {@link
- * ByteOrder} class.  The initial order of a byte buffer is always {@link
- * ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
- *
- * <p> For access to heterogeneous binary data, that is, sequences of values of
- * different types, this class defines a family of absolute and relative
- * <i>get</i> and <i>put</i> methods for each type.  For 32-bit floating-point
- * values, for example, this class defines:
- *
- * <blockquote><pre>
- * float  {@link #getFloat()}
- * float  {@link #getFloat(int) getFloat(int index)}
- *  void  {@link #putFloat(float) putFloat(float f)}
- *  void  {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
- *
- * <p> Corresponding methods are defined for the types <tt>char</tt>,
- * <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and <tt>double</tt>.  The index
- * parameters of the absolute <i>get</i> and <i>put</i> methods are in terms of
- * bytes rather than of the type being read or written.
- *
- * <a name="views">
- *
- * <p> For access to homogeneous binary data, that is, sequences of values of
- * the same type, this class defines methods that can create <i>views</i> of a
- * given byte buffer.  A <i>view buffer</i> is simply another buffer whose
- * content is backed by the byte buffer.  Changes to the byte buffer's content
- * will be visible in the view buffer, and vice versa; the two buffers'
- * position, limit, and mark values are independent.  The {@link
- * #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of
- * the {@link FloatBuffer} class that is backed by the byte buffer upon which
- * the method is invoked.  Corresponding view-creation methods are defined for
- * the types <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and
- * <tt>double</tt>.
- *
- * <p> View buffers have three important advantages over the families of
- * type-specific <i>get</i> and <i>put</i> methods described above:
- *
- * <ul>
- *
- *   <li><p> A view buffer is indexed not in terms of bytes but rather in terms
- *   of the type-specific size of its values;  </p></li>
- *
- *   <li><p> A view buffer provides relative bulk <i>get</i> and <i>put</i>
- *   methods that can transfer contiguous sequences of values between a buffer
- *   and an array or some other buffer of the same type; and  </p></li>
- *
- *   <li><p> A view buffer is potentially much more efficient because it will
- *   be direct if, and only if, its backing byte buffer is direct.  </p></li>
- *
- * </ul>
- *
- * <p> The byte order of a view buffer is fixed to be that of its byte buffer
- * at the time that the view is created.  </p>
- *
-#end[byte]
-*
-#if[!byte]
- *
- * <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
- * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
- * $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
- * be non-direct.  $A$ $fulltype$ buffer created as a view of a byte buffer will
- * be direct if, and only if, the byte buffer itself is direct.  Whether or not
- * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
- * #isDirect isDirect} method.  </p>
- *
-#end[!byte]
-*
-#if[char]
- *
- * <p> This class implements the {@link CharSequence} interface so that
- * character buffers may be used wherever character sequences are accepted, for
- * example in the regular-expression package <tt>{@link java.util.regex}</tt>.
- * </p>
- *
-#end[char]
- *
-#if[byte]
- * <h4> Invocation chaining </h4>
-#end[byte]
- *
- * <p> Methods in this class that do not otherwise have a value to return are
- * specified to return the buffer upon which they are invoked.  This allows
- * method invocations to be chained.
- *
-#if[byte]
- *
- * The sequence of statements
- *
- * <blockquote><pre>
- * bb.putInt(0xCAFEBABE);
- * bb.putShort(3);
- * bb.putShort(45);</pre></blockquote>
- *
- * can, for example, be replaced by the single statement
- *
- * <blockquote><pre>
- * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);</pre></blockquote>
- *
-#end[byte]
-#if[char]
- *
- * The sequence of statements
- *
- * <blockquote><pre>
- * cb.put("text/");
- * cb.put(subtype);
- * cb.put("; charset=");
- * cb.put(enc);</pre></blockquote>
- *
- * can, for example, be replaced by the single statement
- *
- * <blockquote><pre>
- * cb.put("text/").put(subtype).put("; charset=").put(enc);</pre></blockquote>
- *
-#end[char]
- *
- *
- * @author Mark Reinhold
- * @author JSR-51 Expert Group
- * @since 1.4
- */
-
-public abstract class $Type$Buffer
-    extends Buffer
-    implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
-{
-
-    // These fields are declared here rather than in Heap-X-Buffer in order to
-    // reduce the number of virtual method invocations needed to access these
-    // values, which is especially costly when coding small buffers.
-    //
-    final $type$[] hb;                  // Non-null only for heap buffers
-    final int offset;
-    boolean isReadOnly;                 // Valid only for heap buffers
-
-    // Creates a new buffer with the given mark, position, limit, capacity,
-    // backing array, and array offset
-    //
-    $Type$Buffer(int mark, int pos, int lim, int cap,   // package-private
-                 $type$[] hb, int offset)
-    {
-        super(mark, pos, lim, cap);
-        this.hb = hb;
-        this.offset = offset;
-    }
-
-    // Creates a new buffer with the given mark, position, limit, and capacity
-    //
-    $Type$Buffer(int mark, int pos, int lim, int cap) { // package-private
-        this(mark, pos, lim, cap, null, 0);
-    }
-
-#if[byte]
-
-    /**
-     * Allocates a new direct $fulltype$ buffer.
-     *
-     * <p> The new buffer's position will be zero, its limit will be its
-     * capacity, its mark will be undefined, and each of its elements will be
-     * initialized to zero.  Whether or not it has a
-     * {@link #hasArray </code>backing array<code>} is unspecified.
-     *
-     * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
-     *
-     * @return  The new $fulltype$ buffer
-     *
-     * @throws  IllegalArgumentException
-     *          If the <tt>capacity</tt> is a negative integer
-     */
-    public static $Type$Buffer allocateDirect(int capacity) {
-        return new Direct$Type$Buffer(capacity);
-    }
-
-#end[byte]
-
-    /**
-     * Allocates a new $fulltype$ buffer.
-     *
-     * <p> The new buffer's position will be zero, its limit will be its
-     * capacity, its mark will be undefined, and each of its elements will be
-     * initialized to zero.  It will have a {@link #array
-     * </code>backing array<code>}, and its {@link #arrayOffset </code>array
-     * offset<code>} will be zero.
-     *
-     * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
-     *
-     * @return  The new $fulltype$ buffer
-     *
-     * @throws  IllegalArgumentException
-     *          If the <tt>capacity</tt> is a negative integer
-     */
-    public static $Type$Buffer allocate(int capacity) {
-        if (capacity < 0)
-            throw new IllegalArgumentException();
-        return new Heap$Type$Buffer(capacity, capacity);
-    }
-
-    /**
-     * Wraps $a$ $fulltype$ array into a buffer.
-     *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
-     * that is, modifications to the buffer will cause the array to be modified
-     * and vice versa.  The new buffer's capacity will be
-     * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
-     * will be <tt>offset + length</tt>, and its mark will be undefined.  Its
-     * {@link #array </code>backing array<code>} will be the given array, and
-     * its {@link #arrayOffset </code>array offset<code>} will be zero.  </p>
-     *
-     * @param  array
-     *         The array that will back the new buffer
-     *
-     * @param  offset
-     *         The offset of the subarray to be used; must be non-negative and
-     *         no larger than <tt>array.length</tt>.  The new buffer's position
-     *         will be set to this value.
-     *
-     * @param  length
-     *         The length of the subarray to be used;
-     *         must be non-negative and no larger than
-     *         <tt>array.length - offset</tt>.
-     *         The new buffer's limit will be set to <tt>offset + length</tt>.
-     *
-     * @return  The new $fulltype$ buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
-     *          parameters do not hold
-     */
-    public static $Type$Buffer wrap($type$[] array,
-                                    int offset, int length)
-    {
-        try {
-            return new Heap$Type$Buffer(array, offset, length);
-        } catch (IllegalArgumentException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-    /**
-     * Wraps $a$ $fulltype$ array into a buffer.
-     *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
-     * that is, modifications to the buffer will cause the array to be modified
-     * and vice versa.  The new buffer's capacity and limit will be
-     * <tt>array.length</tt>, its position will be zero, and its mark will be
-     * undefined.  Its {@link #array </code>backing array<code>} will be the
-     * given array, and its {@link #arrayOffset </code>array offset<code>} will
-     * be zero.  </p>
-     *
-     * @param  array
-     *         The array that will back this buffer
-     *
-     * @return  The new $fulltype$ buffer
-     */
-    public static $Type$Buffer wrap($type$[] array) {
-        return wrap(array, 0, array.length);
-    }
-
-#if[char]
-
-    /**
-     * Attempts to read characters into the specified character buffer.
-     * The buffer is used as a repository of characters as-is: the only
-     * changes made are the results of a put operation. No flipping or
-     * rewinding of the buffer is performed.
-     *
-     * @param target the buffer to read characters into
-     * @return The number of characters added to the buffer, or
-     *         -1 if this source of characters is at its end
-     * @throws IOException if an I/O error occurs
-     * @throws NullPointerException if target is null
-     * @throws ReadOnlyBufferException if target is a read only buffer
-     * @since 1.5
-     */
-    public int read(CharBuffer target) throws IOException {
-        // Determine the number of bytes n that can be transferred
-        int targetRemaining = target.remaining();
-        int remaining = remaining();
-        if (remaining == 0)
-            return -1;
-        int n = Math.min(remaining, targetRemaining);
-        int limit = limit();
-        // Set source limit to prevent target overflow
-        if (targetRemaining < remaining)
-            limit(position() + n);
-        try {
-            if (n > 0)
-                target.put(this);
-        } finally {
-            limit(limit); // restore real limit
-        }
-        return n;
-    }
-
-    /**
-     * Wraps a character sequence into a buffer.
-     *
-     * <p> The content of the new, read-only buffer will be the content of the
-     * given character sequence.  The buffer's capacity will be
-     * <tt>csq.length()</tt>, its position will be <tt>start</tt>, its limit
-     * will be <tt>end</tt>, and its mark will be undefined.  </p>
-     *
-     * @param  csq
-     *         The character sequence from which the new character buffer is to
-     *         be created
-     *
-     * @param  start
-     *         The index of the first character to be used;
-     *         must be non-negative and no larger than <tt>csq.length()</tt>.
-     *         The new buffer's position will be set to this value.
-     *
-     * @param  end
-     *         The index of the character following the last character to be
-     *         used; must be no smaller than <tt>start</tt> and no larger
-     *         than <tt>csq.length()</tt>.
-     *         The new buffer's limit will be set to this value.
-     *
-     * @return  The new character buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
-     *          parameters do not hold
-     */
-    public static CharBuffer wrap(CharSequence csq, int start, int end) {
-        try {
-            return new StringCharBuffer(csq, start, end);
-        } catch (IllegalArgumentException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-    /**
-     * Wraps a character sequence into a buffer.
-     *
-     * <p> The content of the new, read-only buffer will be the content of the
-     * given character sequence.  The new buffer's capacity and limit will be
-     * <tt>csq.length()</tt>, its position will be zero, and its mark will be
-     * undefined.  </p>
-     *
-     * @param  csq
-     *         The character sequence from which the new character buffer is to
-     *         be created
-     *
-     * @return  The new character buffer
-     */
-    public static CharBuffer wrap(CharSequence csq) {
-        return wrap(csq, 0, csq.length());
-    }
-
-#end[char]
-
-    /**
-     * Creates a new $fulltype$ buffer whose content is a shared subsequence of
-     * this buffer's content.
-     *
-     * <p> The content of the new buffer will start at this buffer's current
-     * position.  Changes to this buffer's content will be visible in the new
-     * buffer, and vice versa; the two buffers' position, limit, and mark
-     * values will be independent.
-     *
-     * <p> The new buffer's position will be zero, its capacity and its limit
-     * will be the number of $fulltype$s remaining in this buffer, and its mark
-     * will be undefined.  The new buffer will be direct if, and only if, this
-     * buffer is direct, and it will be read-only if, and only if, this buffer
-     * is read-only.  </p>
-     *
-     * @return  The new $fulltype$ buffer
-     */
-    public abstract $Type$Buffer slice();
-
-    /**
-     * Creates a new $fulltype$ buffer that shares this buffer's content.
-     *
-     * <p> The content of the new buffer will be that of this buffer.  Changes
-     * to this buffer's content will be visible in the new buffer, and vice
-     * versa; the two buffers' position, limit, and mark values will be
-     * independent.
-     *
-     * <p> The new buffer's capacity, limit, position, and mark values will be
-     * identical to those of this buffer.  The new buffer will be direct if,
-     * and only if, this buffer is direct, and it will be read-only if, and
-     * only if, this buffer is read-only.  </p>
-     *
-     * @return  The new $fulltype$ buffer
-     */
-    public abstract $Type$Buffer duplicate();
-
-    /**
-     * Creates a new, read-only $fulltype$ buffer that shares this buffer's
-     * content.
-     *
-     * <p> The content of the new buffer will be that of this buffer.  Changes
-     * to this buffer's content will be visible in the new buffer; the new
-     * buffer itself, however, will be read-only and will not allow the shared
-     * content to be modified.  The two buffers' position, limit, and mark
-     * values will be independent.
-     *
-     * <p> The new buffer's capacity, limit, position, and mark values will be
-     * identical to those of this buffer.
-     *
-     * <p> If this buffer is itself read-only then this method behaves in
-     * exactly the same way as the {@link #duplicate duplicate} method.  </p>
-     *
-     * @return  The new, read-only $fulltype$ buffer
-     */
-    public abstract $Type$Buffer asReadOnlyBuffer();
-
-
-    // -- Singleton get/put methods --
-
-    /**
-     * Relative <i>get</i> method.  Reads the $fulltype$ at this buffer's
-     * current position, and then increments the position. </p>
-     *
-     * @return  The $fulltype$ at the buffer's current position
-     *
-     * @throws  BufferUnderflowException
-     *          If the buffer's current position is not smaller than its limit
-     */
-    public abstract $type$ get();
-
-    /**
-     * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes the given $fulltype$ into this buffer at the current
-     * position, and then increments the position. </p>
-     *
-     * @param  $x$
-     *         The $fulltype$ to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If this buffer's current position is not smaller than its limit
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract $Type$Buffer put($type$ $x$);
-
-    /**
-     * Absolute <i>get</i> method.  Reads the $fulltype$ at the given
-     * index. </p>
-     *
-     * @param  index
-     *         The index from which the $fulltype$ will be read
-     *
-     * @return  The $fulltype$ at the given index
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit
-     */
-    public abstract $type$ get(int index);
-
-    /**
-     * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes the given $fulltype$ into this buffer at the given
-     * index. </p>
-     *
-     * @param  index
-     *         The index at which the $fulltype$ will be written
-     *
-     * @param  $x$
-     *         The $fulltype$ value to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract $Type$Buffer put(int index, $type$ $x$);
-
-
-    // -- Bulk get operations --
-
-    /**
-     * Relative bulk <i>get</i> method.
-     *
-     * <p> This method transfers $fulltype$s from this buffer into the given
-     * destination array.  If there are fewer $fulltype$s remaining in the
-     * buffer than are required to satisfy the request, that is, if
-     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferUnderflowException} is
-     * thrown.
-     *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
-     * buffer into the given array, starting at the current position of this
-     * buffer and at the given offset in the array.  The position of this
-     * buffer is then incremented by <tt>length</tt>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>src.get(dst,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
-     * the loop
-     *
-     * <pre>
-     *     for (int i = off; i < off + len; i++)
-     *         dst[i] = src.get(); </pre>
-     *
-     * except that it first checks that there are sufficient $fulltype$s in
-     * this buffer and it is potentially much more efficient. </p>
-     *
-     * @param  dst
-     *         The array into which $fulltype$s are to be written
-     *
-     * @param  offset
-     *         The offset within the array of the first $fulltype$ to be
-     *         written; must be non-negative and no larger than
-     *         <tt>dst.length</tt>
-     *
-     * @param  length
-     *         The maximum number of $fulltype$s to be written to the given
-     *         array; must be non-negative and no larger than
-     *         <tt>dst.length - offset</tt>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
-     *          remaining in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
-     *          parameters do not hold
-     */
-    public $Type$Buffer get($type$[] dst, int offset, int length) {
-        checkBounds(offset, length, dst.length);
-        if (length > remaining())
-            throw new BufferUnderflowException();
-        int end = offset + length;
-        for (int i = offset; i < end; i++)
-            dst[i] = get();
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>get</i> method.
-     *
-     * <p> This method transfers $fulltype$s from this buffer into the given
-     * destination array.  An invocation of this method of the form
-     * <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     src.get(a, 0, a.length) </pre>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
-     *          remaining in this buffer
-     */
-    public $Type$Buffer get($type$[] dst) {
-        return get(dst, 0, dst.length);
-    }
-
-
-    // -- Bulk put operations --
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers the $fulltype$s remaining in the given source
-     * buffer into this buffer.  If there are more $fulltype$s remaining in the
-     * source buffer than in this buffer, that is, if
-     * <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
-     * BufferOverflowException} is thrown.
-     *
-     * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
-     * buffer into this buffer, starting at each buffer's current position.
-     * The positions of both buffers are then incremented by <i>n</i>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>dst.put(src)</tt> has exactly the same effect as the loop
-     *
-     * <pre>
-     *     while (src.hasRemaining())
-     *         dst.put(src.get()); </pre>
-     *
-     * except that it first checks that there is sufficient space in this
-     * buffer and it is potentially much more efficient. </p>
-     *
-     * @param  src
-     *         The source buffer from which $fulltype$s are to be read;
-     *         must not be this buffer
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *          for the remaining $fulltype$s in the source buffer
-     *
-     * @throws  IllegalArgumentException
-     *          If the source buffer is this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public $Type$Buffer put($Type$Buffer src) {
-        if (src == this)
-            throw new IllegalArgumentException();
-        int n = src.remaining();
-        if (n > remaining())
-            throw new BufferOverflowException();
-        for (int i = 0; i < n; i++)
-            put(src.get());
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers $fulltype$s into this buffer from the given
-     * source array.  If there are more $fulltype$s to be copied from the array
-     * than remain in this buffer, that is, if
-     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferOverflowException} is
-     * thrown.
-     *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
-     * given array into this buffer, starting at the given offset in the array
-     * and at the current position of this buffer.  The position of this buffer
-     * is then incremented by <tt>length</tt>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>dst.put(src,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
-     * the loop
-     *
-     * <pre>
-     *     for (int i = off; i < off + len; i++)
-     *         dst.put(a[i]); </pre>
-     *
-     * except that it first checks that there is sufficient space in this
-     * buffer and it is potentially much more efficient. </p>
-     *
-     * @param  src
-     *         The array from which $fulltype$s are to be read
-     *
-     * @param  offset
-     *         The offset within the array of the first $fulltype$ to be read;
-     *         must be non-negative and no larger than <tt>array.length</tt>
-     *
-     * @param  length
-     *         The number of $fulltype$s to be read from the given array;
-     *         must be non-negative and no larger than
-     *         <tt>array.length - offset</tt>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
-     *          parameters do not hold
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public $Type$Buffer put($type$[] src, int offset, int length) {
-        checkBounds(offset, length, src.length);
-        if (length > remaining())
-            throw new BufferOverflowException();
-        int end = offset + length;
-        for (int i = offset; i < end; i++)
-            this.put(src[i]);
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers the entire content of the given source
-     * $fulltype$ array into this buffer.  An invocation of this method of the
-     * form <tt>dst.put(a)</tt> behaves in exactly the same way as the
-     * invocation
-     *
-     * <pre>
-     *     dst.put(a, 0, a.length) </pre>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public final $Type$Buffer put($type$[] src) {
-        return put(src, 0, src.length);
-    }
-
-#if[char]
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers $fulltype$s from the given string into this
-     * buffer.  If there are more $fulltype$s to be copied from the string than
-     * remain in this buffer, that is, if
-     * <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
-     * BufferOverflowException} is thrown.
-     *
-     * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
-     * from the given string into this buffer, starting at the given
-     * <tt>start</tt> index and at the current position of this buffer.  The
-     * position of this buffer is then incremented by <i>n</i>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>dst.put(src,&nbsp;start,&nbsp;end)</tt> has exactly the same effect
-     * as the loop
-     *
-     * <pre>
-     *     for (int i = start; i < end; i++)
-     *         dst.put(src.charAt(i)); </pre>
-     *
-     * except that it first checks that there is sufficient space in this
-     * buffer and it is potentially much more efficient. </p>
-     *
-     * @param  src
-     *         The string from which $fulltype$s are to be read
-     *
-     * @param  start
-     *         The offset within the string of the first $fulltype$ to be read;
-     *         must be non-negative and no larger than
-     *         <tt>string.length()</tt>
-     *
-     * @param  end
-     *         The offset within the string of the last $fulltype$ to be read,
-     *         plus one; must be non-negative and no larger than
-     *         <tt>string.length()</tt>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
-     *          parameters do not hold
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public $Type$Buffer put(String src, int start, int end) {
-        checkBounds(start, end - start, src.length());
-        for (int i = start; i < end; i++)
-            this.put(src.charAt(i));
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers the entire content of the given source string
-     * into this buffer.  An invocation of this method of the form
-     * <tt>dst.put(s)</tt> behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     dst.put(s, 0, s.length()) </pre>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public final $Type$Buffer put(String src) {
-        return put(src, 0, src.length());
-    }
-
-#end[char]
-
-
-    // -- Other stuff --
-
-    /**
-     * Tells whether or not this buffer is backed by an accessible $fulltype$
-     * array.
-     *
-     * <p> If this method returns <tt>true</tt> then the {@link #array() array}
-     * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
-     * </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this buffer
-     *          is backed by an array and is not read-only
-     */
-    public final boolean hasArray() {
-        return (hb != null) && !isReadOnly;
-    }
-
-    /**
-     * Returns the $fulltype$ array that backs this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Modifications to this buffer's content will cause the returned
-     * array's content to be modified, and vice versa.
-     *
-     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
-     * method in order to ensure that this buffer has an accessible backing
-     * array.  </p>
-     *
-     * @return  The array that backs this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is backed by an array but is read-only
-     *
-     * @throws  UnsupportedOperationException
-     *          If this buffer is not backed by an accessible array
-     */
-    public final $type$[] array() {
-        if (hb == null)
-            throw new UnsupportedOperationException();
-        if (isReadOnly)
-            throw new ReadOnlyBufferException();
-        return hb;
-    }
-
-    /**
-     * Returns the offset within this buffer's backing array of the first
-     * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> If this buffer is backed by an array then buffer position <i>p</i>
-     * corresponds to array index <i>p</i>&nbsp;+&nbsp;<tt>arrayOffset()</tt>.
-     *
-     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
-     * method in order to ensure that this buffer has an accessible backing
-     * array.  </p>
-     *
-     * @return  The offset within this buffer's array
-     *          of the first element of the buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is backed by an array but is read-only
-     *
-     * @throws  UnsupportedOperationException
-     *          If this buffer is not backed by an accessible array
-     */
-    public final int arrayOffset() {
-        if (hb == null)
-            throw new UnsupportedOperationException();
-        if (isReadOnly)
-            throw new ReadOnlyBufferException();
-        return offset;
-    }
-
-    /**
-     * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> The $fulltype$s between the buffer's current position and its limit,
-     * if any, are copied to the beginning of the buffer.  That is, the
-     * $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
-     * to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
-     * to index one, and so forth until the $fulltype$ at index
-     * <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
-     * <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
-     * The buffer's position is then set to <i>n+1</i> and its limit is set to
-     * its capacity.  The mark, if defined, is discarded.
-     *
-     * <p> The buffer's position is set to the number of $fulltype$s copied,
-     * rather than to zero, so that an invocation of this method can be
-     * followed immediately by an invocation of another relative <i>put</i>
-     * method. </p>
-     *
-#if[byte]
-     *
-     * <p> Invoke this method after writing data from a buffer in case the
-     * write was incomplete.  The following loop, for example, copies bytes
-     * from one channel to another via the buffer <tt>buf</tt>:
-     *
-     * <blockquote><pre>
-     * buf.clear();          // Prepare buffer for use
-     * while (in.read(buf) >= 0 || buf.position != 0) {
-     *     buf.flip();
-     *     out.write(buf);
-     *     buf.compact();    // In case of partial write
-     * }</pre></blockquote>
-     *
-#end[byte]
-     *
-     * @return  This buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract $Type$Buffer compact();
-
-    /**
-     * Tells whether or not this $fulltype$ buffer is direct. </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this buffer is direct
-     */
-    public abstract boolean isDirect();
-
-#if[!char]
-
-    /**
-     * Returns a string summarizing the state of this buffer.  </p>
-     *
-     * @return  A summary string
-     */
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append(getClass().getName());
-        sb.append("[pos=");
-        sb.append(position());
-        sb.append(" lim=");
-        sb.append(limit());
-        sb.append(" cap=");
-        sb.append(capacity());
-        sb.append("]");
-        return sb.toString();
-    }
-
-#end[!char]
-
-
-    // ## Should really use unchecked accessors here for speed
-
-    /**
-     * Returns the current hash code of this buffer.
-     *
-     * <p> The hash code of a $type$ buffer depends only upon its remaining
-     * elements; that is, upon the elements from <tt>position()</tt> up to, and
-     * including, the element at <tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>.
-     *
-     * <p> Because buffer hash codes are content-dependent, it is inadvisable
-     * to use buffers as keys in hash maps or similar data structures unless it
-     * is known that their contents will not change.  </p>
-     *
-     * @return  The current hash code of this buffer
-     */
-    public int hashCode() {
-        int h = 1;
-        int p = position();
-        for (int i = limit() - 1; i >= p; i--)
-            h = 31 * h + (int)get(i);
-        return h;
-    }
-
-    /**
-     * Tells whether or not this buffer is equal to another object.
-     *
-     * <p> Two $type$ buffers are equal if, and only if,
-     *
-     * <p><ol>
-     *
-     *   <li><p> They have the same element type,  </p></li>
-     *
-     *   <li><p> They have the same number of remaining elements, and
-     *   </p></li>
-     *
-     *   <li><p> The two sequences of remaining elements, considered
-     *   independently of their starting positions, are pointwise equal.
-     *   </p></li>
-     *
-     * </ol>
-     *
-     * <p> A $type$ buffer is not equal to any other type of object.  </p>
-     *
-     * @param  ob  The object to which this buffer is to be compared
-     *
-     * @return  <tt>true</tt> if, and only if, this buffer is equal to the
-     *           given object
-     */
-    public boolean equals(Object ob) {
-        if (this == ob)
-            return true;
-        if (!(ob instanceof $Type$Buffer))
-            return false;
-        $Type$Buffer that = ($Type$Buffer)ob;
-        if (this.remaining() != that.remaining())
-            return false;
-        int p = this.position();
-        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 != v2) {
-                if ((v1 != v1) && (v2 != v2))   // For float and double
-                    continue;
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Compares this buffer to another.
-     *
-     * <p> Two $type$ buffers are compared by comparing their sequences of
-     * remaining elements lexicographically, without regard to the starting
-     * position of each sequence within its corresponding buffer.
-     *
-     * <p> A $type$ buffer is not comparable to any other type of object.
-     *
-     * @return  A negative integer, zero, or a positive integer as this buffer
-     *          is less than, equal to, or greater than the given buffer
-     */
-    public int compareTo($Type$Buffer that) {
-        int n = this.position() + Math.min(this.remaining(), that.remaining());
-        for (int i = this.position(), j = that.position(); i < n; i++, j++) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 == v2)
-                continue;
-            if ((v1 != v1) && (v2 != v2))       // For float and double
-                continue;
-            if (v1 < v2)
-                return -1;
-            return +1;
-        }
-        return this.remaining() - that.remaining();
-    }
-
-
-
-    // -- Other char stuff --
-
-#if[char]
-
-    /**
-     * Returns a string containing the characters in this buffer.
-     *
-     * <p> The first character of the resulting string will be the character at
-     * this buffer's position, while the last character will be the character
-     * at index <tt>limit()</tt>&nbsp;-&nbsp;1.  Invoking this method does not
-     * change the buffer's position. </p>
-     *
-     * @return  The specified string
-     */
-    public String toString() {
-        return toString(position(), limit());
-    }
-
-    abstract String toString(int start, int end);       // package-private
-
-
-    // --- Methods to support CharSequence ---
-
-    /**
-     * Returns the length of this character buffer.
-     *
-     * <p> When viewed as a character sequence, the length of a character
-     * buffer is simply the number of characters between the position
-     * (inclusive) and the limit (exclusive); that is, it is equivalent to
-     * <tt>remaining()</tt>. </p>
-     *
-     * @return  The length of this character buffer
-     */
-    public final int length() {
-        return remaining();
-    }
-
-    /**
-     * Reads the character at the given index relative to the current
-     * position. </p>
-     *
-     * @param  index
-     *         The index of the character to be read, relative to the position;
-     *         must be non-negative and smaller than <tt>remaining()</tt>
-     *
-     * @return  The character at index
-     *          <tt>position()&nbsp;+&nbsp;index</tt>
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on <tt>index</tt> do not hold
-     */
-    public final char charAt(int index) {
-        return get(position() + checkIndex(index, 1));
-    }
-
-    /**
-     * Creates a new character buffer that represents the specified subsequence
-     * of this buffer, relative to the current position.
-     *
-     * <p> The new buffer will share this buffer's content; that is, if the
-     * content of this buffer is mutable then modifications to one buffer will
-     * cause the other to be modified.  The new buffer's capacity will be that
-     * of this buffer, its position will be
-     * <tt>position()</tt>&nbsp;+&nbsp;<tt>start</tt>, and its limit will be
-     * <tt>position()</tt>&nbsp;+&nbsp;<tt>end</tt>.  The new buffer will be
-     * direct if, and only if, this buffer is direct, and it will be read-only
-     * if, and only if, this buffer is read-only.  </p>
-     *
-     * @param  start
-     *         The index, relative to the current position, of the first
-     *         character in the subsequence; must be non-negative and no larger
-     *         than <tt>remaining()</tt>
-     *
-     * @param  end
-     *         The index, relative to the current position, of the character
-     *         following the last character in the subsequence; must be no
-     *         smaller than <tt>start</tt> and no larger than
-     *         <tt>remaining()</tt>
-     *
-     * @return  The new character buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on <tt>start</tt> and <tt>end</tt>
-     *          do not hold
-     */
-    public abstract CharBuffer subSequence(int start, int end);
-
-
-    // --- Methods to support Appendable ---
-
-    /**
-     * Appends the specified character sequence  to this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> An invocation of this method of the form <tt>dst.append(csq)</tt>
-     * behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     dst.put(csq.toString()) </pre>
-     *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended.  For instance, invoking the {@link $Type$Buffer#toString()
-     * toString} method of a character buffer will return a subsequence whose
-     * content depends upon the buffer's position and limit.
-     *
-     * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
-     *         appended to this character buffer.
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     *
-     * @since  1.5
-     */
-    public $Type$Buffer append(CharSequence csq) {
-        if (csq == null)
-            return put("null");
-        else
-            return put(csq.toString());
-    }
-
-    /**
-     * Appends a subsequence of the  specified character sequence  to this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> An invocation of this method of the form <tt>dst.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in exactly the
-     * same way as the invocation
-     *
-     * <pre>
-     *     dst.put(csq.subSequence(start, end).toString()) </pre>
-     *
-     * @param  csq
-     *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     *
-     * @since  1.5
-     */
-    public $Type$Buffer append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        return put(cs.subSequence(start, end).toString());
-    }
-
-    /**
-     * Appends the specified $fulltype$  to this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
-     * behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     dst.put($x$) </pre>
-     *
-     * @param  $x$
-     *         The 16-bit $fulltype$ to append
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     *
-     * @since  1.5
-     */
-    public $Type$Buffer append($type$ $x$) {
-        return put($x$);
-    }
-
-#end[char]
-
-
-    // -- Other byte stuff: Access to binary data --
-
-#if[!byte]
-
-    /**
-     * Retrieves this buffer's byte order.
-     *
-     * <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
-     * wrapping an existing <tt>$type$</tt> array is the {@link
-     * ByteOrder#nativeOrder </code>native order<code>} of the underlying
-     * hardware.  The byte order of $a$ $fulltype$ buffer created as a <a
-     * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
-     * byte buffer at the moment that the view is created.  </p>
-     *
-     * @return  This buffer's byte order
-     */
-    public abstract ByteOrder order();
-
-#end[!byte]
-
-#if[byte]
-
-    boolean bigEndian                                   // package-private
-        = true;
-    boolean nativeByteOrder                             // package-private
-        = (Bits.byteOrder() == ByteOrder.BIG_ENDIAN);
-
-    /**
-     * Retrieves this buffer's byte order.
-     *
-     * <p> The byte order is used when reading or writing multibyte values, and
-     * when creating buffers that are views of this byte buffer.  The order of
-     * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
-     * BIG_ENDIAN}.  </p>
-     *
-     * @return  This buffer's byte order
-     */
-    public final ByteOrder order() {
-        return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
-    }
-
-    /**
-     * Modifies this buffer's byte order.  </p>
-     *
-     * @param  bo
-     *         The new byte order,
-     *         either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
-     *         or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
-     *
-     * @return  This buffer
-     */
-    public final $Type$Buffer order(ByteOrder bo) {
-        bigEndian = (bo == ByteOrder.BIG_ENDIAN);
-        nativeByteOrder =
-            (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
-        return this;
-    }
-
-    // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
-    //
-    abstract byte _get(int i);                          // package-private
-    abstract void _put(int i, byte b);                  // package-private
-
-    // #BIN
-    //
-    // Binary-data access methods  for short, char, int, long, float,
-    // and double will be inserted here
-
-#end[byte]
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/X-Buffer.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,1428 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+#if[char]
+import java.io.IOException;
+#end[char]
+
+/**
+ * $A$ $fulltype$ buffer.
+ *
+ * <p> This class defines {#if[byte]?six:four} categories of operations upon
+ * $fulltype$ buffers:
+ *
+ * <ul>
+ *
+ *   <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
+ *   {@link #put($type$) </code><i>put</i><code>} methods that read and write
+ *   single $fulltype$s; </p></li>
+ *
+ *   <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
+ *   methods that transfer contiguous sequences of $fulltype$s from this buffer
+ *   into an array; {#if[!byte]?and}</p></li>
+ *
+ *   <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
+ *   methods that transfer contiguous sequences of $fulltype$s from $a$
+ *   $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
+ *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
+ *
+#if[byte]
+ *
+ *   <li><p> Absolute and relative {@link #getChar() </code><i>get</i><code>}
+ *   and {@link #putChar(char) </code><i>put</i><code>} methods that read and
+ *   write values of other primitive types, translating them to and from
+ *   sequences of bytes in a particular byte order; </p></li>
+ *
+ *   <li><p> Methods for creating <i><a href="#views">view buffers</a></i>,
+ *   which allow a byte buffer to be viewed as a buffer containing values of
+ *   some other primitive type; and </p></li>
+ *
+#end[byte]
+ *
+ *   <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
+ *   #duplicate </code>duplicating<code>}, and {@link #slice
+ *   </code>slicing<code>} $a$ $fulltype$ buffer.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> $Fulltype$ buffers can be created either by {@link #allocate
+ * </code><i>allocation</i><code>}, which allocates space for the buffer's
+ *
+#if[byte]
+ *
+ * content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
+ * existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
+ *
+#else[byte]
+ *
+ * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
+ * $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
+ * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
+ *
+#end[byte]
+ *
+#if[byte]
+ *
+ * <a name="direct">
+ * <h4> Direct <i>vs.</i> non-direct buffers </h4>
+ *
+ * <p> A byte buffer is either <i>direct</i> or <i>non-direct</i>.  Given a
+ * direct byte buffer, the Java virtual machine will make a best effort to
+ * perform native I/O operations directly upon it.  That is, it will attempt to
+ * avoid copying the buffer's content to (or from) an intermediate buffer
+ * before (or after) each invocation of one of the underlying operating
+ * system's native I/O operations.
+ *
+ * <p> A direct byte buffer may be created by invoking the {@link
+ * #allocateDirect(int) allocateDirect} factory method of this class.  The
+ * buffers returned by this method typically have somewhat higher allocation
+ * and deallocation costs than non-direct buffers.  The contents of direct
+ * buffers may reside outside of the normal garbage-collected heap, and so
+ * their impact upon the memory footprint of an application might not be
+ * obvious.  It is therefore recommended that direct buffers be allocated
+ * primarily for large, long-lived buffers that are subject to the underlying
+ * system's native I/O operations.  In general it is best to allocate direct
+ * buffers only when they yield a measureable gain in program performance.
+ *
+ * <p> A direct byte buffer may also be created by {@link
+ * java.nio.channels.FileChannel#map </code>mapping<code>} a region of a file
+ * directly into memory.  An implementation of the Java platform may optionally
+ * support the creation of direct byte buffers from native code via JNI.  If an
+ * instance of one of these kinds of buffers refers to an inaccessible region
+ * of memory then an attempt to access that region will not change the buffer's
+ * content and will cause an unspecified exception to be thrown either at the
+ * time of the access or at some later time.
+ *
+ * <p> Whether a byte buffer is direct or non-direct may be determined by
+ * invoking its {@link #isDirect isDirect} method.  This method is provided so
+ * that explicit buffer management can be done in performance-critical code.
+ *
+ *
+ * <a name="bin">
+ * <h4> Access to binary data </h4>
+ *
+ * <p> This class defines methods for reading and writing values of all other
+ * primitive types, except <tt>boolean</tt>.  Primitive values are translated
+ * to (or from) sequences of bytes according to the buffer's current byte
+ * order, which may be retrieved and modified via the {@link #order order}
+ * methods.  Specific byte orders are represented by instances of the {@link
+ * ByteOrder} class.  The initial order of a byte buffer is always {@link
+ * ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+ *
+ * <p> For access to heterogeneous binary data, that is, sequences of values of
+ * different types, this class defines a family of absolute and relative
+ * <i>get</i> and <i>put</i> methods for each type.  For 32-bit floating-point
+ * values, for example, this class defines:
+ *
+ * <blockquote><pre>
+ * float  {@link #getFloat()}
+ * float  {@link #getFloat(int) getFloat(int index)}
+ *  void  {@link #putFloat(float) putFloat(float f)}
+ *  void  {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
+ *
+ * <p> Corresponding methods are defined for the types <tt>char</tt>,
+ * <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and <tt>double</tt>.  The index
+ * parameters of the absolute <i>get</i> and <i>put</i> methods are in terms of
+ * bytes rather than of the type being read or written.
+ *
+ * <a name="views">
+ *
+ * <p> For access to homogeneous binary data, that is, sequences of values of
+ * the same type, this class defines methods that can create <i>views</i> of a
+ * given byte buffer.  A <i>view buffer</i> is simply another buffer whose
+ * content is backed by the byte buffer.  Changes to the byte buffer's content
+ * will be visible in the view buffer, and vice versa; the two buffers'
+ * position, limit, and mark values are independent.  The {@link
+ * #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of
+ * the {@link FloatBuffer} class that is backed by the byte buffer upon which
+ * the method is invoked.  Corresponding view-creation methods are defined for
+ * the types <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and
+ * <tt>double</tt>.
+ *
+ * <p> View buffers have three important advantages over the families of
+ * type-specific <i>get</i> and <i>put</i> methods described above:
+ *
+ * <ul>
+ *
+ *   <li><p> A view buffer is indexed not in terms of bytes but rather in terms
+ *   of the type-specific size of its values;  </p></li>
+ *
+ *   <li><p> A view buffer provides relative bulk <i>get</i> and <i>put</i>
+ *   methods that can transfer contiguous sequences of values between a buffer
+ *   and an array or some other buffer of the same type; and  </p></li>
+ *
+ *   <li><p> A view buffer is potentially much more efficient because it will
+ *   be direct if, and only if, its backing byte buffer is direct.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> The byte order of a view buffer is fixed to be that of its byte buffer
+ * at the time that the view is created.  </p>
+ *
+#end[byte]
+*
+#if[!byte]
+ *
+ * <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
+ * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
+ * $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
+ * be non-direct.  $A$ $fulltype$ buffer created as a view of a byte buffer will
+ * be direct if, and only if, the byte buffer itself is direct.  Whether or not
+ * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
+ * #isDirect isDirect} method.  </p>
+ *
+#end[!byte]
+*
+#if[char]
+ *
+ * <p> This class implements the {@link CharSequence} interface so that
+ * character buffers may be used wherever character sequences are accepted, for
+ * example in the regular-expression package <tt>{@link java.util.regex}</tt>.
+ * </p>
+ *
+#end[char]
+ *
+#if[byte]
+ * <h4> Invocation chaining </h4>
+#end[byte]
+ *
+ * <p> Methods in this class that do not otherwise have a value to return are
+ * specified to return the buffer upon which they are invoked.  This allows
+ * method invocations to be chained.
+ *
+#if[byte]
+ *
+ * The sequence of statements
+ *
+ * <blockquote><pre>
+ * bb.putInt(0xCAFEBABE);
+ * bb.putShort(3);
+ * bb.putShort(45);</pre></blockquote>
+ *
+ * can, for example, be replaced by the single statement
+ *
+ * <blockquote><pre>
+ * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);</pre></blockquote>
+ *
+#end[byte]
+#if[char]
+ *
+ * The sequence of statements
+ *
+ * <blockquote><pre>
+ * cb.put("text/");
+ * cb.put(subtype);
+ * cb.put("; charset=");
+ * cb.put(enc);</pre></blockquote>
+ *
+ * can, for example, be replaced by the single statement
+ *
+ * <blockquote><pre>
+ * cb.put("text/").put(subtype).put("; charset=").put(enc);</pre></blockquote>
+ *
+#end[char]
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ */
+
+public abstract class $Type$Buffer
+    extends Buffer
+    implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
+{
+
+    // These fields are declared here rather than in Heap-X-Buffer in order to
+    // reduce the number of virtual method invocations needed to access these
+    // values, which is especially costly when coding small buffers.
+    //
+    final $type$[] hb;                  // Non-null only for heap buffers
+    final int offset;
+    boolean isReadOnly;                 // Valid only for heap buffers
+
+    // Creates a new buffer with the given mark, position, limit, capacity,
+    // backing array, and array offset
+    //
+    $Type$Buffer(int mark, int pos, int lim, int cap,   // package-private
+                 $type$[] hb, int offset)
+    {
+        super(mark, pos, lim, cap);
+        this.hb = hb;
+        this.offset = offset;
+    }
+
+    // Creates a new buffer with the given mark, position, limit, and capacity
+    //
+    $Type$Buffer(int mark, int pos, int lim, int cap) { // package-private
+        this(mark, pos, lim, cap, null, 0);
+    }
+
+#if[byte]
+
+    /**
+     * Allocates a new direct $fulltype$ buffer.
+     *
+     * <p> The new buffer's position will be zero, its limit will be its
+     * capacity, its mark will be undefined, and each of its elements will be
+     * initialized to zero.  Whether or not it has a
+     * {@link #hasArray </code>backing array<code>} is unspecified.
+     *
+     * @param  capacity
+     *         The new buffer's capacity, in $fulltype$s
+     *
+     * @return  The new $fulltype$ buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the <tt>capacity</tt> is a negative integer
+     */
+    public static $Type$Buffer allocateDirect(int capacity) {
+        return new Direct$Type$Buffer(capacity);
+    }
+
+#end[byte]
+
+    /**
+     * Allocates a new $fulltype$ buffer.
+     *
+     * <p> The new buffer's position will be zero, its limit will be its
+     * capacity, its mark will be undefined, and each of its elements will be
+     * initialized to zero.  It will have a {@link #array
+     * </code>backing array<code>}, and its {@link #arrayOffset </code>array
+     * offset<code>} will be zero.
+     *
+     * @param  capacity
+     *         The new buffer's capacity, in $fulltype$s
+     *
+     * @return  The new $fulltype$ buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the <tt>capacity</tt> is a negative integer
+     */
+    public static $Type$Buffer allocate(int capacity) {
+        if (capacity < 0)
+            throw new IllegalArgumentException();
+        return new Heap$Type$Buffer(capacity, capacity);
+    }
+
+    /**
+     * Wraps $a$ $fulltype$ array into a buffer.
+     *
+     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * that is, modifications to the buffer will cause the array to be modified
+     * and vice versa.  The new buffer's capacity will be
+     * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
+     * will be <tt>offset + length</tt>, and its mark will be undefined.  Its
+     * {@link #array </code>backing array<code>} will be the given array, and
+     * its {@link #arrayOffset </code>array offset<code>} will be zero.  </p>
+     *
+     * @param  array
+     *         The array that will back the new buffer
+     *
+     * @param  offset
+     *         The offset of the subarray to be used; must be non-negative and
+     *         no larger than <tt>array.length</tt>.  The new buffer's position
+     *         will be set to this value.
+     *
+     * @param  length
+     *         The length of the subarray to be used;
+     *         must be non-negative and no larger than
+     *         <tt>array.length - offset</tt>.
+     *         The new buffer's limit will be set to <tt>offset + length</tt>.
+     *
+     * @return  The new $fulltype$ buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
+     *          parameters do not hold
+     */
+    public static $Type$Buffer wrap($type$[] array,
+                                    int offset, int length)
+    {
+        try {
+            return new Heap$Type$Buffer(array, offset, length);
+        } catch (IllegalArgumentException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Wraps $a$ $fulltype$ array into a buffer.
+     *
+     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * that is, modifications to the buffer will cause the array to be modified
+     * and vice versa.  The new buffer's capacity and limit will be
+     * <tt>array.length</tt>, its position will be zero, and its mark will be
+     * undefined.  Its {@link #array </code>backing array<code>} will be the
+     * given array, and its {@link #arrayOffset </code>array offset<code>} will
+     * be zero.  </p>
+     *
+     * @param  array
+     *         The array that will back this buffer
+     *
+     * @return  The new $fulltype$ buffer
+     */
+    public static $Type$Buffer wrap($type$[] array) {
+        return wrap(array, 0, array.length);
+    }
+
+#if[char]
+
+    /**
+     * Attempts to read characters into the specified character buffer.
+     * The buffer is used as a repository of characters as-is: the only
+     * changes made are the results of a put operation. No flipping or
+     * rewinding of the buffer is performed.
+     *
+     * @param target the buffer to read characters into
+     * @return The number of characters added to the buffer, or
+     *         -1 if this source of characters is at its end
+     * @throws IOException if an I/O error occurs
+     * @throws NullPointerException if target is null
+     * @throws ReadOnlyBufferException if target is a read only buffer
+     * @since 1.5
+     */
+    public int read(CharBuffer target) throws IOException {
+        // Determine the number of bytes n that can be transferred
+        int targetRemaining = target.remaining();
+        int remaining = remaining();
+        if (remaining == 0)
+            return -1;
+        int n = Math.min(remaining, targetRemaining);
+        int limit = limit();
+        // Set source limit to prevent target overflow
+        if (targetRemaining < remaining)
+            limit(position() + n);
+        try {
+            if (n > 0)
+                target.put(this);
+        } finally {
+            limit(limit); // restore real limit
+        }
+        return n;
+    }
+
+    /**
+     * Wraps a character sequence into a buffer.
+     *
+     * <p> The content of the new, read-only buffer will be the content of the
+     * given character sequence.  The buffer's capacity will be
+     * <tt>csq.length()</tt>, its position will be <tt>start</tt>, its limit
+     * will be <tt>end</tt>, and its mark will be undefined.  </p>
+     *
+     * @param  csq
+     *         The character sequence from which the new character buffer is to
+     *         be created
+     *
+     * @param  start
+     *         The index of the first character to be used;
+     *         must be non-negative and no larger than <tt>csq.length()</tt>.
+     *         The new buffer's position will be set to this value.
+     *
+     * @param  end
+     *         The index of the character following the last character to be
+     *         used; must be no smaller than <tt>start</tt> and no larger
+     *         than <tt>csq.length()</tt>.
+     *         The new buffer's limit will be set to this value.
+     *
+     * @return  The new character buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
+     *          parameters do not hold
+     */
+    public static CharBuffer wrap(CharSequence csq, int start, int end) {
+        try {
+            return new StringCharBuffer(csq, start, end);
+        } catch (IllegalArgumentException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Wraps a character sequence into a buffer.
+     *
+     * <p> The content of the new, read-only buffer will be the content of the
+     * given character sequence.  The new buffer's capacity and limit will be
+     * <tt>csq.length()</tt>, its position will be zero, and its mark will be
+     * undefined.  </p>
+     *
+     * @param  csq
+     *         The character sequence from which the new character buffer is to
+     *         be created
+     *
+     * @return  The new character buffer
+     */
+    public static CharBuffer wrap(CharSequence csq) {
+        return wrap(csq, 0, csq.length());
+    }
+
+#end[char]
+
+    /**
+     * Creates a new $fulltype$ buffer whose content is a shared subsequence of
+     * this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of $fulltype$s remaining in this buffer, and its mark
+     * will be undefined.  The new buffer will be direct if, and only if, this
+     * buffer is direct, and it will be read-only if, and only if, this buffer
+     * is read-only.  </p>
+     *
+     * @return  The new $fulltype$ buffer
+     */
+    public abstract $Type$Buffer slice();
+
+    /**
+     * Creates a new $fulltype$ buffer that shares this buffer's content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer, and vice
+     * versa; the two buffers' position, limit, and mark values will be
+     * independent.
+     *
+     * <p> The new buffer's capacity, limit, position, and mark values will be
+     * identical to those of this buffer.  The new buffer will be direct if,
+     * and only if, this buffer is direct, and it will be read-only if, and
+     * only if, this buffer is read-only.  </p>
+     *
+     * @return  The new $fulltype$ buffer
+     */
+    public abstract $Type$Buffer duplicate();
+
+    /**
+     * Creates a new, read-only $fulltype$ buffer that shares this buffer's
+     * content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer; the new
+     * buffer itself, however, will be read-only and will not allow the shared
+     * content to be modified.  The two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's capacity, limit, position, and mark values will be
+     * identical to those of this buffer.
+     *
+     * <p> If this buffer is itself read-only then this method behaves in
+     * exactly the same way as the {@link #duplicate duplicate} method.  </p>
+     *
+     * @return  The new, read-only $fulltype$ buffer
+     */
+    public abstract $Type$Buffer asReadOnlyBuffer();
+
+
+    // -- Singleton get/put methods --
+
+    /**
+     * Relative <i>get</i> method.  Reads the $fulltype$ at this buffer's
+     * current position, and then increments the position. </p>
+     *
+     * @return  The $fulltype$ at the buffer's current position
+     *
+     * @throws  BufferUnderflowException
+     *          If the buffer's current position is not smaller than its limit
+     */
+    public abstract $type$ get();
+
+    /**
+     * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes the given $fulltype$ into this buffer at the current
+     * position, and then increments the position. </p>
+     *
+     * @param  $x$
+     *         The $fulltype$ to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If this buffer's current position is not smaller than its limit
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer put($type$ $x$);
+
+    /**
+     * Absolute <i>get</i> method.  Reads the $fulltype$ at the given
+     * index. </p>
+     *
+     * @param  index
+     *         The index from which the $fulltype$ will be read
+     *
+     * @return  The $fulltype$ at the given index
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit
+     */
+    public abstract $type$ get(int index);
+
+    /**
+     * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes the given $fulltype$ into this buffer at the given
+     * index. </p>
+     *
+     * @param  index
+     *         The index at which the $fulltype$ will be written
+     *
+     * @param  $x$
+     *         The $fulltype$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer put(int index, $type$ $x$);
+
+
+    // -- Bulk get operations --
+
+    /**
+     * Relative bulk <i>get</i> method.
+     *
+     * <p> This method transfers $fulltype$s from this buffer into the given
+     * destination array.  If there are fewer $fulltype$s remaining in the
+     * buffer than are required to satisfy the request, that is, if
+     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
+     * $fulltype$s are transferred and a {@link BufferUnderflowException} is
+     * thrown.
+     *
+     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
+     * buffer into the given array, starting at the current position of this
+     * buffer and at the given offset in the array.  The position of this
+     * buffer is then incremented by <tt>length</tt>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>src.get(dst,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
+     * the loop
+     *
+     * <pre>
+     *     for (int i = off; i < off + len; i++)
+     *         dst[i] = src.get(); </pre>
+     *
+     * except that it first checks that there are sufficient $fulltype$s in
+     * this buffer and it is potentially much more efficient. </p>
+     *
+     * @param  dst
+     *         The array into which $fulltype$s are to be written
+     *
+     * @param  offset
+     *         The offset within the array of the first $fulltype$ to be
+     *         written; must be non-negative and no larger than
+     *         <tt>dst.length</tt>
+     *
+     * @param  length
+     *         The maximum number of $fulltype$s to be written to the given
+     *         array; must be non-negative and no larger than
+     *         <tt>dst.length - offset</tt>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          remaining in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
+     *          parameters do not hold
+     */
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+        checkBounds(offset, length, dst.length);
+        if (length > remaining())
+            throw new BufferUnderflowException();
+        int end = offset + length;
+        for (int i = offset; i < end; i++)
+            dst[i] = get();
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>get</i> method.
+     *
+     * <p> This method transfers $fulltype$s from this buffer into the given
+     * destination array.  An invocation of this method of the form
+     * <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     src.get(a, 0, a.length) </pre>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          remaining in this buffer
+     */
+    public $Type$Buffer get($type$[] dst) {
+        return get(dst, 0, dst.length);
+    }
+
+
+    // -- Bulk put operations --
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the $fulltype$s remaining in the given source
+     * buffer into this buffer.  If there are more $fulltype$s remaining in the
+     * source buffer than in this buffer, that is, if
+     * <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
+     * then no $fulltype$s are transferred and a {@link
+     * BufferOverflowException} is thrown.
+     *
+     * <p> Otherwise, this method copies
+     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
+     * buffer into this buffer, starting at each buffer's current position.
+     * The positions of both buffers are then incremented by <i>n</i>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>dst.put(src)</tt> has exactly the same effect as the loop
+     *
+     * <pre>
+     *     while (src.hasRemaining())
+     *         dst.put(src.get()); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient. </p>
+     *
+     * @param  src
+     *         The source buffer from which $fulltype$s are to be read;
+     *         must not be this buffer
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *          for the remaining $fulltype$s in the source buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the source buffer is this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put($Type$Buffer src) {
+        if (src == this)
+            throw new IllegalArgumentException();
+        int n = src.remaining();
+        if (n > remaining())
+            throw new BufferOverflowException();
+        for (int i = 0; i < n; i++)
+            put(src.get());
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers $fulltype$s into this buffer from the given
+     * source array.  If there are more $fulltype$s to be copied from the array
+     * than remain in this buffer, that is, if
+     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
+     * $fulltype$s are transferred and a {@link BufferOverflowException} is
+     * thrown.
+     *
+     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
+     * given array into this buffer, starting at the given offset in the array
+     * and at the current position of this buffer.  The position of this buffer
+     * is then incremented by <tt>length</tt>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>dst.put(src,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
+     * the loop
+     *
+     * <pre>
+     *     for (int i = off; i < off + len; i++)
+     *         dst.put(a[i]); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient. </p>
+     *
+     * @param  src
+     *         The array from which $fulltype$s are to be read
+     *
+     * @param  offset
+     *         The offset within the array of the first $fulltype$ to be read;
+     *         must be non-negative and no larger than <tt>array.length</tt>
+     *
+     * @param  length
+     *         The number of $fulltype$s to be read from the given array;
+     *         must be non-negative and no larger than
+     *         <tt>array.length - offset</tt>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
+     *          parameters do not hold
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+        checkBounds(offset, length, src.length);
+        if (length > remaining())
+            throw new BufferOverflowException();
+        int end = offset + length;
+        for (int i = offset; i < end; i++)
+            this.put(src[i]);
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the entire content of the given source
+     * $fulltype$ array into this buffer.  An invocation of this method of the
+     * form <tt>dst.put(a)</tt> behaves in exactly the same way as the
+     * invocation
+     *
+     * <pre>
+     *     dst.put(a, 0, a.length) </pre>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public final $Type$Buffer put($type$[] src) {
+        return put(src, 0, src.length);
+    }
+
+#if[char]
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers $fulltype$s from the given string into this
+     * buffer.  If there are more $fulltype$s to be copied from the string than
+     * remain in this buffer, that is, if
+     * <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
+     * then no $fulltype$s are transferred and a {@link
+     * BufferOverflowException} is thrown.
+     *
+     * <p> Otherwise, this method copies
+     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
+     * from the given string into this buffer, starting at the given
+     * <tt>start</tt> index and at the current position of this buffer.  The
+     * position of this buffer is then incremented by <i>n</i>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>dst.put(src,&nbsp;start,&nbsp;end)</tt> has exactly the same effect
+     * as the loop
+     *
+     * <pre>
+     *     for (int i = start; i < end; i++)
+     *         dst.put(src.charAt(i)); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient. </p>
+     *
+     * @param  src
+     *         The string from which $fulltype$s are to be read
+     *
+     * @param  start
+     *         The offset within the string of the first $fulltype$ to be read;
+     *         must be non-negative and no larger than
+     *         <tt>string.length()</tt>
+     *
+     * @param  end
+     *         The offset within the string of the last $fulltype$ to be read,
+     *         plus one; must be non-negative and no larger than
+     *         <tt>string.length()</tt>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
+     *          parameters do not hold
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put(String src, int start, int end) {
+        checkBounds(start, end - start, src.length());
+        for (int i = start; i < end; i++)
+            this.put(src.charAt(i));
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the entire content of the given source string
+     * into this buffer.  An invocation of this method of the form
+     * <tt>dst.put(s)</tt> behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put(s, 0, s.length()) </pre>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public final $Type$Buffer put(String src) {
+        return put(src, 0, src.length());
+    }
+
+#end[char]
+
+
+    // -- Other stuff --
+
+    /**
+     * Tells whether or not this buffer is backed by an accessible $fulltype$
+     * array.
+     *
+     * <p> If this method returns <tt>true</tt> then the {@link #array() array}
+     * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
+     * </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this buffer
+     *          is backed by an array and is not read-only
+     */
+    public final boolean hasArray() {
+        return (hb != null) && !isReadOnly;
+    }
+
+    /**
+     * Returns the $fulltype$ array that backs this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Modifications to this buffer's content will cause the returned
+     * array's content to be modified, and vice versa.
+     *
+     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
+     * method in order to ensure that this buffer has an accessible backing
+     * array.  </p>
+     *
+     * @return  The array that backs this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is backed by an array but is read-only
+     *
+     * @throws  UnsupportedOperationException
+     *          If this buffer is not backed by an accessible array
+     */
+    public final $type$[] array() {
+        if (hb == null)
+            throw new UnsupportedOperationException();
+        if (isReadOnly)
+            throw new ReadOnlyBufferException();
+        return hb;
+    }
+
+    /**
+     * Returns the offset within this buffer's backing array of the first
+     * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this buffer is backed by an array then buffer position <i>p</i>
+     * corresponds to array index <i>p</i>&nbsp;+&nbsp;<tt>arrayOffset()</tt>.
+     *
+     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
+     * method in order to ensure that this buffer has an accessible backing
+     * array.  </p>
+     *
+     * @return  The offset within this buffer's array
+     *          of the first element of the buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is backed by an array but is read-only
+     *
+     * @throws  UnsupportedOperationException
+     *          If this buffer is not backed by an accessible array
+     */
+    public final int arrayOffset() {
+        if (hb == null)
+            throw new UnsupportedOperationException();
+        if (isReadOnly)
+            throw new ReadOnlyBufferException();
+        return offset;
+    }
+
+    /**
+     * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> The $fulltype$s between the buffer's current position and its limit,
+     * if any, are copied to the beginning of the buffer.  That is, the
+     * $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
+     * to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
+     * to index one, and so forth until the $fulltype$ at index
+     * <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
+     * <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
+     * The buffer's position is then set to <i>n+1</i> and its limit is set to
+     * its capacity.  The mark, if defined, is discarded.
+     *
+     * <p> The buffer's position is set to the number of $fulltype$s copied,
+     * rather than to zero, so that an invocation of this method can be
+     * followed immediately by an invocation of another relative <i>put</i>
+     * method. </p>
+     *
+#if[byte]
+     *
+     * <p> Invoke this method after writing data from a buffer in case the
+     * write was incomplete.  The following loop, for example, copies bytes
+     * from one channel to another via the buffer <tt>buf</tt>:
+     *
+     * <blockquote><pre>
+     * buf.clear();          // Prepare buffer for use
+     * while (in.read(buf) >= 0 || buf.position != 0) {
+     *     buf.flip();
+     *     out.write(buf);
+     *     buf.compact();    // In case of partial write
+     * }</pre></blockquote>
+     *
+#end[byte]
+     *
+     * @return  This buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer compact();
+
+    /**
+     * Tells whether or not this $fulltype$ buffer is direct. </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this buffer is direct
+     */
+    public abstract boolean isDirect();
+
+#if[!char]
+
+    /**
+     * Returns a string summarizing the state of this buffer.  </p>
+     *
+     * @return  A summary string
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(getClass().getName());
+        sb.append("[pos=");
+        sb.append(position());
+        sb.append(" lim=");
+        sb.append(limit());
+        sb.append(" cap=");
+        sb.append(capacity());
+        sb.append("]");
+        return sb.toString();
+    }
+
+#end[!char]
+
+
+    // ## Should really use unchecked accessors here for speed
+
+    /**
+     * Returns the current hash code of this buffer.
+     *
+     * <p> The hash code of a $type$ buffer depends only upon its remaining
+     * elements; that is, upon the elements from <tt>position()</tt> up to, and
+     * including, the element at <tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>.
+     *
+     * <p> Because buffer hash codes are content-dependent, it is inadvisable
+     * to use buffers as keys in hash maps or similar data structures unless it
+     * is known that their contents will not change.  </p>
+     *
+     * @return  The current hash code of this buffer
+     */
+    public int hashCode() {
+        int h = 1;
+        int p = position();
+        for (int i = limit() - 1; i >= p; i--)
+            h = 31 * h + (int)get(i);
+        return h;
+    }
+
+    /**
+     * Tells whether or not this buffer is equal to another object.
+     *
+     * <p> Two $type$ buffers are equal if, and only if,
+     *
+     * <p><ol>
+     *
+     *   <li><p> They have the same element type,  </p></li>
+     *
+     *   <li><p> They have the same number of remaining elements, and
+     *   </p></li>
+     *
+     *   <li><p> The two sequences of remaining elements, considered
+     *   independently of their starting positions, are pointwise equal.
+     *   </p></li>
+     *
+     * </ol>
+     *
+     * <p> A $type$ buffer is not equal to any other type of object.  </p>
+     *
+     * @param  ob  The object to which this buffer is to be compared
+     *
+     * @return  <tt>true</tt> if, and only if, this buffer is equal to the
+     *           given object
+     */
+    public boolean equals(Object ob) {
+        if (this == ob)
+            return true;
+        if (!(ob instanceof $Type$Buffer))
+            return false;
+        $Type$Buffer that = ($Type$Buffer)ob;
+        if (this.remaining() != that.remaining())
+            return false;
+        int p = this.position();
+        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
+            $type$ v1 = this.get(i);
+            $type$ v2 = that.get(j);
+            if (v1 != v2) {
+                if ((v1 != v1) && (v2 != v2))   // For float and double
+                    continue;
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Compares this buffer to another.
+     *
+     * <p> Two $type$ buffers are compared by comparing their sequences of
+     * remaining elements lexicographically, without regard to the starting
+     * position of each sequence within its corresponding buffer.
+     *
+     * <p> A $type$ buffer is not comparable to any other type of object.
+     *
+     * @return  A negative integer, zero, or a positive integer as this buffer
+     *          is less than, equal to, or greater than the given buffer
+     */
+    public int compareTo($Type$Buffer that) {
+        int n = this.position() + Math.min(this.remaining(), that.remaining());
+        for (int i = this.position(), j = that.position(); i < n; i++, j++) {
+            $type$ v1 = this.get(i);
+            $type$ v2 = that.get(j);
+            if (v1 == v2)
+                continue;
+            if ((v1 != v1) && (v2 != v2))       // For float and double
+                continue;
+            if (v1 < v2)
+                return -1;
+            return +1;
+        }
+        return this.remaining() - that.remaining();
+    }
+
+
+
+    // -- Other char stuff --
+
+#if[char]
+
+    /**
+     * Returns a string containing the characters in this buffer.
+     *
+     * <p> The first character of the resulting string will be the character at
+     * this buffer's position, while the last character will be the character
+     * at index <tt>limit()</tt>&nbsp;-&nbsp;1.  Invoking this method does not
+     * change the buffer's position. </p>
+     *
+     * @return  The specified string
+     */
+    public String toString() {
+        return toString(position(), limit());
+    }
+
+    abstract String toString(int start, int end);       // package-private
+
+
+    // --- Methods to support CharSequence ---
+
+    /**
+     * Returns the length of this character buffer.
+     *
+     * <p> When viewed as a character sequence, the length of a character
+     * buffer is simply the number of characters between the position
+     * (inclusive) and the limit (exclusive); that is, it is equivalent to
+     * <tt>remaining()</tt>. </p>
+     *
+     * @return  The length of this character buffer
+     */
+    public final int length() {
+        return remaining();
+    }
+
+    /**
+     * Reads the character at the given index relative to the current
+     * position. </p>
+     *
+     * @param  index
+     *         The index of the character to be read, relative to the position;
+     *         must be non-negative and smaller than <tt>remaining()</tt>
+     *
+     * @return  The character at index
+     *          <tt>position()&nbsp;+&nbsp;index</tt>
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on <tt>index</tt> do not hold
+     */
+    public final char charAt(int index) {
+        return get(position() + checkIndex(index, 1));
+    }
+
+    /**
+     * Creates a new character buffer that represents the specified subsequence
+     * of this buffer, relative to the current position.
+     *
+     * <p> The new buffer will share this buffer's content; that is, if the
+     * content of this buffer is mutable then modifications to one buffer will
+     * cause the other to be modified.  The new buffer's capacity will be that
+     * of this buffer, its position will be
+     * <tt>position()</tt>&nbsp;+&nbsp;<tt>start</tt>, and its limit will be
+     * <tt>position()</tt>&nbsp;+&nbsp;<tt>end</tt>.  The new buffer will be
+     * direct if, and only if, this buffer is direct, and it will be read-only
+     * if, and only if, this buffer is read-only.  </p>
+     *
+     * @param  start
+     *         The index, relative to the current position, of the first
+     *         character in the subsequence; must be non-negative and no larger
+     *         than <tt>remaining()</tt>
+     *
+     * @param  end
+     *         The index, relative to the current position, of the character
+     *         following the last character in the subsequence; must be no
+     *         smaller than <tt>start</tt> and no larger than
+     *         <tt>remaining()</tt>
+     *
+     * @return  The new character buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on <tt>start</tt> and <tt>end</tt>
+     *          do not hold
+     */
+    public abstract CharBuffer subSequence(int start, int end);
+
+
+    // --- Methods to support Appendable ---
+
+    /**
+     * Appends the specified character sequence  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form <tt>dst.append(csq)</tt>
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put(csq.toString()) </pre>
+     *
+     * <p> Depending on the specification of <tt>toString</tt> for the
+     * character sequence <tt>csq</tt>, the entire sequence may not be
+     * appended.  For instance, invoking the {@link $Type$Buffer#toString()
+     * toString} method of a character buffer will return a subsequence whose
+     * content depends upon the buffer's position and limit.
+     *
+     * @param  csq
+     *         The character sequence to append.  If <tt>csq</tt> is
+     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         appended to this character buffer.
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append(CharSequence csq) {
+        if (csq == null)
+            return put("null");
+        else
+            return put(csq.toString());
+    }
+
+    /**
+     * Appends a subsequence of the  specified character sequence  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form <tt>dst.append(csq, start,
+     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in exactly the
+     * same way as the invocation
+     *
+     * <pre>
+     *     dst.put(csq.subSequence(start, end).toString()) </pre>
+     *
+     * @param  csq
+     *         The character sequence from which a subsequence will be
+     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
+     *         will be appended as if <tt>csq</tt> contained the four
+     *         characters <tt>"null"</tt>.
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
+     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
+     *          <tt>csq.length()</tt>
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append(CharSequence csq, int start, int end) {
+        CharSequence cs = (csq == null ? "null" : csq);
+        return put(cs.subSequence(start, end).toString());
+    }
+
+    /**
+     * Appends the specified $fulltype$  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put($x$) </pre>
+     *
+     * @param  $x$
+     *         The 16-bit $fulltype$ to append
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append($type$ $x$) {
+        return put($x$);
+    }
+
+#end[char]
+
+
+    // -- Other byte stuff: Access to binary data --
+
+#if[!byte]
+
+    /**
+     * Retrieves this buffer's byte order.
+     *
+     * <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
+     * wrapping an existing <tt>$type$</tt> array is the {@link
+     * ByteOrder#nativeOrder </code>native order<code>} of the underlying
+     * hardware.  The byte order of $a$ $fulltype$ buffer created as a <a
+     * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
+     * byte buffer at the moment that the view is created.  </p>
+     *
+     * @return  This buffer's byte order
+     */
+    public abstract ByteOrder order();
+
+#end[!byte]
+
+#if[byte]
+
+    boolean bigEndian                                   // package-private
+        = true;
+    boolean nativeByteOrder                             // package-private
+        = (Bits.byteOrder() == ByteOrder.BIG_ENDIAN);
+
+    /**
+     * Retrieves this buffer's byte order.
+     *
+     * <p> The byte order is used when reading or writing multibyte values, and
+     * when creating buffers that are views of this byte buffer.  The order of
+     * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
+     * BIG_ENDIAN}.  </p>
+     *
+     * @return  This buffer's byte order
+     */
+    public final ByteOrder order() {
+        return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+    }
+
+    /**
+     * Modifies this buffer's byte order.  </p>
+     *
+     * @param  bo
+     *         The new byte order,
+     *         either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
+     *         or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
+     *
+     * @return  This buffer
+     */
+    public final $Type$Buffer order(ByteOrder bo) {
+        bigEndian = (bo == ByteOrder.BIG_ENDIAN);
+        nativeByteOrder =
+            (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
+        return this;
+    }
+
+    // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
+    //
+    abstract byte _get(int i);                          // package-private
+    abstract void _put(int i, byte b);                  // package-private
+
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+}
--- a/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,972 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio.charset;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.lang.ref.WeakReference;
-import java.nio.charset.CoderMalfunctionError;                  // javadoc
-
-
-/**
- * An engine that can transform a sequence of $itypesPhrase$ into a sequence of
- * $otypesPhrase$.
- *
- * <a name="steps">
- *
- * <p> The input $itype$ sequence is provided in a $itype$ buffer or a series
- * of such buffers.  The output $otype$ sequence is written to a $otype$ buffer
- * or a series of such buffers.  $A$ $coder$ should always be used by making
- * the following sequence of method invocations, hereinafter referred to as $a$
- * <i>$coding$ operation</i>:
- *
- * <ol>
- *
- *   <li><p> Reset the $coder$ via the {@link #reset reset} method, unless it
- *   has not been used before; </p></li>
- *
- *   <li><p> Invoke the {@link #$code$ $code$} method zero or more times, as
- *   long as additional input may be available, passing <tt>false</tt> for the
- *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
- *   output buffer between invocations; </p></li>
- *
- *   <li><p> Invoke the {@link #$code$ $code$} method one final time, passing
- *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
- *
- *   <li><p> Invoke the {@link #flush flush} method so that the $coder$ can
- *   flush any internal state to the output buffer. </p></li>
- *
- * </ol>
- *
- * Each invocation of the {@link #$code$ $code$} method will $code$ as many
- * $itype$s as possible from the input buffer, writing the resulting $otype$s
- * to the output buffer.  The {@link #$code$ $code$} method returns when more
- * input is required, when there is not enough room in the output buffer, or
- * when $a$ $coding$ error has occurred.  In each case a {@link CoderResult}
- * object is returned to describe the reason for termination.  An invoker can
- * examine this object and fill the input buffer, flush the output buffer, or
- * attempt to recover from $a$ $coding$ error, as appropriate, and try again.
- *
- * <a name="ce">
- *
- * <p> There are two general types of $coding$ errors.  If the input $itype$
- * sequence is $notLegal$ then the input is considered <i>malformed</i>.  If
- * the input $itype$ sequence is legal but cannot be mapped to a valid
- * $outSequence$ then an <i>unmappable character</i> has been encountered.
- *
- * <a name="cae">
- *
- * <p> How $a$ $coding$ error is handled depends upon the action requested for
- * that type of error, which is described by an instance of the {@link
- * CodingErrorAction} class.  The possible error actions are to {@link
- * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
- * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
- * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
- * </code>replace<code>} the erroneous input with the current value of the
- * replacement $replTypeName$.  The replacement
- *
-#if[encoder]
- * is initially set to the $coder$'s default replacement, which often
- * (but not always) has the initial value&nbsp;$defaultReplName$;
-#end[encoder]
-#if[decoder]
- * has the initial value $defaultReplName$;
-#end[decoder]
- *
- * its value may be changed via the {@link #replaceWith($replFQType$)
- * replaceWith} method.
- *
- * <p> The default action for malformed-input and unmappable-character errors
- * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
- * malformed-input error action may be changed via the {@link
- * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
- * unmappable-character action may be changed via the {@link
- * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
- *
- * <p> This class is designed to handle many of the details of the $coding$
- * process, including the implementation of error actions.  $A$ $coder$ for a
- * specific charset, which is a concrete subclass of this class, need only
- * implement the abstract {@link #$code$Loop $code$Loop} method, which
- * encapsulates the basic $coding$ loop.  A subclass that maintains internal
- * state should, additionally, override the {@link #implFlush implFlush} and
- * {@link #implReset implReset} methods.
- *
- * <p> Instances of this class are not safe for use by multiple concurrent
- * threads.  </p>
- *
- *
- * @author Mark Reinhold
- * @author JSR-51 Expert Group
- * @since 1.4
- *
- * @see ByteBuffer
- * @see CharBuffer
- * @see Charset
- * @see Charset$OtherCoder$
- */
-
-public abstract class Charset$Coder$ {
-
-    private final Charset charset;
-    private final float average$ItypesPerOtype$;
-    private final float max$ItypesPerOtype$;
-
-    private $replType$ replacement;
-    private CodingErrorAction malformedInputAction
-        = CodingErrorAction.REPORT;
-    private CodingErrorAction unmappableCharacterAction
-        = CodingErrorAction.REPORT;
-
-    // Internal states
-    //
-    private static final int ST_RESET   = 0;
-    private static final int ST_CODING  = 1;
-    private static final int ST_END     = 2;
-    private static final int ST_FLUSHED = 3;
-
-    private int state = ST_RESET;
-
-    private static String stateNames[]
-        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
-
-
-    /**
-     * Initializes a new $coder$.  The new $coder$ will have the given
-     * $otypes-per-itype$ and replacement values. </p>
-     *
-     * @param  average$ItypesPerOtype$
-     *         A positive float value indicating the expected number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @param  max$ItypesPerOtype$
-     *         A positive float value indicating the maximum number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @param  replacement
-     *         The initial replacement; must not be <tt>null</tt>, must have
-     *         non-zero length, must not be longer than max$ItypesPerOtype$,
-     *         and must be {@link #isLegalReplacement </code>legal<code>}
-     *
-     * @throws  IllegalArgumentException
-     *          If the preconditions on the parameters do not hold
-     */
-    {#if[encoder]?protected:private}
-    Charset$Coder$(Charset cs,
-                   float average$ItypesPerOtype$,
-                   float max$ItypesPerOtype$,
-                   $replType$ replacement)
-    {
-        this.charset = cs;
-        if (average$ItypesPerOtype$ <= 0.0f)
-            throw new IllegalArgumentException("Non-positive "
-                                               + "average$ItypesPerOtype$");
-        if (max$ItypesPerOtype$ <= 0.0f)
-            throw new IllegalArgumentException("Non-positive "
-                                               + "max$ItypesPerOtype$");
-        if (!Charset.atBugLevel("1.4")) {
-            if (average$ItypesPerOtype$ > max$ItypesPerOtype$)
-                throw new IllegalArgumentException("average$ItypesPerOtype$"
-                                                   + " exceeds "
-                                                   + "max$ItypesPerOtype$");
-        }
-        this.replacement = replacement;
-        this.average$ItypesPerOtype$ = average$ItypesPerOtype$;
-        this.max$ItypesPerOtype$ = max$ItypesPerOtype$;
-        replaceWith(replacement);
-    }
-
-    /**
-     * Initializes a new $coder$.  The new $coder$ will have the given
-     * $otypes-per-itype$ values and its replacement will be the
-     * $replTypeName$ $defaultReplName$. </p>
-     *
-     * @param  average$ItypesPerOtype$
-     *         A positive float value indicating the expected number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @param  max$ItypesPerOtype$
-     *         A positive float value indicating the maximum number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @throws  IllegalArgumentException
-     *          If the preconditions on the parameters do not hold
-     */
-    protected Charset$Coder$(Charset cs,
-                             float average$ItypesPerOtype$,
-                             float max$ItypesPerOtype$)
-    {
-        this(cs,
-             average$ItypesPerOtype$, max$ItypesPerOtype$,
-             $defaultRepl$);
-    }
-
-    /**
-     * Returns the charset that created this $coder$.  </p>
-     *
-     * @return  This $coder$'s charset
-     */
-    public final Charset charset() {
-        return charset;
-    }
-
-    /**
-     * Returns this $coder$'s replacement value. </p>
-     *
-     * @return  This $coder$'s current replacement,
-     *          which is never <tt>null</tt> and is never empty
-     */
-    public final $replType$ replacement() {
-        return replacement;
-    }
-
-    /**
-     * Changes this $coder$'s replacement value.
-     *
-     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
-     * method, passing the new replacement, after checking that the new
-     * replacement is acceptable.  </p>
-     *
-     * @param  newReplacement
-     *
-#if[decoder]
-     *         The new replacement; must not be <tt>null</tt>
-     *         and must have non-zero length
-#end[decoder]
-#if[encoder]
-     *         The new replacement; must not be <tt>null</tt>, must have
-     *         non-zero length, must not be longer than the value returned by
-     *         the {@link #max$ItypesPerOtype$() max$ItypesPerOtype$} method, and
-     *         must be {@link #isLegalReplacement </code>legal<code>}
-#end[encoder]
-     *
-     * @return  This $coder$
-     *
-     * @throws  IllegalArgumentException
-     *          If the preconditions on the parameter do not hold
-     */
-    public final Charset$Coder$ replaceWith($replType$ newReplacement) {
-        if (newReplacement == null)
-            throw new IllegalArgumentException("Null replacement");
-        int len = newReplacement.$replLength$;
-        if (len == 0)
-            throw new IllegalArgumentException("Empty replacement");
-        if (len > max$ItypesPerOtype$)
-            throw new IllegalArgumentException("Replacement too long");
-#if[encoder]
-        if (!isLegalReplacement(newReplacement))
-            throw new IllegalArgumentException("Illegal replacement");
-#end[encoder]
-        this.replacement = newReplacement;
-        implReplaceWith(newReplacement);
-        return this;
-    }
-
-    /**
-     * Reports a change to this $coder$'s replacement value.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that require notification of changes to
-     * the replacement.  </p>
-     *
-     * @param  newReplacement
-     */
-    protected void implReplaceWith($replType$ newReplacement) {
-    }
-
-#if[encoder]
-
-    private WeakReference<CharsetDecoder> cachedDecoder = null;
-
-    /**
-     * Tells whether or not the given byte array is a legal replacement value
-     * for this encoder.
-     *
-     * <p> A replacement is legal if, and only if, it is a legal sequence of
-     * bytes in this encoder's charset; that is, it must be possible to decode
-     * the replacement into one or more sixteen-bit Unicode characters.
-     *
-     * <p> The default implementation of this method is not very efficient; it
-     * should generally be overridden to improve performance.  </p>
-     *
-     * @param  repl  The byte array to be tested
-     *
-     * @return  <tt>true</tt> if, and only if, the given byte array
-     *          is a legal replacement value for this encoder
-     */
-    public boolean isLegalReplacement(byte[] repl) {
-        WeakReference<CharsetDecoder> wr = cachedDecoder;
-        CharsetDecoder dec = null;
-        if ((wr == null) || ((dec = wr.get()) == null)) {
-            dec = charset().newDecoder();
-            dec.onMalformedInput(CodingErrorAction.REPORT);
-            dec.onUnmappableCharacter(CodingErrorAction.REPORT);
-            cachedDecoder = new WeakReference<CharsetDecoder>(dec);
-        } else {
-            dec.reset();
-        }
-        ByteBuffer bb = ByteBuffer.wrap(repl);
-        CharBuffer cb = CharBuffer.allocate((int)(bb.remaining()
-                                                  * dec.maxCharsPerByte()));
-        CoderResult cr = dec.decode(bb, cb, true);
-        return !cr.isError();
-    }
-
-#end[encoder]
-
-    /**
-     * Returns this $coder$'s current action for malformed-input errors.  </p>
-     *
-     * @return The current malformed-input action, which is never <tt>null</tt>
-     */
-    public CodingErrorAction malformedInputAction() {
-        return malformedInputAction;
-    }
-
-    /**
-     * Changes this $coder$'s action for malformed-input errors.  </p>
-     *
-     * <p> This method invokes the {@link #implOnMalformedInput
-     * implOnMalformedInput} method, passing the new action.  </p>
-     *
-     * @param  newAction  The new action; must not be <tt>null</tt>
-     *
-     * @return  This $coder$
-     *
-     * @throws IllegalArgumentException
-     *         If the precondition on the parameter does not hold
-     */
-    public final Charset$Coder$ onMalformedInput(CodingErrorAction newAction) {
-        if (newAction == null)
-            throw new IllegalArgumentException("Null action");
-        malformedInputAction = newAction;
-        implOnMalformedInput(newAction);
-        return this;
-    }
-
-    /**
-     * Reports a change to this $coder$'s malformed-input action.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that require notification of changes to
-     * the malformed-input action.  </p>
-     */
-    protected void implOnMalformedInput(CodingErrorAction newAction) { }
-
-    /**
-     * Returns this $coder$'s current action for unmappable-character errors.
-     * </p>
-     *
-     * @return The current unmappable-character action, which is never
-     *         <tt>null</tt>
-     */
-    public CodingErrorAction unmappableCharacterAction() {
-        return unmappableCharacterAction;
-    }
-
-    /**
-     * Changes this $coder$'s action for unmappable-character errors.
-     *
-     * <p> This method invokes the {@link #implOnUnmappableCharacter
-     * implOnUnmappableCharacter} method, passing the new action.  </p>
-     *
-     * @param  newAction  The new action; must not be <tt>null</tt>
-     *
-     * @return  This $coder$
-     *
-     * @throws IllegalArgumentException
-     *         If the precondition on the parameter does not hold
-     */
-    public final Charset$Coder$ onUnmappableCharacter(CodingErrorAction
-                                                      newAction)
-    {
-        if (newAction == null)
-            throw new IllegalArgumentException("Null action");
-        unmappableCharacterAction = newAction;
-        implOnUnmappableCharacter(newAction);
-        return this;
-    }
-
-    /**
-     * Reports a change to this $coder$'s unmappable-character action.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that require notification of changes to
-     * the unmappable-character action.  </p>
-     */
-    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
-
-    /**
-     * Returns the average number of $otype$s that will be produced for each
-     * $itype$ of input.  This heuristic value may be used to estimate the size
-     * of the output buffer required for a given input sequence. </p>
-     *
-     * @return  The average number of $otype$s produced
-     *          per $itype$ of input
-     */
-    public final float average$ItypesPerOtype$() {
-        return average$ItypesPerOtype$;
-    }
-
-    /**
-     * Returns the maximum number of $otype$s that will be produced for each
-     * $itype$ of input.  This value may be used to compute the worst-case size
-     * of the output buffer required for a given input sequence. </p>
-     *
-     * @return  The maximum number of $otype$s that will be produced per
-     *          $itype$ of input
-     */
-    public final float max$ItypesPerOtype$() {
-        return max$ItypesPerOtype$;
-    }
-
-    /**
-     * $Code$s as many $itype$s as possible from the given input buffer,
-     * writing the results to the given output buffer.
-     *
-     * <p> The buffers are read from, and written to, starting at their current
-     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
-     * will be read and at most {@link Buffer#remaining out.remaining()}
-     * $otype$s will be written.  The buffers' positions will be advanced to
-     * reflect the $itype$s read and the $otype$s written, but their marks and
-     * limits will not be modified.
-     *
-     * <p> In addition to reading $itype$s from the input buffer and writing
-     * $otype$s to the output buffer, this method returns a {@link CoderResult}
-     * object to describe its reason for termination:
-     *
-     * <ul>
-     *
-     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
-     *   input buffer as possible has been $code$d.  If there is no further
-     *   input then the invoker can proceed to the next step of the
-     *   <a href="#steps">$coding$ operation</a>.  Otherwise this method
-     *   should be invoked again with further input.  </p></li>
-     *
-     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
-     *   insufficient space in the output buffer to $code$ any more $itype$s.
-     *   This method should be invoked again with an output buffer that has
-     *   more {@linkplain Buffer#remaining remaining} $otype$s. This is
-     *   typically done by draining any $code$d $otype$s from the output
-     *   buffer.  </p></li>
-     *
-     *   <li><p> A {@link CoderResult#malformedForLength
-     *   </code>malformed-input<code>} result indicates that a malformed-input
-     *   error has been detected.  The malformed $itype$s begin at the input
-     *   buffer's (possibly incremented) position; the number of malformed
-     *   $itype$s may be determined by invoking the result object's {@link
-     *   CoderResult#length() length} method.  This case applies only if the
-     *   {@link #onMalformedInput </code>malformed action<code>} of this $coder$
-     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
-     *   will be ignored or replaced, as requested.  </p></li>
-     *
-     *   <li><p> An {@link CoderResult#unmappableForLength
-     *   </code>unmappable-character<code>} result indicates that an
-     *   unmappable-character error has been detected.  The $itype$s that
-     *   $code$ the unmappable character begin at the input buffer's (possibly
-     *   incremented) position; the number of such $itype$s may be determined
-     *   by invoking the result object's {@link CoderResult#length() length}
-     *   method.  This case applies only if the {@link #onUnmappableCharacter
-     *   </code>unmappable action<code>} of this $coder$ is {@link
-     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
-     *   ignored or replaced, as requested.  </p></li>
-     *
-     * </ul>
-     *
-     * In any case, if this method is to be reinvoked in the same $coding$
-     * operation then care should be taken to preserve any $itype$s remaining
-     * in the input buffer so that they are available to the next invocation.
-     *
-     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
-     * the invoker can provide further input beyond that contained in the given
-     * input buffer.  If there is a possibility of providing additional input
-     * then the invoker should pass <tt>false</tt> for this parameter; if there
-     * is no possibility of providing further input then the invoker should
-     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
-     * common, to pass <tt>false</tt> in one invocation and later discover that
-     * no further input was actually available.  It is critical, however, that
-     * the final invocation of this method in a sequence of invocations always
-     * pass <tt>true</tt> so that any remaining un$code$d input will be treated
-     * as being malformed.
-     *
-     * <p> This method works by invoking the {@link #$code$Loop $code$Loop}
-     * method, interpreting its results, handling error conditions, and
-     * reinvoking it as necessary.  </p>
-     *
-     *
-     * @param  in
-     *         The input $itype$ buffer
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @param  endOfInput
-     *         <tt>true</tt> if, and only if, the invoker can provide no
-     *         additional input $itype$s beyond those in the given buffer
-     *
-     * @return  A coder-result object describing the reason for termination
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress and the previous
-     *          step was an invocation neither of the {@link #reset reset}
-     *          method, nor of this method with a value of <tt>false</tt> for
-     *          the <tt>endOfInput</tt> parameter, nor of this method with a
-     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
-     *          but a return value indicating an incomplete $coding$ operation
-     *
-     * @throws  CoderMalfunctionError
-     *          If an invocation of the $code$Loop method threw
-     *          an unexpected exception
-     */
-    public final CoderResult $code$($Itype$Buffer in, $Otype$Buffer out,
-                                    boolean endOfInput)
-    {
-        int newState = endOfInput ? ST_END : ST_CODING;
-        if ((state != ST_RESET) && (state != ST_CODING)
-            && !(endOfInput && (state == ST_END)))
-            throwIllegalStateException(state, newState);
-        state = newState;
-
-        for (;;) {
-
-            CoderResult cr;
-            try {
-                cr = $code$Loop(in, out);
-            } catch (BufferUnderflowException x) {
-                throw new CoderMalfunctionError(x);
-            } catch (BufferOverflowException x) {
-                throw new CoderMalfunctionError(x);
-            }
-
-            if (cr.isOverflow())
-                return cr;
-
-            if (cr.isUnderflow()) {
-                if (endOfInput && in.hasRemaining()) {
-                    cr = CoderResult.malformedForLength(in.remaining());
-                    // Fall through to malformed-input case
-                } else {
-                    return cr;
-                }
-            }
-
-            CodingErrorAction action = null;
-            if (cr.isMalformed())
-                action = malformedInputAction;
-            else if (cr.isUnmappable())
-                action = unmappableCharacterAction;
-            else
-                assert false : cr.toString();
-
-            if (action == CodingErrorAction.REPORT)
-                return cr;
-
-            if (action == CodingErrorAction.REPLACE) {
-                if (out.remaining() < replacement.$replLength$)
-                    return CoderResult.OVERFLOW;
-                out.put(replacement);
-            }
-
-            if ((action == CodingErrorAction.IGNORE)
-                || (action == CodingErrorAction.REPLACE)) {
-                // Skip erroneous input either way
-                in.position(in.position() + cr.length());
-                continue;
-            }
-
-            assert false;
-        }
-
-    }
-
-    /**
-     * Flushes this $coder$.
-     *
-     * <p> Some $coder$s maintain internal state and may need to write some
-     * final $otype$s to the output buffer once the overall input sequence has
-     * been read.
-     *
-     * <p> Any additional output is written to the output buffer beginning at
-     * its current position.  At most {@link Buffer#remaining out.remaining()}
-     * $otype$s will be written.  The buffer's position will be advanced
-     * appropriately, but its mark and limit will not be modified.
-     *
-     * <p> If this method completes successfully then it returns {@link
-     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
-     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
-     * then this method must be invoked again, with an output buffer that has
-     * more room, in order to complete the current <a href="#steps">$coding$
-     * operation</a>.
-     *
-     * <p> If this $coder$ has already been flushed then invoking this method
-     * has no effect.
-     *
-     * <p> This method invokes the {@link #implFlush implFlush} method to
-     * perform the actual flushing operation.  </p>
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
-     *          {@link CoderResult#OVERFLOW}
-     *
-     * @throws  IllegalStateException
-     *          If the previous step of the current $coding$ operation was an
-     *          invocation neither of the {@link #flush flush} method nor of
-     *          the three-argument {@link
-     *          #$code$($Itype$Buffer,$Otype$Buffer,boolean) $code$} method
-     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
-     *          parameter
-     */
-    public final CoderResult flush($Otype$Buffer out) {
-        if (state == ST_END) {
-            CoderResult cr = implFlush(out);
-            if (cr.isUnderflow())
-                state = ST_FLUSHED;
-            return cr;
-        }
-
-        if (state != ST_FLUSHED)
-            throwIllegalStateException(state, ST_FLUSHED);
-
-        return CoderResult.UNDERFLOW; // Already flushed
-    }
-
-    /**
-     * Flushes this $coder$.
-     *
-     * <p> The default implementation of this method does nothing, and always
-     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
-     * by $coder$s that may need to write final $otype$s to the output buffer
-     * once the entire input sequence has been read. </p>
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
-     *          {@link CoderResult#OVERFLOW}
-     */
-    protected CoderResult implFlush($Otype$Buffer out) {
-        return CoderResult.UNDERFLOW;
-    }
-
-    /**
-     * Resets this $coder$, clearing any internal state.
-     *
-     * <p> This method resets charset-independent state and also invokes the
-     * {@link #implReset() implReset} method in order to perform any
-     * charset-specific reset actions.  </p>
-     *
-     * @return  This $coder$
-     *
-     */
-    public final Charset$Coder$ reset() {
-        implReset();
-        state = ST_RESET;
-        return this;
-    }
-
-    /**
-     * Resets this $coder$, clearing any charset-specific internal state.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that maintain internal state.  </p>
-     */
-    protected void implReset() { }
-
-    /**
-     * $Code$s one or more $itype$s into one or more $otype$s.
-     *
-     * <p> This method encapsulates the basic $coding$ loop, $coding$ as many
-     * $itype$s as possible until it either runs out of input, runs out of room
-     * in the output buffer, or encounters $a$ $coding$ error.  This method is
-     * invoked by the {@link #$code$ $code$} method, which handles result
-     * interpretation and error recovery.
-     *
-     * <p> The buffers are read from, and written to, starting at their current
-     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
-     * will be read, and at most {@link Buffer#remaining out.remaining()}
-     * $otype$s will be written.  The buffers' positions will be advanced to
-     * reflect the $itype$s read and the $otype$s written, but their marks and
-     * limits will not be modified.
-     *
-     * <p> This method returns a {@link CoderResult} object to describe its
-     * reason for termination, in the same manner as the {@link #$code$ $code$}
-     * method.  Most implementations of this method will handle $coding$ errors
-     * by returning an appropriate result object for interpretation by the
-     * {@link #$code$ $code$} method.  An optimized implementation may instead
-     * examine the relevant error action and implement that action itself.
-     *
-     * <p> An implementation of this method may perform arbitrary lookahead by
-     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
-     * input.  </p>
-     *
-     * @param  in
-     *         The input $itype$ buffer
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @return  A coder-result object describing the reason for termination
-     */
-    protected abstract CoderResult $code$Loop($Itype$Buffer in,
-                                              $Otype$Buffer out);
-
-    /**
-     * Convenience method that $code$s the remaining content of a single input
-     * $itype$ buffer into a newly-allocated $otype$ buffer.
-     *
-     * <p> This method implements an entire <a href="#steps">$coding$
-     * operation</a>; that is, it resets this $coder$, then it $code$s the
-     * $itype$s in the given $itype$ buffer, and finally it flushes this
-     * $coder$.  This method should therefore not be invoked if $a$ $coding$
-     * operation is already in progress.  </p>
-     *
-     * @param  in
-     *         The input $itype$ buffer
-     *
-     * @return A newly-allocated $otype$ buffer containing the result of the
-     *         $coding$ operation.  The buffer's position will be zero and its
-     *         limit will follow the last $otype$ written.
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress
-     *
-     * @throws  MalformedInputException
-     *          If the $itype$ sequence starting at the input buffer's current
-     *          position is $notLegal$ and the current malformed-input action
-     *          is {@link CodingErrorAction#REPORT}
-     *
-     * @throws  UnmappableCharacterException
-     *          If the $itype$ sequence starting at the input buffer's current
-     *          position cannot be mapped to an equivalent $otype$ sequence and
-     *          the current unmappable-character action is {@link
-     *          CodingErrorAction#REPORT}
-     */
-    public final $Otype$Buffer $code$($Itype$Buffer in)
-        throws CharacterCodingException
-    {
-        int n = (int)(in.remaining() * average$ItypesPerOtype$());
-        $Otype$Buffer out = $Otype$Buffer.allocate(n);
-
-        if ((n == 0) && (in.remaining() == 0))
-            return out;
-        reset();
-        for (;;) {
-            CoderResult cr = in.hasRemaining() ?
-                $code$(in, out, true) : CoderResult.UNDERFLOW;
-            if (cr.isUnderflow())
-                cr = flush(out);
-
-            if (cr.isUnderflow())
-                break;
-            if (cr.isOverflow()) {
-                n = 2*n + 1;    // Ensure progress; n might be 0!
-                $Otype$Buffer o = $Otype$Buffer.allocate(n);
-                out.flip();
-                o.put(out);
-                out = o;
-                continue;
-            }
-            cr.throwException();
-        }
-        out.flip();
-        return out;
-    }
-
-#if[decoder]
-
-    /**
-     * Tells whether or not this decoder implements an auto-detecting charset.
-     *
-     * <p> The default implementation of this method always returns
-     * <tt>false</tt>; it should be overridden by auto-detecting decoders to
-     * return <tt>true</tt>.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this decoder implements an
-     *          auto-detecting charset
-     */
-    public boolean isAutoDetecting() {
-        return false;
-    }
-
-    /**
-     * Tells whether or not this decoder has yet detected a
-     * charset&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> If this decoder implements an auto-detecting charset then at a
-     * single point during a decoding operation this method may start returning
-     * <tt>true</tt> to indicate that a specific charset has been detected in
-     * the input byte sequence.  Once this occurs, the {@link #detectedCharset
-     * detectedCharset} method may be invoked to retrieve the detected charset.
-     *
-     * <p> That this method returns <tt>false</tt> does not imply that no bytes
-     * have yet been decoded.  Some auto-detecting decoders are capable of
-     * decoding some, or even all, of an input byte sequence without fixing on
-     * a particular charset.
-     *
-     * <p> The default implementation of this method always throws an {@link
-     * UnsupportedOperationException}; it should be overridden by
-     * auto-detecting decoders to return <tt>true</tt> once the input charset
-     * has been determined.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this decoder has detected a
-     *          specific charset
-     *
-     * @throws  UnsupportedOperationException
-     *          If this decoder does not implement an auto-detecting charset
-     */
-    public boolean isCharsetDetected() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Retrieves the charset that was detected by this
-     * decoder&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> If this decoder implements an auto-detecting charset then this
-     * method returns the actual charset once it has been detected.  After that
-     * point, this method returns the same value for the duration of the
-     * current decoding operation.  If not enough input bytes have yet been
-     * read to determine the actual charset then this method throws an {@link
-     * IllegalStateException}.
-     *
-     * <p> The default implementation of this method always throws an {@link
-     * UnsupportedOperationException}; it should be overridden by
-     * auto-detecting decoders to return the appropriate value.  </p>
-     *
-     * @return  The charset detected by this auto-detecting decoder,
-     *          or <tt>null</tt> if the charset has not yet been determined
-     *
-     * @throws  IllegalStateException
-     *          If insufficient bytes have been read to determine a charset
-     *
-     * @throws  UnsupportedOperationException
-     *          If this decoder does not implement an auto-detecting charset
-     */
-    public Charset detectedCharset() {
-        throw new UnsupportedOperationException();
-    }
-
-#end[decoder]
-
-#if[encoder]
-
-    private boolean canEncode(CharBuffer cb) {
-        if (state == ST_FLUSHED)
-            reset();
-        else if (state != ST_RESET)
-            throwIllegalStateException(state, ST_CODING);
-        CodingErrorAction ma = malformedInputAction();
-        CodingErrorAction ua = unmappableCharacterAction();
-        try {
-            onMalformedInput(CodingErrorAction.REPORT);
-            onUnmappableCharacter(CodingErrorAction.REPORT);
-            encode(cb);
-        } catch (CharacterCodingException x) {
-            return false;
-        } finally {
-            onMalformedInput(ma);
-            onUnmappableCharacter(ua);
-            reset();
-        }
-        return true;
-    }
-
-    /**
-     * Tells whether or not this encoder can encode the given character.
-     *
-     * <p> This method returns <tt>false</tt> if the given character is a
-     * surrogate character; such characters can be interpreted only when they
-     * are members of a pair consisting of a high surrogate followed by a low
-     * surrogate.  The {@link #canEncode(java.lang.CharSequence)
-     * canEncode(CharSequence)} method may be used to test whether or not a
-     * character sequence can be encoded.
-     *
-     * <p> This method may modify this encoder's state; it should therefore not
-     * be invoked if an <a href="#steps">encoding operation</a> is already in
-     * progress.
-     *
-     * <p> The default implementation of this method is not very efficient; it
-     * should generally be overridden to improve performance.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this encoder can encode
-     *          the given character
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress
-     */
-    public boolean canEncode(char c) {
-        CharBuffer cb = CharBuffer.allocate(1);
-        cb.put(c);
-        cb.flip();
-        return canEncode(cb);
-    }
-
-    /**
-     * Tells whether or not this encoder can encode the given character
-     * sequence.
-     *
-     * <p> If this method returns <tt>false</tt> for a particular character
-     * sequence then more information about why the sequence cannot be encoded
-     * may be obtained by performing a full <a href="#steps">encoding
-     * operation</a>.
-     *
-     * <p> This method may modify this encoder's state; it should therefore not
-     * be invoked if an encoding operation is already in progress.
-     *
-     * <p> The default implementation of this method is not very efficient; it
-     * should generally be overridden to improve performance.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this encoder can encode
-     *          the given character without throwing any exceptions and without
-     *          performing any replacements
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress
-     */
-    public boolean canEncode(CharSequence cs) {
-        CharBuffer cb;
-        if (cs instanceof CharBuffer)
-            cb = ((CharBuffer)cs).duplicate();
-        else
-            cb = CharBuffer.wrap(cs.toString());
-        return canEncode(cb);
-    }
-
-#end[encoder]
-
-
-    private void throwIllegalStateException(int from, int to) {
-        throw new IllegalStateException("Current state = " + stateNames[from]
-                                        + ", new state = " + stateNames[to]);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/charset/Charset-X-Coder.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,972 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio.charset;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.lang.ref.WeakReference;
+import java.nio.charset.CoderMalfunctionError;                  // javadoc
+
+
+/**
+ * An engine that can transform a sequence of $itypesPhrase$ into a sequence of
+ * $otypesPhrase$.
+ *
+ * <a name="steps">
+ *
+ * <p> The input $itype$ sequence is provided in a $itype$ buffer or a series
+ * of such buffers.  The output $otype$ sequence is written to a $otype$ buffer
+ * or a series of such buffers.  $A$ $coder$ should always be used by making
+ * the following sequence of method invocations, hereinafter referred to as $a$
+ * <i>$coding$ operation</i>:
+ *
+ * <ol>
+ *
+ *   <li><p> Reset the $coder$ via the {@link #reset reset} method, unless it
+ *   has not been used before; </p></li>
+ *
+ *   <li><p> Invoke the {@link #$code$ $code$} method zero or more times, as
+ *   long as additional input may be available, passing <tt>false</tt> for the
+ *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
+ *   output buffer between invocations; </p></li>
+ *
+ *   <li><p> Invoke the {@link #$code$ $code$} method one final time, passing
+ *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
+ *
+ *   <li><p> Invoke the {@link #flush flush} method so that the $coder$ can
+ *   flush any internal state to the output buffer. </p></li>
+ *
+ * </ol>
+ *
+ * Each invocation of the {@link #$code$ $code$} method will $code$ as many
+ * $itype$s as possible from the input buffer, writing the resulting $otype$s
+ * to the output buffer.  The {@link #$code$ $code$} method returns when more
+ * input is required, when there is not enough room in the output buffer, or
+ * when $a$ $coding$ error has occurred.  In each case a {@link CoderResult}
+ * object is returned to describe the reason for termination.  An invoker can
+ * examine this object and fill the input buffer, flush the output buffer, or
+ * attempt to recover from $a$ $coding$ error, as appropriate, and try again.
+ *
+ * <a name="ce">
+ *
+ * <p> There are two general types of $coding$ errors.  If the input $itype$
+ * sequence is $notLegal$ then the input is considered <i>malformed</i>.  If
+ * the input $itype$ sequence is legal but cannot be mapped to a valid
+ * $outSequence$ then an <i>unmappable character</i> has been encountered.
+ *
+ * <a name="cae">
+ *
+ * <p> How $a$ $coding$ error is handled depends upon the action requested for
+ * that type of error, which is described by an instance of the {@link
+ * CodingErrorAction} class.  The possible error actions are to {@link
+ * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
+ * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
+ * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
+ * </code>replace<code>} the erroneous input with the current value of the
+ * replacement $replTypeName$.  The replacement
+ *
+#if[encoder]
+ * is initially set to the $coder$'s default replacement, which often
+ * (but not always) has the initial value&nbsp;$defaultReplName$;
+#end[encoder]
+#if[decoder]
+ * has the initial value $defaultReplName$;
+#end[decoder]
+ *
+ * its value may be changed via the {@link #replaceWith($replFQType$)
+ * replaceWith} method.
+ *
+ * <p> The default action for malformed-input and unmappable-character errors
+ * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
+ * malformed-input error action may be changed via the {@link
+ * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
+ * unmappable-character action may be changed via the {@link
+ * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
+ *
+ * <p> This class is designed to handle many of the details of the $coding$
+ * process, including the implementation of error actions.  $A$ $coder$ for a
+ * specific charset, which is a concrete subclass of this class, need only
+ * implement the abstract {@link #$code$Loop $code$Loop} method, which
+ * encapsulates the basic $coding$ loop.  A subclass that maintains internal
+ * state should, additionally, override the {@link #implFlush implFlush} and
+ * {@link #implReset implReset} methods.
+ *
+ * <p> Instances of this class are not safe for use by multiple concurrent
+ * threads.  </p>
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ *
+ * @see ByteBuffer
+ * @see CharBuffer
+ * @see Charset
+ * @see Charset$OtherCoder$
+ */
+
+public abstract class Charset$Coder$ {
+
+    private final Charset charset;
+    private final float average$ItypesPerOtype$;
+    private final float max$ItypesPerOtype$;
+
+    private $replType$ replacement;
+    private CodingErrorAction malformedInputAction
+        = CodingErrorAction.REPORT;
+    private CodingErrorAction unmappableCharacterAction
+        = CodingErrorAction.REPORT;
+
+    // Internal states
+    //
+    private static final int ST_RESET   = 0;
+    private static final int ST_CODING  = 1;
+    private static final int ST_END     = 2;
+    private static final int ST_FLUSHED = 3;
+
+    private int state = ST_RESET;
+
+    private static String stateNames[]
+        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
+
+
+    /**
+     * Initializes a new $coder$.  The new $coder$ will have the given
+     * $otypes-per-itype$ and replacement values. </p>
+     *
+     * @param  average$ItypesPerOtype$
+     *         A positive float value indicating the expected number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @param  max$ItypesPerOtype$
+     *         A positive float value indicating the maximum number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @param  replacement
+     *         The initial replacement; must not be <tt>null</tt>, must have
+     *         non-zero length, must not be longer than max$ItypesPerOtype$,
+     *         and must be {@link #isLegalReplacement </code>legal<code>}
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     */
+    {#if[encoder]?protected:private}
+    Charset$Coder$(Charset cs,
+                   float average$ItypesPerOtype$,
+                   float max$ItypesPerOtype$,
+                   $replType$ replacement)
+    {
+        this.charset = cs;
+        if (average$ItypesPerOtype$ <= 0.0f)
+            throw new IllegalArgumentException("Non-positive "
+                                               + "average$ItypesPerOtype$");
+        if (max$ItypesPerOtype$ <= 0.0f)
+            throw new IllegalArgumentException("Non-positive "
+                                               + "max$ItypesPerOtype$");
+        if (!Charset.atBugLevel("1.4")) {
+            if (average$ItypesPerOtype$ > max$ItypesPerOtype$)
+                throw new IllegalArgumentException("average$ItypesPerOtype$"
+                                                   + " exceeds "
+                                                   + "max$ItypesPerOtype$");
+        }
+        this.replacement = replacement;
+        this.average$ItypesPerOtype$ = average$ItypesPerOtype$;
+        this.max$ItypesPerOtype$ = max$ItypesPerOtype$;
+        replaceWith(replacement);
+    }
+
+    /**
+     * Initializes a new $coder$.  The new $coder$ will have the given
+     * $otypes-per-itype$ values and its replacement will be the
+     * $replTypeName$ $defaultReplName$. </p>
+     *
+     * @param  average$ItypesPerOtype$
+     *         A positive float value indicating the expected number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @param  max$ItypesPerOtype$
+     *         A positive float value indicating the maximum number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     */
+    protected Charset$Coder$(Charset cs,
+                             float average$ItypesPerOtype$,
+                             float max$ItypesPerOtype$)
+    {
+        this(cs,
+             average$ItypesPerOtype$, max$ItypesPerOtype$,
+             $defaultRepl$);
+    }
+
+    /**
+     * Returns the charset that created this $coder$.  </p>
+     *
+     * @return  This $coder$'s charset
+     */
+    public final Charset charset() {
+        return charset;
+    }
+
+    /**
+     * Returns this $coder$'s replacement value. </p>
+     *
+     * @return  This $coder$'s current replacement,
+     *          which is never <tt>null</tt> and is never empty
+     */
+    public final $replType$ replacement() {
+        return replacement;
+    }
+
+    /**
+     * Changes this $coder$'s replacement value.
+     *
+     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
+     * method, passing the new replacement, after checking that the new
+     * replacement is acceptable.  </p>
+     *
+     * @param  newReplacement
+     *
+#if[decoder]
+     *         The new replacement; must not be <tt>null</tt>
+     *         and must have non-zero length
+#end[decoder]
+#if[encoder]
+     *         The new replacement; must not be <tt>null</tt>, must have
+     *         non-zero length, must not be longer than the value returned by
+     *         the {@link #max$ItypesPerOtype$() max$ItypesPerOtype$} method, and
+     *         must be {@link #isLegalReplacement </code>legal<code>}
+#end[encoder]
+     *
+     * @return  This $coder$
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameter do not hold
+     */
+    public final Charset$Coder$ replaceWith($replType$ newReplacement) {
+        if (newReplacement == null)
+            throw new IllegalArgumentException("Null replacement");
+        int len = newReplacement.$replLength$;
+        if (len == 0)
+            throw new IllegalArgumentException("Empty replacement");
+        if (len > max$ItypesPerOtype$)
+            throw new IllegalArgumentException("Replacement too long");
+#if[encoder]
+        if (!isLegalReplacement(newReplacement))
+            throw new IllegalArgumentException("Illegal replacement");
+#end[encoder]
+        this.replacement = newReplacement;
+        implReplaceWith(newReplacement);
+        return this;
+    }
+
+    /**
+     * Reports a change to this $coder$'s replacement value.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that require notification of changes to
+     * the replacement.  </p>
+     *
+     * @param  newReplacement
+     */
+    protected void implReplaceWith($replType$ newReplacement) {
+    }
+
+#if[encoder]
+
+    private WeakReference<CharsetDecoder> cachedDecoder = null;
+
+    /**
+     * Tells whether or not the given byte array is a legal replacement value
+     * for this encoder.
+     *
+     * <p> A replacement is legal if, and only if, it is a legal sequence of
+     * bytes in this encoder's charset; that is, it must be possible to decode
+     * the replacement into one or more sixteen-bit Unicode characters.
+     *
+     * <p> The default implementation of this method is not very efficient; it
+     * should generally be overridden to improve performance.  </p>
+     *
+     * @param  repl  The byte array to be tested
+     *
+     * @return  <tt>true</tt> if, and only if, the given byte array
+     *          is a legal replacement value for this encoder
+     */
+    public boolean isLegalReplacement(byte[] repl) {
+        WeakReference<CharsetDecoder> wr = cachedDecoder;
+        CharsetDecoder dec = null;
+        if ((wr == null) || ((dec = wr.get()) == null)) {
+            dec = charset().newDecoder();
+            dec.onMalformedInput(CodingErrorAction.REPORT);
+            dec.onUnmappableCharacter(CodingErrorAction.REPORT);
+            cachedDecoder = new WeakReference<CharsetDecoder>(dec);
+        } else {
+            dec.reset();
+        }
+        ByteBuffer bb = ByteBuffer.wrap(repl);
+        CharBuffer cb = CharBuffer.allocate((int)(bb.remaining()
+                                                  * dec.maxCharsPerByte()));
+        CoderResult cr = dec.decode(bb, cb, true);
+        return !cr.isError();
+    }
+
+#end[encoder]
+
+    /**
+     * Returns this $coder$'s current action for malformed-input errors.  </p>
+     *
+     * @return The current malformed-input action, which is never <tt>null</tt>
+     */
+    public CodingErrorAction malformedInputAction() {
+        return malformedInputAction;
+    }
+
+    /**
+     * Changes this $coder$'s action for malformed-input errors.  </p>
+     *
+     * <p> This method invokes the {@link #implOnMalformedInput
+     * implOnMalformedInput} method, passing the new action.  </p>
+     *
+     * @param  newAction  The new action; must not be <tt>null</tt>
+     *
+     * @return  This $coder$
+     *
+     * @throws IllegalArgumentException
+     *         If the precondition on the parameter does not hold
+     */
+    public final Charset$Coder$ onMalformedInput(CodingErrorAction newAction) {
+        if (newAction == null)
+            throw new IllegalArgumentException("Null action");
+        malformedInputAction = newAction;
+        implOnMalformedInput(newAction);
+        return this;
+    }
+
+    /**
+     * Reports a change to this $coder$'s malformed-input action.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that require notification of changes to
+     * the malformed-input action.  </p>
+     */
+    protected void implOnMalformedInput(CodingErrorAction newAction) { }
+
+    /**
+     * Returns this $coder$'s current action for unmappable-character errors.
+     * </p>
+     *
+     * @return The current unmappable-character action, which is never
+     *         <tt>null</tt>
+     */
+    public CodingErrorAction unmappableCharacterAction() {
+        return unmappableCharacterAction;
+    }
+
+    /**
+     * Changes this $coder$'s action for unmappable-character errors.
+     *
+     * <p> This method invokes the {@link #implOnUnmappableCharacter
+     * implOnUnmappableCharacter} method, passing the new action.  </p>
+     *
+     * @param  newAction  The new action; must not be <tt>null</tt>
+     *
+     * @return  This $coder$
+     *
+     * @throws IllegalArgumentException
+     *         If the precondition on the parameter does not hold
+     */
+    public final Charset$Coder$ onUnmappableCharacter(CodingErrorAction
+                                                      newAction)
+    {
+        if (newAction == null)
+            throw new IllegalArgumentException("Null action");
+        unmappableCharacterAction = newAction;
+        implOnUnmappableCharacter(newAction);
+        return this;
+    }
+
+    /**
+     * Reports a change to this $coder$'s unmappable-character action.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that require notification of changes to
+     * the unmappable-character action.  </p>
+     */
+    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
+
+    /**
+     * Returns the average number of $otype$s that will be produced for each
+     * $itype$ of input.  This heuristic value may be used to estimate the size
+     * of the output buffer required for a given input sequence. </p>
+     *
+     * @return  The average number of $otype$s produced
+     *          per $itype$ of input
+     */
+    public final float average$ItypesPerOtype$() {
+        return average$ItypesPerOtype$;
+    }
+
+    /**
+     * Returns the maximum number of $otype$s that will be produced for each
+     * $itype$ of input.  This value may be used to compute the worst-case size
+     * of the output buffer required for a given input sequence. </p>
+     *
+     * @return  The maximum number of $otype$s that will be produced per
+     *          $itype$ of input
+     */
+    public final float max$ItypesPerOtype$() {
+        return max$ItypesPerOtype$;
+    }
+
+    /**
+     * $Code$s as many $itype$s as possible from the given input buffer,
+     * writing the results to the given output buffer.
+     *
+     * <p> The buffers are read from, and written to, starting at their current
+     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
+     * will be read and at most {@link Buffer#remaining out.remaining()}
+     * $otype$s will be written.  The buffers' positions will be advanced to
+     * reflect the $itype$s read and the $otype$s written, but their marks and
+     * limits will not be modified.
+     *
+     * <p> In addition to reading $itype$s from the input buffer and writing
+     * $otype$s to the output buffer, this method returns a {@link CoderResult}
+     * object to describe its reason for termination:
+     *
+     * <ul>
+     *
+     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
+     *   input buffer as possible has been $code$d.  If there is no further
+     *   input then the invoker can proceed to the next step of the
+     *   <a href="#steps">$coding$ operation</a>.  Otherwise this method
+     *   should be invoked again with further input.  </p></li>
+     *
+     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
+     *   insufficient space in the output buffer to $code$ any more $itype$s.
+     *   This method should be invoked again with an output buffer that has
+     *   more {@linkplain Buffer#remaining remaining} $otype$s. This is
+     *   typically done by draining any $code$d $otype$s from the output
+     *   buffer.  </p></li>
+     *
+     *   <li><p> A {@link CoderResult#malformedForLength
+     *   </code>malformed-input<code>} result indicates that a malformed-input
+     *   error has been detected.  The malformed $itype$s begin at the input
+     *   buffer's (possibly incremented) position; the number of malformed
+     *   $itype$s may be determined by invoking the result object's {@link
+     *   CoderResult#length() length} method.  This case applies only if the
+     *   {@link #onMalformedInput </code>malformed action<code>} of this $coder$
+     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
+     *   will be ignored or replaced, as requested.  </p></li>
+     *
+     *   <li><p> An {@link CoderResult#unmappableForLength
+     *   </code>unmappable-character<code>} result indicates that an
+     *   unmappable-character error has been detected.  The $itype$s that
+     *   $code$ the unmappable character begin at the input buffer's (possibly
+     *   incremented) position; the number of such $itype$s may be determined
+     *   by invoking the result object's {@link CoderResult#length() length}
+     *   method.  This case applies only if the {@link #onUnmappableCharacter
+     *   </code>unmappable action<code>} of this $coder$ is {@link
+     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
+     *   ignored or replaced, as requested.  </p></li>
+     *
+     * </ul>
+     *
+     * In any case, if this method is to be reinvoked in the same $coding$
+     * operation then care should be taken to preserve any $itype$s remaining
+     * in the input buffer so that they are available to the next invocation.
+     *
+     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
+     * the invoker can provide further input beyond that contained in the given
+     * input buffer.  If there is a possibility of providing additional input
+     * then the invoker should pass <tt>false</tt> for this parameter; if there
+     * is no possibility of providing further input then the invoker should
+     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
+     * common, to pass <tt>false</tt> in one invocation and later discover that
+     * no further input was actually available.  It is critical, however, that
+     * the final invocation of this method in a sequence of invocations always
+     * pass <tt>true</tt> so that any remaining un$code$d input will be treated
+     * as being malformed.
+     *
+     * <p> This method works by invoking the {@link #$code$Loop $code$Loop}
+     * method, interpreting its results, handling error conditions, and
+     * reinvoking it as necessary.  </p>
+     *
+     *
+     * @param  in
+     *         The input $itype$ buffer
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @param  endOfInput
+     *         <tt>true</tt> if, and only if, the invoker can provide no
+     *         additional input $itype$s beyond those in the given buffer
+     *
+     * @return  A coder-result object describing the reason for termination
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress and the previous
+     *          step was an invocation neither of the {@link #reset reset}
+     *          method, nor of this method with a value of <tt>false</tt> for
+     *          the <tt>endOfInput</tt> parameter, nor of this method with a
+     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
+     *          but a return value indicating an incomplete $coding$ operation
+     *
+     * @throws  CoderMalfunctionError
+     *          If an invocation of the $code$Loop method threw
+     *          an unexpected exception
+     */
+    public final CoderResult $code$($Itype$Buffer in, $Otype$Buffer out,
+                                    boolean endOfInput)
+    {
+        int newState = endOfInput ? ST_END : ST_CODING;
+        if ((state != ST_RESET) && (state != ST_CODING)
+            && !(endOfInput && (state == ST_END)))
+            throwIllegalStateException(state, newState);
+        state = newState;
+
+        for (;;) {
+
+            CoderResult cr;
+            try {
+                cr = $code$Loop(in, out);
+            } catch (BufferUnderflowException x) {
+                throw new CoderMalfunctionError(x);
+            } catch (BufferOverflowException x) {
+                throw new CoderMalfunctionError(x);
+            }
+
+            if (cr.isOverflow())
+                return cr;
+
+            if (cr.isUnderflow()) {
+                if (endOfInput && in.hasRemaining()) {
+                    cr = CoderResult.malformedForLength(in.remaining());
+                    // Fall through to malformed-input case
+                } else {
+                    return cr;
+                }
+            }
+
+            CodingErrorAction action = null;
+            if (cr.isMalformed())
+                action = malformedInputAction;
+            else if (cr.isUnmappable())
+                action = unmappableCharacterAction;
+            else
+                assert false : cr.toString();
+
+            if (action == CodingErrorAction.REPORT)
+                return cr;
+
+            if (action == CodingErrorAction.REPLACE) {
+                if (out.remaining() < replacement.$replLength$)
+                    return CoderResult.OVERFLOW;
+                out.put(replacement);
+            }
+
+            if ((action == CodingErrorAction.IGNORE)
+                || (action == CodingErrorAction.REPLACE)) {
+                // Skip erroneous input either way
+                in.position(in.position() + cr.length());
+                continue;
+            }
+
+            assert false;
+        }
+
+    }
+
+    /**
+     * Flushes this $coder$.
+     *
+     * <p> Some $coder$s maintain internal state and may need to write some
+     * final $otype$s to the output buffer once the overall input sequence has
+     * been read.
+     *
+     * <p> Any additional output is written to the output buffer beginning at
+     * its current position.  At most {@link Buffer#remaining out.remaining()}
+     * $otype$s will be written.  The buffer's position will be advanced
+     * appropriately, but its mark and limit will not be modified.
+     *
+     * <p> If this method completes successfully then it returns {@link
+     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
+     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
+     * then this method must be invoked again, with an output buffer that has
+     * more room, in order to complete the current <a href="#steps">$coding$
+     * operation</a>.
+     *
+     * <p> If this $coder$ has already been flushed then invoking this method
+     * has no effect.
+     *
+     * <p> This method invokes the {@link #implFlush implFlush} method to
+     * perform the actual flushing operation.  </p>
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
+     *          {@link CoderResult#OVERFLOW}
+     *
+     * @throws  IllegalStateException
+     *          If the previous step of the current $coding$ operation was an
+     *          invocation neither of the {@link #flush flush} method nor of
+     *          the three-argument {@link
+     *          #$code$($Itype$Buffer,$Otype$Buffer,boolean) $code$} method
+     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
+     *          parameter
+     */
+    public final CoderResult flush($Otype$Buffer out) {
+        if (state == ST_END) {
+            CoderResult cr = implFlush(out);
+            if (cr.isUnderflow())
+                state = ST_FLUSHED;
+            return cr;
+        }
+
+        if (state != ST_FLUSHED)
+            throwIllegalStateException(state, ST_FLUSHED);
+
+        return CoderResult.UNDERFLOW; // Already flushed
+    }
+
+    /**
+     * Flushes this $coder$.
+     *
+     * <p> The default implementation of this method does nothing, and always
+     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
+     * by $coder$s that may need to write final $otype$s to the output buffer
+     * once the entire input sequence has been read. </p>
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
+     *          {@link CoderResult#OVERFLOW}
+     */
+    protected CoderResult implFlush($Otype$Buffer out) {
+        return CoderResult.UNDERFLOW;
+    }
+
+    /**
+     * Resets this $coder$, clearing any internal state.
+     *
+     * <p> This method resets charset-independent state and also invokes the
+     * {@link #implReset() implReset} method in order to perform any
+     * charset-specific reset actions.  </p>
+     *
+     * @return  This $coder$
+     *
+     */
+    public final Charset$Coder$ reset() {
+        implReset();
+        state = ST_RESET;
+        return this;
+    }
+
+    /**
+     * Resets this $coder$, clearing any charset-specific internal state.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that maintain internal state.  </p>
+     */
+    protected void implReset() { }
+
+    /**
+     * $Code$s one or more $itype$s into one or more $otype$s.
+     *
+     * <p> This method encapsulates the basic $coding$ loop, $coding$ as many
+     * $itype$s as possible until it either runs out of input, runs out of room
+     * in the output buffer, or encounters $a$ $coding$ error.  This method is
+     * invoked by the {@link #$code$ $code$} method, which handles result
+     * interpretation and error recovery.
+     *
+     * <p> The buffers are read from, and written to, starting at their current
+     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
+     * will be read, and at most {@link Buffer#remaining out.remaining()}
+     * $otype$s will be written.  The buffers' positions will be advanced to
+     * reflect the $itype$s read and the $otype$s written, but their marks and
+     * limits will not be modified.
+     *
+     * <p> This method returns a {@link CoderResult} object to describe its
+     * reason for termination, in the same manner as the {@link #$code$ $code$}
+     * method.  Most implementations of this method will handle $coding$ errors
+     * by returning an appropriate result object for interpretation by the
+     * {@link #$code$ $code$} method.  An optimized implementation may instead
+     * examine the relevant error action and implement that action itself.
+     *
+     * <p> An implementation of this method may perform arbitrary lookahead by
+     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
+     * input.  </p>
+     *
+     * @param  in
+     *         The input $itype$ buffer
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @return  A coder-result object describing the reason for termination
+     */
+    protected abstract CoderResult $code$Loop($Itype$Buffer in,
+                                              $Otype$Buffer out);
+
+    /**
+     * Convenience method that $code$s the remaining content of a single input
+     * $itype$ buffer into a newly-allocated $otype$ buffer.
+     *
+     * <p> This method implements an entire <a href="#steps">$coding$
+     * operation</a>; that is, it resets this $coder$, then it $code$s the
+     * $itype$s in the given $itype$ buffer, and finally it flushes this
+     * $coder$.  This method should therefore not be invoked if $a$ $coding$
+     * operation is already in progress.  </p>
+     *
+     * @param  in
+     *         The input $itype$ buffer
+     *
+     * @return A newly-allocated $otype$ buffer containing the result of the
+     *         $coding$ operation.  The buffer's position will be zero and its
+     *         limit will follow the last $otype$ written.
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress
+     *
+     * @throws  MalformedInputException
+     *          If the $itype$ sequence starting at the input buffer's current
+     *          position is $notLegal$ and the current malformed-input action
+     *          is {@link CodingErrorAction#REPORT}
+     *
+     * @throws  UnmappableCharacterException
+     *          If the $itype$ sequence starting at the input buffer's current
+     *          position cannot be mapped to an equivalent $otype$ sequence and
+     *          the current unmappable-character action is {@link
+     *          CodingErrorAction#REPORT}
+     */
+    public final $Otype$Buffer $code$($Itype$Buffer in)
+        throws CharacterCodingException
+    {
+        int n = (int)(in.remaining() * average$ItypesPerOtype$());
+        $Otype$Buffer out = $Otype$Buffer.allocate(n);
+
+        if ((n == 0) && (in.remaining() == 0))
+            return out;
+        reset();
+        for (;;) {
+            CoderResult cr = in.hasRemaining() ?
+                $code$(in, out, true) : CoderResult.UNDERFLOW;
+            if (cr.isUnderflow())
+                cr = flush(out);
+
+            if (cr.isUnderflow())
+                break;
+            if (cr.isOverflow()) {
+                n = 2*n + 1;    // Ensure progress; n might be 0!
+                $Otype$Buffer o = $Otype$Buffer.allocate(n);
+                out.flip();
+                o.put(out);
+                out = o;
+                continue;
+            }
+            cr.throwException();
+        }
+        out.flip();
+        return out;
+    }
+
+#if[decoder]
+
+    /**
+     * Tells whether or not this decoder implements an auto-detecting charset.
+     *
+     * <p> The default implementation of this method always returns
+     * <tt>false</tt>; it should be overridden by auto-detecting decoders to
+     * return <tt>true</tt>.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this decoder implements an
+     *          auto-detecting charset
+     */
+    public boolean isAutoDetecting() {
+        return false;
+    }
+
+    /**
+     * Tells whether or not this decoder has yet detected a
+     * charset&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this decoder implements an auto-detecting charset then at a
+     * single point during a decoding operation this method may start returning
+     * <tt>true</tt> to indicate that a specific charset has been detected in
+     * the input byte sequence.  Once this occurs, the {@link #detectedCharset
+     * detectedCharset} method may be invoked to retrieve the detected charset.
+     *
+     * <p> That this method returns <tt>false</tt> does not imply that no bytes
+     * have yet been decoded.  Some auto-detecting decoders are capable of
+     * decoding some, or even all, of an input byte sequence without fixing on
+     * a particular charset.
+     *
+     * <p> The default implementation of this method always throws an {@link
+     * UnsupportedOperationException}; it should be overridden by
+     * auto-detecting decoders to return <tt>true</tt> once the input charset
+     * has been determined.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this decoder has detected a
+     *          specific charset
+     *
+     * @throws  UnsupportedOperationException
+     *          If this decoder does not implement an auto-detecting charset
+     */
+    public boolean isCharsetDetected() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Retrieves the charset that was detected by this
+     * decoder&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this decoder implements an auto-detecting charset then this
+     * method returns the actual charset once it has been detected.  After that
+     * point, this method returns the same value for the duration of the
+     * current decoding operation.  If not enough input bytes have yet been
+     * read to determine the actual charset then this method throws an {@link
+     * IllegalStateException}.
+     *
+     * <p> The default implementation of this method always throws an {@link
+     * UnsupportedOperationException}; it should be overridden by
+     * auto-detecting decoders to return the appropriate value.  </p>
+     *
+     * @return  The charset detected by this auto-detecting decoder,
+     *          or <tt>null</tt> if the charset has not yet been determined
+     *
+     * @throws  IllegalStateException
+     *          If insufficient bytes have been read to determine a charset
+     *
+     * @throws  UnsupportedOperationException
+     *          If this decoder does not implement an auto-detecting charset
+     */
+    public Charset detectedCharset() {
+        throw new UnsupportedOperationException();
+    }
+
+#end[decoder]
+
+#if[encoder]
+
+    private boolean canEncode(CharBuffer cb) {
+        if (state == ST_FLUSHED)
+            reset();
+        else if (state != ST_RESET)
+            throwIllegalStateException(state, ST_CODING);
+        CodingErrorAction ma = malformedInputAction();
+        CodingErrorAction ua = unmappableCharacterAction();
+        try {
+            onMalformedInput(CodingErrorAction.REPORT);
+            onUnmappableCharacter(CodingErrorAction.REPORT);
+            encode(cb);
+        } catch (CharacterCodingException x) {
+            return false;
+        } finally {
+            onMalformedInput(ma);
+            onUnmappableCharacter(ua);
+            reset();
+        }
+        return true;
+    }
+
+    /**
+     * Tells whether or not this encoder can encode the given character.
+     *
+     * <p> This method returns <tt>false</tt> if the given character is a
+     * surrogate character; such characters can be interpreted only when they
+     * are members of a pair consisting of a high surrogate followed by a low
+     * surrogate.  The {@link #canEncode(java.lang.CharSequence)
+     * canEncode(CharSequence)} method may be used to test whether or not a
+     * character sequence can be encoded.
+     *
+     * <p> This method may modify this encoder's state; it should therefore not
+     * be invoked if an <a href="#steps">encoding operation</a> is already in
+     * progress.
+     *
+     * <p> The default implementation of this method is not very efficient; it
+     * should generally be overridden to improve performance.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this encoder can encode
+     *          the given character
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress
+     */
+    public boolean canEncode(char c) {
+        CharBuffer cb = CharBuffer.allocate(1);
+        cb.put(c);
+        cb.flip();
+        return canEncode(cb);
+    }
+
+    /**
+     * Tells whether or not this encoder can encode the given character
+     * sequence.
+     *
+     * <p> If this method returns <tt>false</tt> for a particular character
+     * sequence then more information about why the sequence cannot be encoded
+     * may be obtained by performing a full <a href="#steps">encoding
+     * operation</a>.
+     *
+     * <p> This method may modify this encoder's state; it should therefore not
+     * be invoked if an encoding operation is already in progress.
+     *
+     * <p> The default implementation of this method is not very efficient; it
+     * should generally be overridden to improve performance.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this encoder can encode
+     *          the given character without throwing any exceptions and without
+     *          performing any replacements
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress
+     */
+    public boolean canEncode(CharSequence cs) {
+        CharBuffer cb;
+        if (cs instanceof CharBuffer)
+            cb = ((CharBuffer)cs).duplicate();
+        else
+            cb = CharBuffer.wrap(cs.toString());
+        return canEncode(cb);
+    }
+
+#end[encoder]
+
+
+    private void throwIllegalStateException(int from, int to) {
+        throw new IllegalStateException("Current state = " + stateNames[from]
+                                        + ", new state = " + stateNames[to]);
+    }
+
+}
--- a/jdk/src/share/classes/java/util/AbstractList.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/AbstractList.java	Wed Jul 05 17:02:54 2017 +0200
@@ -256,9 +256,8 @@
     public boolean addAll(int index, Collection<? extends E> c) {
         rangeCheckForAdd(index);
         boolean modified = false;
-        Iterator<? extends E> e = c.iterator();
-        while (e.hasNext()) {
-            add(index++, e.next());
+        for (E e : c) {
+            add(index++, e);
             modified = true;
         }
         return modified;
--- a/jdk/src/share/classes/java/util/AbstractQueue.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/AbstractQueue.java	Wed Jul 05 17:02:54 2017 +0200
@@ -183,11 +183,9 @@
         if (c == this)
             throw new IllegalArgumentException();
         boolean modified = false;
-        Iterator<? extends E> e = c.iterator();
-        while (e.hasNext()) {
-            if (add(e.next()))
+        for (E e : c)
+            if (add(e))
                 modified = true;
-        }
         return modified;
     }
 
--- a/jdk/src/share/classes/java/util/HashMap.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/HashMap.java	Wed Jul 05 17:02:54 2017 +0200
@@ -448,10 +448,8 @@
     }
 
     private void putAllForCreate(Map<? extends K, ? extends V> m) {
-        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
-            Map.Entry<? extends K, ? extends V> e = i.next();
+        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
             putForCreate(e.getKey(), e.getValue());
-        }
     }
 
     /**
@@ -536,10 +534,8 @@
                 resize(newCapacity);
         }
 
-        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
-            Map.Entry<? extends K, ? extends V> e = i.next();
+        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
             put(e.getKey(), e.getValue());
-        }
     }
 
     /**
--- a/jdk/src/share/classes/java/util/HashSet.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/HashSet.java	Wed Jul 05 17:02:54 2017 +0200
@@ -280,8 +280,8 @@
         s.writeInt(map.size());
 
         // Write out all elements in the proper order.
-        for (Iterator i=map.keySet().iterator(); i.hasNext(); )
-            s.writeObject(i.next());
+        for (E e : map.keySet())
+            s.writeObject(e);
     }
 
     /**
--- a/jdk/src/share/classes/java/util/Random.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/Random.java	Wed Jul 05 17:02:54 2017 +0200
@@ -50,6 +50,18 @@
  * <p>
  * Many applications will find the method {@link Math#random} simpler to use.
  *
+ * <p>Instances of {@code java.util.Random} are threadsafe.
+ * However, the concurrent use of the same {@code java.util.Random}
+ * instance across threads may encounter contention and consequent
+ * poor performance. Consider instead using
+ * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded
+ * designs.
+ *
+ * <p>Instances of {@code java.util.Random} are not cryptographically
+ * secure.  Consider instead using {@link java.security.SecureRandom} to
+ * get a cryptographically secure pseudo-random number generator for use
+ * by security-sensitive applications.
+ *
  * @author  Frank Yellin
  * @since   1.0
  */
--- a/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Wed Jul 05 17:02:54 2017 +0200
@@ -218,8 +218,8 @@
         if (capacity < c.size())
             throw new IllegalArgumentException();
 
-        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
-            add(it.next());
+        for (E e : c)
+            add(e);
     }
 
     /**
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Wed Jul 05 17:02:54 2017 +0200
@@ -250,8 +250,8 @@
      *         of its elements are null
      */
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
-        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
-            add(it.next());
+        for (E e : c)
+            add(e);
     }
 
     // Have to override just to update the javadoc
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Wed Jul 05 17:02:54 2017 +0200
@@ -895,7 +895,7 @@
                 if (n != null) {
                     Node<K,V> f = n.next;
                     if (n != b.next)               // inconsistent read
-                        break;;
+                        break;
                     Object v = n.value;
                     if (v == null) {               // n is deleted
                         n.helpDelete(b, f);
--- a/jdk/src/share/classes/java/util/concurrent/CountDownLatch.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/CountDownLatch.java	Wed Jul 05 17:02:54 2017 +0200
@@ -148,7 +148,8 @@
  *
  * </pre>
  *
- * <p>Memory consistency effects: Actions in a thread prior to calling
+ * <p>Memory consistency effects: Until the count reaches
+ * zero, actions in a thread prior to calling
  * {@code countDown()}
  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  * actions following a successful return from a corresponding
--- a/jdk/src/share/classes/java/util/concurrent/ExecutorService.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ExecutorService.java	Wed Jul 05 17:02:54 2017 +0200
@@ -332,8 +332,8 @@
      * @param tasks the collection of tasks
      * @return the result returned by one of the tasks
      * @throws InterruptedException if interrupted while waiting
-     * @throws NullPointerException if tasks or any of its elements
-     *         are <tt>null</tt>
+     * @throws NullPointerException if tasks or any element task
+     *         subject to execution is <tt>null</tt>
      * @throws IllegalArgumentException if tasks is empty
      * @throws ExecutionException if no task successfully completes
      * @throws RejectedExecutionException if tasks cannot be scheduled
@@ -356,8 +356,8 @@
      * @param unit the time unit of the timeout argument
      * @return the result returned by one of the tasks.
      * @throws InterruptedException if interrupted while waiting
-     * @throws NullPointerException if tasks, any of its elements, or
-     *         unit are <tt>null</tt>
+     * @throws NullPointerException if tasks, or unit, or any element
+     *         task subject to execution is <tt>null</tt>
      * @throws TimeoutException if the given timeout elapses before
      *         any task successfully completes
      * @throws ExecutionException if no task successfully completes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,1988 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * An {@link ExecutorService} for running {@link ForkJoinTask}s.
+ * A {@code ForkJoinPool} provides the entry point for submissions
+ * from non-{@code ForkJoinTask}s, as well as management and
+ * monitoring operations.
+ *
+ * <p>A {@code ForkJoinPool} differs from other kinds of {@link
+ * ExecutorService} mainly by virtue of employing
+ * <em>work-stealing</em>: all threads in the pool attempt to find and
+ * execute subtasks created by other active tasks (eventually blocking
+ * waiting for work if none exist). This enables efficient processing
+ * when most tasks spawn other subtasks (as do most {@code
+ * ForkJoinTask}s). A {@code ForkJoinPool} may also be used for mixed
+ * execution of some plain {@code Runnable}- or {@code Callable}-
+ * based activities along with {@code ForkJoinTask}s. When setting
+ * {@linkplain #setAsyncMode async mode}, a {@code ForkJoinPool} may
+ * also be appropriate for use with fine-grained tasks of any form
+ * that are never joined. Otherwise, other {@code ExecutorService}
+ * implementations are typically more appropriate choices.
+ *
+ * <p>A {@code ForkJoinPool} is constructed with a given target
+ * parallelism level; by default, equal to the number of available
+ * processors. Unless configured otherwise via {@link
+ * #setMaintainsParallelism}, the pool attempts to maintain this
+ * number of active (or available) threads by dynamically adding,
+ * suspending, or resuming internal worker threads, even if some tasks
+ * are stalled waiting to join others. However, no such adjustments
+ * are performed in the face of blocked IO or other unmanaged
+ * synchronization. The nested {@link ManagedBlocker} interface
+ * enables extension of the kinds of synchronization accommodated.
+ * The target parallelism level may also be changed dynamically
+ * ({@link #setParallelism}). The total number of threads may be
+ * limited using method {@link #setMaximumPoolSize}, in which case it
+ * may become possible for the activities of a pool to stall due to
+ * the lack of available threads to process new tasks.
+ *
+ * <p>In addition to execution and lifecycle control methods, this
+ * class provides status check methods (for example
+ * {@link #getStealCount}) that are intended to aid in developing,
+ * tuning, and monitoring fork/join applications. Also, method
+ * {@link #toString} returns indications of pool state in a
+ * convenient form for informal monitoring.
+ *
+ * <p><b>Sample Usage.</b> Normally a single {@code ForkJoinPool} is
+ * used for all parallel task execution in a program or subsystem.
+ * Otherwise, use would not usually outweigh the construction and
+ * bookkeeping overhead of creating a large set of threads. For
+ * example, a common pool could be used for the {@code SortTasks}
+ * illustrated in {@link RecursiveAction}. Because {@code
+ * ForkJoinPool} uses threads in {@linkplain java.lang.Thread#isDaemon
+ * daemon} mode, there is typically no need to explicitly {@link
+ * #shutdown} such a pool upon program exit.
+ *
+ * <pre>
+ * static final ForkJoinPool mainPool = new ForkJoinPool();
+ * ...
+ * public void sort(long[] array) {
+ *   mainPool.invoke(new SortTask(array, 0, array.length));
+ * }
+ * </pre>
+ *
+ * <p><b>Implementation notes</b>: This implementation restricts the
+ * maximum number of running threads to 32767. Attempts to create
+ * pools with greater than the maximum number result in
+ * {@code IllegalArgumentException}.
+ *
+ * <p>This implementation rejects submitted tasks (that is, by throwing
+ * {@link RejectedExecutionException}) only when the pool is shut down.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ForkJoinPool extends AbstractExecutorService {
+
+    /*
+     * See the extended comments interspersed below for design,
+     * rationale, and walkthroughs.
+     */
+
+    /** Mask for packing and unpacking shorts */
+    private static final int  shortMask = 0xffff;
+
+    /** Max pool size -- must be a power of two minus 1 */
+    private static final int MAX_THREADS =  0x7FFF;
+
+    /**
+     * Factory for creating new {@link ForkJoinWorkerThread}s.
+     * A {@code ForkJoinWorkerThreadFactory} must be defined and used
+     * for {@code ForkJoinWorkerThread} subclasses that extend base
+     * functionality or initialize threads with different contexts.
+     */
+    public static interface ForkJoinWorkerThreadFactory {
+        /**
+         * Returns a new worker thread operating in the given pool.
+         *
+         * @param pool the pool this thread works in
+         * @throws NullPointerException if the pool is null
+         */
+        public ForkJoinWorkerThread newThread(ForkJoinPool pool);
+    }
+
+    /**
+     * Default ForkJoinWorkerThreadFactory implementation; creates a
+     * new ForkJoinWorkerThread.
+     */
+    static class  DefaultForkJoinWorkerThreadFactory
+        implements ForkJoinWorkerThreadFactory {
+        public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
+            try {
+                return new ForkJoinWorkerThread(pool);
+            } catch (OutOfMemoryError oom)  {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Creates a new ForkJoinWorkerThread. This factory is used unless
+     * overridden in ForkJoinPool constructors.
+     */
+    public static final ForkJoinWorkerThreadFactory
+        defaultForkJoinWorkerThreadFactory =
+        new DefaultForkJoinWorkerThreadFactory();
+
+    /**
+     * Permission required for callers of methods that may start or
+     * kill threads.
+     */
+    private static final RuntimePermission modifyThreadPermission =
+        new RuntimePermission("modifyThread");
+
+    /**
+     * If there is a security manager, makes sure caller has
+     * permission to modify threads.
+     */
+    private static void checkPermission() {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null)
+            security.checkPermission(modifyThreadPermission);
+    }
+
+    /**
+     * Generator for assigning sequence numbers as pool names.
+     */
+    private static final AtomicInteger poolNumberGenerator =
+        new AtomicInteger();
+
+    /**
+     * Array holding all worker threads in the pool. Initialized upon
+     * first use. Array size must be a power of two.  Updates and
+     * replacements are protected by workerLock, but it is always kept
+     * in a consistent enough state to be randomly accessed without
+     * locking by workers performing work-stealing.
+     */
+    volatile ForkJoinWorkerThread[] workers;
+
+    /**
+     * Lock protecting access to workers.
+     */
+    private final ReentrantLock workerLock;
+
+    /**
+     * Condition for awaitTermination.
+     */
+    private final Condition termination;
+
+    /**
+     * The uncaught exception handler used when any worker
+     * abruptly terminates
+     */
+    private Thread.UncaughtExceptionHandler ueh;
+
+    /**
+     * Creation factory for worker threads.
+     */
+    private final ForkJoinWorkerThreadFactory factory;
+
+    /**
+     * Head of stack of threads that were created to maintain
+     * parallelism when other threads blocked, but have since
+     * suspended when the parallelism level rose.
+     */
+    private volatile WaitQueueNode spareStack;
+
+    /**
+     * Sum of per-thread steal counts, updated only when threads are
+     * idle or terminating.
+     */
+    private final AtomicLong stealCount;
+
+    /**
+     * Queue for external submissions.
+     */
+    private final LinkedTransferQueue<ForkJoinTask<?>> submissionQueue;
+
+    /**
+     * Head of Treiber stack for barrier sync. See below for explanation.
+     */
+    private volatile WaitQueueNode syncStack;
+
+    /**
+     * The count for event barrier
+     */
+    private volatile long eventCount;
+
+    /**
+     * Pool number, just for assigning useful names to worker threads
+     */
+    private final int poolNumber;
+
+    /**
+     * The maximum allowed pool size
+     */
+    private volatile int maxPoolSize;
+
+    /**
+     * The desired parallelism level, updated only under workerLock.
+     */
+    private volatile int parallelism;
+
+    /**
+     * True if use local fifo, not default lifo, for local polling
+     */
+    private volatile boolean locallyFifo;
+
+    /**
+     * Holds number of total (i.e., created and not yet terminated)
+     * and running (i.e., not blocked on joins or other managed sync)
+     * threads, packed into one int to ensure consistent snapshot when
+     * making decisions about creating and suspending spare
+     * threads. Updated only by CAS.  Note: CASes in
+     * updateRunningCount and preJoin assume that running active count
+     * is in low word, so need to be modified if this changes.
+     */
+    private volatile int workerCounts;
+
+    private static int totalCountOf(int s)           { return s >>> 16;  }
+    private static int runningCountOf(int s)         { return s & shortMask; }
+    private static int workerCountsFor(int t, int r) { return (t << 16) + r; }
+
+    /**
+     * Adds delta (which may be negative) to running count.  This must
+     * be called before (with negative arg) and after (with positive)
+     * any managed synchronization (i.e., mainly, joins).
+     *
+     * @param delta the number to add
+     */
+    final void updateRunningCount(int delta) {
+        int s;
+        do {} while (!casWorkerCounts(s = workerCounts, s + delta));
+    }
+
+    /**
+     * Adds delta (which may be negative) to both total and running
+     * count.  This must be called upon creation and termination of
+     * worker threads.
+     *
+     * @param delta the number to add
+     */
+    private void updateWorkerCount(int delta) {
+        int d = delta + (delta << 16); // add to both lo and hi parts
+        int s;
+        do {} while (!casWorkerCounts(s = workerCounts, s + d));
+    }
+
+    /**
+     * Lifecycle control. High word contains runState, low word
+     * contains the number of workers that are (probably) executing
+     * tasks. This value is atomically incremented before a worker
+     * gets a task to run, and decremented when worker has no tasks
+     * and cannot find any. These two fields are bundled together to
+     * support correct termination triggering.  Note: activeCount
+     * CAS'es cheat by assuming active count is in low word, so need
+     * to be modified if this changes
+     */
+    private volatile int runControl;
+
+    // RunState values. Order among values matters
+    private static final int RUNNING     = 0;
+    private static final int SHUTDOWN    = 1;
+    private static final int TERMINATING = 2;
+    private static final int TERMINATED  = 3;
+
+    private static int runStateOf(int c)             { return c >>> 16; }
+    private static int activeCountOf(int c)          { return c & shortMask; }
+    private static int runControlFor(int r, int a)   { return (r << 16) + a; }
+
+    /**
+     * Tries incrementing active count; fails on contention.
+     * Called by workers before/during executing tasks.
+     *
+     * @return true on success
+     */
+    final boolean tryIncrementActiveCount() {
+        int c = runControl;
+        return casRunControl(c, c+1);
+    }
+
+    /**
+     * Tries decrementing active count; fails on contention.
+     * Possibly triggers termination on success.
+     * Called by workers when they can't find tasks.
+     *
+     * @return true on success
+     */
+    final boolean tryDecrementActiveCount() {
+        int c = runControl;
+        int nextc = c - 1;
+        if (!casRunControl(c, nextc))
+            return false;
+        if (canTerminateOnShutdown(nextc))
+            terminateOnShutdown();
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if argument represents zero active count
+     * and nonzero runstate, which is the triggering condition for
+     * terminating on shutdown.
+     */
+    private static boolean canTerminateOnShutdown(int c) {
+        // i.e. least bit is nonzero runState bit
+        return ((c & -c) >>> 16) != 0;
+    }
+
+    /**
+     * Transition run state to at least the given state. Return true
+     * if not already at least given state.
+     */
+    private boolean transitionRunStateTo(int state) {
+        for (;;) {
+            int c = runControl;
+            if (runStateOf(c) >= state)
+                return false;
+            if (casRunControl(c, runControlFor(state, activeCountOf(c))))
+                return true;
+        }
+    }
+
+    /**
+     * Controls whether to add spares to maintain parallelism
+     */
+    private volatile boolean maintainsParallelism;
+
+    // Constructors
+
+    /**
+     * Creates a {@code ForkJoinPool} with parallelism equal to {@link
+     * java.lang.Runtime#availableProcessors}, and using the {@linkplain
+     * #defaultForkJoinWorkerThreadFactory default thread factory}.
+     *
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool() {
+        this(Runtime.getRuntime().availableProcessors(),
+             defaultForkJoinWorkerThreadFactory);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with the indicated parallelism
+     * level and using the {@linkplain
+     * #defaultForkJoinWorkerThreadFactory default thread factory}.
+     *
+     * @param parallelism the parallelism level
+     * @throws IllegalArgumentException if parallelism less than or
+     *         equal to zero, or greater than implementation limit
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool(int parallelism) {
+        this(parallelism, defaultForkJoinWorkerThreadFactory);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with parallelism equal to {@link
+     * java.lang.Runtime#availableProcessors}, and using the given
+     * thread factory.
+     *
+     * @param factory the factory for creating new threads
+     * @throws NullPointerException if the factory is null
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool(ForkJoinWorkerThreadFactory factory) {
+        this(Runtime.getRuntime().availableProcessors(), factory);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with the given parallelism and
+     * thread factory.
+     *
+     * @param parallelism the parallelism level
+     * @param factory the factory for creating new threads
+     * @throws IllegalArgumentException if parallelism less than or
+     *         equal to zero, or greater than implementation limit
+     * @throws NullPointerException if the factory is null
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory) {
+        if (parallelism <= 0 || parallelism > MAX_THREADS)
+            throw new IllegalArgumentException();
+        if (factory == null)
+            throw new NullPointerException();
+        checkPermission();
+        this.factory = factory;
+        this.parallelism = parallelism;
+        this.maxPoolSize = MAX_THREADS;
+        this.maintainsParallelism = true;
+        this.poolNumber = poolNumberGenerator.incrementAndGet();
+        this.workerLock = new ReentrantLock();
+        this.termination = workerLock.newCondition();
+        this.stealCount = new AtomicLong();
+        this.submissionQueue = new LinkedTransferQueue<ForkJoinTask<?>>();
+        // worker array and workers are lazily constructed
+    }
+
+    /**
+     * Creates a new worker thread using factory.
+     *
+     * @param index the index to assign worker
+     * @return new worker, or null if factory failed
+     */
+    private ForkJoinWorkerThread createWorker(int index) {
+        Thread.UncaughtExceptionHandler h = ueh;
+        ForkJoinWorkerThread w = factory.newThread(this);
+        if (w != null) {
+            w.poolIndex = index;
+            w.setDaemon(true);
+            w.setAsyncMode(locallyFifo);
+            w.setName("ForkJoinPool-" + poolNumber + "-worker-" + index);
+            if (h != null)
+                w.setUncaughtExceptionHandler(h);
+        }
+        return w;
+    }
+
+    /**
+     * Returns a good size for worker array given pool size.
+     * Currently requires size to be a power of two.
+     */
+    private static int arraySizeFor(int poolSize) {
+        if (poolSize <= 1)
+            return 1;
+        // See Hackers Delight, sec 3.2
+        int c = poolSize >= MAX_THREADS ? MAX_THREADS : (poolSize - 1);
+        c |= c >>>  1;
+        c |= c >>>  2;
+        c |= c >>>  4;
+        c |= c >>>  8;
+        c |= c >>> 16;
+        return c + 1;
+    }
+
+    /**
+     * Creates or resizes array if necessary to hold newLength.
+     * Call only under exclusion.
+     *
+     * @return the array
+     */
+    private ForkJoinWorkerThread[] ensureWorkerArrayCapacity(int newLength) {
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws == null)
+            return workers = new ForkJoinWorkerThread[arraySizeFor(newLength)];
+        else if (newLength > ws.length)
+            return workers = Arrays.copyOf(ws, arraySizeFor(newLength));
+        else
+            return ws;
+    }
+
+    /**
+     * Tries to shrink workers into smaller array after one or more terminate.
+     */
+    private void tryShrinkWorkerArray() {
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            int len = ws.length;
+            int last = len - 1;
+            while (last >= 0 && ws[last] == null)
+                --last;
+            int newLength = arraySizeFor(last+1);
+            if (newLength < len)
+                workers = Arrays.copyOf(ws, newLength);
+        }
+    }
+
+    /**
+     * Initializes workers if necessary.
+     */
+    final void ensureWorkerInitialization() {
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws == null) {
+            final ReentrantLock lock = this.workerLock;
+            lock.lock();
+            try {
+                ws = workers;
+                if (ws == null) {
+                    int ps = parallelism;
+                    ws = ensureWorkerArrayCapacity(ps);
+                    for (int i = 0; i < ps; ++i) {
+                        ForkJoinWorkerThread w = createWorker(i);
+                        if (w != null) {
+                            ws[i] = w;
+                            w.start();
+                            updateWorkerCount(1);
+                        }
+                    }
+                }
+            } finally {
+                lock.unlock();
+            }
+        }
+    }
+
+    /**
+     * Worker creation and startup for threads added via setParallelism.
+     */
+    private void createAndStartAddedWorkers() {
+        resumeAllSpares();  // Allow spares to convert to nonspare
+        int ps = parallelism;
+        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(ps);
+        int len = ws.length;
+        // Sweep through slots, to keep lowest indices most populated
+        int k = 0;
+        while (k < len) {
+            if (ws[k] != null) {
+                ++k;
+                continue;
+            }
+            int s = workerCounts;
+            int tc = totalCountOf(s);
+            int rc = runningCountOf(s);
+            if (rc >= ps || tc >= ps)
+                break;
+            if (casWorkerCounts (s, workerCountsFor(tc+1, rc+1))) {
+                ForkJoinWorkerThread w = createWorker(k);
+                if (w != null) {
+                    ws[k++] = w;
+                    w.start();
+                }
+                else {
+                    updateWorkerCount(-1); // back out on failed creation
+                    break;
+                }
+            }
+        }
+    }
+
+    // Execution methods
+
+    /**
+     * Common code for execute, invoke and submit
+     */
+    private <T> void doSubmit(ForkJoinTask<T> task) {
+        if (task == null)
+            throw new NullPointerException();
+        if (isShutdown())
+            throw new RejectedExecutionException();
+        if (workers == null)
+            ensureWorkerInitialization();
+        submissionQueue.offer(task);
+        signalIdleWorkers();
+    }
+
+    /**
+     * Performs the given task, returning its result upon completion.
+     *
+     * @param task the task
+     * @return the task's result
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> T invoke(ForkJoinTask<T> task) {
+        doSubmit(task);
+        return task.join();
+    }
+
+    /**
+     * Arranges for (asynchronous) execution of the given task.
+     *
+     * @param task the task
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public void execute(ForkJoinTask<?> task) {
+        doSubmit(task);
+    }
+
+    // AbstractExecutorService methods
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public void execute(Runnable task) {
+        ForkJoinTask<?> job;
+        if (task instanceof ForkJoinTask<?>) // avoid re-wrap
+            job = (ForkJoinTask<?>) task;
+        else
+            job = ForkJoinTask.adapt(task, null);
+        doSubmit(job);
+    }
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(Callable<T> task) {
+        ForkJoinTask<T> job = ForkJoinTask.adapt(task);
+        doSubmit(job);
+        return job;
+    }
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(Runnable task, T result) {
+        ForkJoinTask<T> job = ForkJoinTask.adapt(task, result);
+        doSubmit(job);
+        return job;
+    }
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public ForkJoinTask<?> submit(Runnable task) {
+        ForkJoinTask<?> job;
+        if (task instanceof ForkJoinTask<?>) // avoid re-wrap
+            job = (ForkJoinTask<?>) task;
+        else
+            job = ForkJoinTask.adapt(task, null);
+        doSubmit(job);
+        return job;
+    }
+
+    /**
+     * Submits a ForkJoinTask for execution.
+     *
+     * @param task the task to submit
+     * @return the task
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
+        doSubmit(task);
+        return task;
+    }
+
+
+    /**
+     * @throws NullPointerException       {@inheritDoc}
+     * @throws RejectedExecutionException {@inheritDoc}
+     */
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
+        ArrayList<ForkJoinTask<T>> forkJoinTasks =
+            new ArrayList<ForkJoinTask<T>>(tasks.size());
+        for (Callable<T> task : tasks)
+            forkJoinTasks.add(ForkJoinTask.adapt(task));
+        invoke(new InvokeAll<T>(forkJoinTasks));
+
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
+        return futures;
+    }
+
+    static final class InvokeAll<T> extends RecursiveAction {
+        final ArrayList<ForkJoinTask<T>> tasks;
+        InvokeAll(ArrayList<ForkJoinTask<T>> tasks) { this.tasks = tasks; }
+        public void compute() {
+            try { invokeAll(tasks); }
+            catch (Exception ignore) {}
+        }
+        private static final long serialVersionUID = -7914297376763021607L;
+    }
+
+    // Configuration and status settings and queries
+
+    /**
+     * Returns the factory used for constructing new workers.
+     *
+     * @return the factory used for constructing new workers
+     */
+    public ForkJoinWorkerThreadFactory getFactory() {
+        return factory;
+    }
+
+    /**
+     * Returns the handler for internal worker threads that terminate
+     * due to unrecoverable errors encountered while executing tasks.
+     *
+     * @return the handler, or {@code null} if none
+     */
+    public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
+        Thread.UncaughtExceptionHandler h;
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            h = ueh;
+        } finally {
+            lock.unlock();
+        }
+        return h;
+    }
+
+    /**
+     * Sets the handler for internal worker threads that terminate due
+     * to unrecoverable errors encountered while executing tasks.
+     * Unless set, the current default or ThreadGroup handler is used
+     * as handler.
+     *
+     * @param h the new handler
+     * @return the old handler, or {@code null} if none
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public Thread.UncaughtExceptionHandler
+        setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler h) {
+        checkPermission();
+        Thread.UncaughtExceptionHandler old = null;
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            old = ueh;
+            ueh = h;
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread w = ws[i];
+                    if (w != null)
+                        w.setUncaughtExceptionHandler(h);
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+        return old;
+    }
+
+
+    /**
+     * Sets the target parallelism level of this pool.
+     *
+     * @param parallelism the target parallelism
+     * @throws IllegalArgumentException if parallelism less than or
+     * equal to zero or greater than maximum size bounds
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public void setParallelism(int parallelism) {
+        checkPermission();
+        if (parallelism <= 0 || parallelism > maxPoolSize)
+            throw new IllegalArgumentException();
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            if (isProcessingTasks()) {
+                int p = this.parallelism;
+                this.parallelism = parallelism;
+                if (parallelism > p)
+                    createAndStartAddedWorkers();
+                else
+                    trimSpares();
+            }
+        } finally {
+            lock.unlock();
+        }
+        signalIdleWorkers();
+    }
+
+    /**
+     * Returns the targeted parallelism level of this pool.
+     *
+     * @return the targeted parallelism level of this pool
+     */
+    public int getParallelism() {
+        return parallelism;
+    }
+
+    /**
+     * Returns the number of worker threads that have started but not
+     * yet terminated.  This result returned by this method may differ
+     * from {@link #getParallelism} when threads are created to
+     * maintain parallelism when others are cooperatively blocked.
+     *
+     * @return the number of worker threads
+     */
+    public int getPoolSize() {
+        return totalCountOf(workerCounts);
+    }
+
+    /**
+     * Returns the maximum number of threads allowed to exist in the
+     * pool. Unless set using {@link #setMaximumPoolSize}, the
+     * maximum is an implementation-defined value designed only to
+     * prevent runaway growth.
+     *
+     * @return the maximum
+     */
+    public int getMaximumPoolSize() {
+        return maxPoolSize;
+    }
+
+    /**
+     * Sets the maximum number of threads allowed to exist in the
+     * pool. The given value should normally be greater than or equal
+     * to the {@link #getParallelism parallelism} level. Setting this
+     * value has no effect on current pool size. It controls
+     * construction of new threads.
+     *
+     * @throws IllegalArgumentException if negative or greater than
+     * internal implementation limit
+     */
+    public void setMaximumPoolSize(int newMax) {
+        if (newMax < 0 || newMax > MAX_THREADS)
+            throw new IllegalArgumentException();
+        maxPoolSize = newMax;
+    }
+
+
+    /**
+     * Returns {@code true} if this pool dynamically maintains its
+     * target parallelism level. If false, new threads are added only
+     * to avoid possible starvation.  This setting is by default true.
+     *
+     * @return {@code true} if maintains parallelism
+     */
+    public boolean getMaintainsParallelism() {
+        return maintainsParallelism;
+    }
+
+    /**
+     * Sets whether this pool dynamically maintains its target
+     * parallelism level. If false, new threads are added only to
+     * avoid possible starvation.
+     *
+     * @param enable {@code true} to maintain parallelism
+     */
+    public void setMaintainsParallelism(boolean enable) {
+        maintainsParallelism = enable;
+    }
+
+    /**
+     * Establishes local first-in-first-out scheduling mode for forked
+     * tasks that are never joined. This mode may be more appropriate
+     * than default locally stack-based mode in applications in which
+     * worker threads only process asynchronous tasks.  This method is
+     * designed to be invoked only when the pool is quiescent, and
+     * typically only before any tasks are submitted. The effects of
+     * invocations at other times may be unpredictable.
+     *
+     * @param async if {@code true}, use locally FIFO scheduling
+     * @return the previous mode
+     * @see #getAsyncMode
+     */
+    public boolean setAsyncMode(boolean async) {
+        boolean oldMode = locallyFifo;
+        locallyFifo = async;
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                ForkJoinWorkerThread t = ws[i];
+                if (t != null)
+                    t.setAsyncMode(async);
+            }
+        }
+        return oldMode;
+    }
+
+    /**
+     * Returns {@code true} if this pool uses local first-in-first-out
+     * scheduling mode for forked tasks that are never joined.
+     *
+     * @return {@code true} if this pool uses async mode
+     * @see #setAsyncMode
+     */
+    public boolean getAsyncMode() {
+        return locallyFifo;
+    }
+
+    /**
+     * Returns an estimate of the number of worker threads that are
+     * not blocked waiting to join tasks or for other managed
+     * synchronization.
+     *
+     * @return the number of worker threads
+     */
+    public int getRunningThreadCount() {
+        return runningCountOf(workerCounts);
+    }
+
+    /**
+     * Returns an estimate of the number of threads that are currently
+     * stealing or executing tasks. This method may overestimate the
+     * number of active threads.
+     *
+     * @return the number of active threads
+     */
+    public int getActiveThreadCount() {
+        return activeCountOf(runControl);
+    }
+
+    /**
+     * Returns an estimate of the number of threads that are currently
+     * idle waiting for tasks. This method may underestimate the
+     * number of idle threads.
+     *
+     * @return the number of idle threads
+     */
+    final int getIdleThreadCount() {
+        int c = runningCountOf(workerCounts) - activeCountOf(runControl);
+        return (c <= 0) ? 0 : c;
+    }
+
+    /**
+     * Returns {@code true} if all worker threads are currently idle.
+     * An idle worker is one that cannot obtain a task to execute
+     * because none are available to steal from other threads, and
+     * there are no pending submissions to the pool. This method is
+     * conservative; it might not return {@code true} immediately upon
+     * idleness of all threads, but will eventually become true if
+     * threads remain inactive.
+     *
+     * @return {@code true} if all threads are currently idle
+     */
+    public boolean isQuiescent() {
+        return activeCountOf(runControl) == 0;
+    }
+
+    /**
+     * Returns an estimate of the total number of tasks stolen from
+     * one thread's work queue by another. The reported value
+     * underestimates the actual total number of steals when the pool
+     * is not quiescent. This value may be useful for monitoring and
+     * tuning fork/join programs: in general, steal counts should be
+     * high enough to keep threads busy, but low enough to avoid
+     * overhead and contention across threads.
+     *
+     * @return the number of steals
+     */
+    public long getStealCount() {
+        return stealCount.get();
+    }
+
+    /**
+     * Accumulates steal count from a worker.
+     * Call only when worker known to be idle.
+     */
+    private void updateStealCount(ForkJoinWorkerThread w) {
+        int sc = w.getAndClearStealCount();
+        if (sc != 0)
+            stealCount.addAndGet(sc);
+    }
+
+    /**
+     * Returns an estimate of the total number of tasks currently held
+     * in queues by worker threads (but not including tasks submitted
+     * to the pool that have not begun executing). This value is only
+     * an approximation, obtained by iterating across all threads in
+     * the pool. This method may be useful for tuning task
+     * granularities.
+     *
+     * @return the number of queued tasks
+     */
+    public long getQueuedTaskCount() {
+        long count = 0;
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                ForkJoinWorkerThread t = ws[i];
+                if (t != null)
+                    count += t.getQueueSize();
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Returns an estimate of the number of tasks submitted to this
+     * pool that have not yet begun executing.  This method takes time
+     * proportional to the number of submissions.
+     *
+     * @return the number of queued submissions
+     */
+    public int getQueuedSubmissionCount() {
+        return submissionQueue.size();
+    }
+
+    /**
+     * Returns {@code true} if there are any tasks submitted to this
+     * pool that have not yet begun executing.
+     *
+     * @return {@code true} if there are any queued submissions
+     */
+    public boolean hasQueuedSubmissions() {
+        return !submissionQueue.isEmpty();
+    }
+
+    /**
+     * Removes and returns the next unexecuted submission if one is
+     * available.  This method may be useful in extensions to this
+     * class that re-assign work in systems with multiple pools.
+     *
+     * @return the next submission, or {@code null} if none
+     */
+    protected ForkJoinTask<?> pollSubmission() {
+        return submissionQueue.poll();
+    }
+
+    /**
+     * Removes all available unexecuted submitted and forked tasks
+     * from scheduling queues and adds them to the given collection,
+     * without altering their execution status. These may include
+     * artificially generated or wrapped tasks. This method is
+     * designed to be invoked only when the pool is known to be
+     * quiescent. Invocations at other times may not remove all
+     * tasks. A failure encountered while attempting to add elements
+     * to collection {@code c} may result in elements being in
+     * neither, either or both collections when the associated
+     * exception is thrown.  The behavior of this operation is
+     * undefined if the specified collection is modified while the
+     * operation is in progress.
+     *
+     * @param c the collection to transfer elements into
+     * @return the number of elements transferred
+     */
+    protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
+        int n = submissionQueue.drainTo(c);
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                ForkJoinWorkerThread w = ws[i];
+                if (w != null)
+                    n += w.drainTasksTo(c);
+            }
+        }
+        return n;
+    }
+
+    /**
+     * Returns a string identifying this pool, as well as its state,
+     * including indications of run state, parallelism level, and
+     * worker and task counts.
+     *
+     * @return a string identifying this pool, as well as its state
+     */
+    public String toString() {
+        int ps = parallelism;
+        int wc = workerCounts;
+        int rc = runControl;
+        long st = getStealCount();
+        long qt = getQueuedTaskCount();
+        long qs = getQueuedSubmissionCount();
+        return super.toString() +
+            "[" + runStateToString(runStateOf(rc)) +
+            ", parallelism = " + ps +
+            ", size = " + totalCountOf(wc) +
+            ", active = " + activeCountOf(rc) +
+            ", running = " + runningCountOf(wc) +
+            ", steals = " + st +
+            ", tasks = " + qt +
+            ", submissions = " + qs +
+            "]";
+    }
+
+    private static String runStateToString(int rs) {
+        switch(rs) {
+        case RUNNING: return "Running";
+        case SHUTDOWN: return "Shutting down";
+        case TERMINATING: return "Terminating";
+        case TERMINATED: return "Terminated";
+        default: throw new Error("Unknown run state");
+        }
+    }
+
+    // lifecycle control
+
+    /**
+     * Initiates an orderly shutdown in which previously submitted
+     * tasks are executed, but no new tasks will be accepted.
+     * Invocation has no additional effect if already shut down.
+     * Tasks that are in the process of being submitted concurrently
+     * during the course of this method may or may not be rejected.
+     *
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public void shutdown() {
+        checkPermission();
+        transitionRunStateTo(SHUTDOWN);
+        if (canTerminateOnShutdown(runControl)) {
+            if (workers == null) { // shutting down before workers created
+                final ReentrantLock lock = this.workerLock;
+                lock.lock();
+                try {
+                    if (workers == null) {
+                        terminate();
+                        transitionRunStateTo(TERMINATED);
+                        termination.signalAll();
+                    }
+                } finally {
+                    lock.unlock();
+                }
+            }
+            terminateOnShutdown();
+        }
+    }
+
+    /**
+     * Attempts to cancel and/or stop all tasks, and reject all
+     * subsequently submitted tasks.  Tasks that are in the process of
+     * being submitted or executed concurrently during the course of
+     * this method may or may not be rejected. This method cancels
+     * both existing and unexecuted tasks, in order to permit
+     * termination in the presence of task dependencies. So the method
+     * always returns an empty list (unlike the case for some other
+     * Executors).
+     *
+     * @return an empty list
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public List<Runnable> shutdownNow() {
+        checkPermission();
+        terminate();
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns {@code true} if all tasks have completed following shut down.
+     *
+     * @return {@code true} if all tasks have completed following shut down
+     */
+    public boolean isTerminated() {
+        return runStateOf(runControl) == TERMINATED;
+    }
+
+    /**
+     * Returns {@code true} if the process of termination has
+     * commenced but not yet completed.  This method may be useful for
+     * debugging. A return of {@code true} reported a sufficient
+     * period after shutdown may indicate that submitted tasks have
+     * ignored or suppressed interruption, causing this executor not
+     * to properly terminate.
+     *
+     * @return {@code true} if terminating but not yet terminated
+     */
+    public boolean isTerminating() {
+        return runStateOf(runControl) == TERMINATING;
+    }
+
+    /**
+     * Returns {@code true} if this pool has been shut down.
+     *
+     * @return {@code true} if this pool has been shut down
+     */
+    public boolean isShutdown() {
+        return runStateOf(runControl) >= SHUTDOWN;
+    }
+
+    /**
+     * Returns true if pool is not terminating or terminated.
+     * Used internally to suppress execution when terminating.
+     */
+    final boolean isProcessingTasks() {
+        return runStateOf(runControl) < TERMINATING;
+    }
+
+    /**
+     * Blocks until all tasks have completed execution after a shutdown
+     * request, or the timeout occurs, or the current thread is
+     * interrupted, whichever happens first.
+     *
+     * @param timeout the maximum time to wait
+     * @param unit the time unit of the timeout argument
+     * @return {@code true} if this executor terminated and
+     *         {@code false} if the timeout elapsed before termination
+     * @throws InterruptedException if interrupted while waiting
+     */
+    public boolean awaitTermination(long timeout, TimeUnit unit)
+        throws InterruptedException {
+        long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            for (;;) {
+                if (isTerminated())
+                    return true;
+                if (nanos <= 0)
+                    return false;
+                nanos = termination.awaitNanos(nanos);
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    // Shutdown and termination support
+
+    /**
+     * Callback from terminating worker. Nulls out the corresponding
+     * workers slot, and if terminating, tries to terminate; else
+     * tries to shrink workers array.
+     *
+     * @param w the worker
+     */
+    final void workerTerminated(ForkJoinWorkerThread w) {
+        updateStealCount(w);
+        updateWorkerCount(-1);
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                int idx = w.poolIndex;
+                if (idx >= 0 && idx < ws.length && ws[idx] == w)
+                    ws[idx] = null;
+                if (totalCountOf(workerCounts) == 0) {
+                    terminate(); // no-op if already terminating
+                    transitionRunStateTo(TERMINATED);
+                    termination.signalAll();
+                }
+                else if (isProcessingTasks()) {
+                    tryShrinkWorkerArray();
+                    tryResumeSpare(true); // allow replacement
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+        signalIdleWorkers();
+    }
+
+    /**
+     * Initiates termination.
+     */
+    private void terminate() {
+        if (transitionRunStateTo(TERMINATING)) {
+            stopAllWorkers();
+            resumeAllSpares();
+            signalIdleWorkers();
+            cancelQueuedSubmissions();
+            cancelQueuedWorkerTasks();
+            interruptUnterminatedWorkers();
+            signalIdleWorkers(); // resignal after interrupt
+        }
+    }
+
+    /**
+     * Possibly terminates when on shutdown state.
+     */
+    private void terminateOnShutdown() {
+        if (!hasQueuedSubmissions() && canTerminateOnShutdown(runControl))
+            terminate();
+    }
+
+    /**
+     * Clears out and cancels submissions.
+     */
+    private void cancelQueuedSubmissions() {
+        ForkJoinTask<?> task;
+        while ((task = pollSubmission()) != null)
+            task.cancel(false);
+    }
+
+    /**
+     * Cleans out worker queues.
+     */
+    private void cancelQueuedWorkerTasks() {
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread t = ws[i];
+                    if (t != null)
+                        t.cancelTasks();
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Sets each worker's status to terminating. Requires lock to avoid
+     * conflicts with add/remove.
+     */
+    private void stopAllWorkers() {
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread t = ws[i];
+                    if (t != null)
+                        t.shutdownNow();
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Interrupts all unterminated workers.  This is not required for
+     * sake of internal control, but may help unstick user code during
+     * shutdown.
+     */
+    private void interruptUnterminatedWorkers() {
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread t = ws[i];
+                    if (t != null && !t.isTerminated()) {
+                        try {
+                            t.interrupt();
+                        } catch (SecurityException ignore) {
+                        }
+                    }
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+
+    /*
+     * Nodes for event barrier to manage idle threads.  Queue nodes
+     * are basic Treiber stack nodes, also used for spare stack.
+     *
+     * The event barrier has an event count and a wait queue (actually
+     * a Treiber stack).  Workers are enabled to look for work when
+     * the eventCount is incremented. If they fail to find work, they
+     * may wait for next count. Upon release, threads help others wake
+     * up.
+     *
+     * Synchronization events occur only in enough contexts to
+     * maintain overall liveness:
+     *
+     *   - Submission of a new task to the pool
+     *   - Resizes or other changes to the workers array
+     *   - pool termination
+     *   - A worker pushing a task on an empty queue
+     *
+     * The case of pushing a task occurs often enough, and is heavy
+     * enough compared to simple stack pushes, to require special
+     * handling: Method signalWork returns without advancing count if
+     * the queue appears to be empty.  This would ordinarily result in
+     * races causing some queued waiters not to be woken up. To avoid
+     * this, the first worker enqueued in method sync (see
+     * syncIsReleasable) rescans for tasks after being enqueued, and
+     * helps signal if any are found. This works well because the
+     * worker has nothing better to do, and so might as well help
+     * alleviate the overhead and contention on the threads actually
+     * doing work.  Also, since event counts increments on task
+     * availability exist to maintain liveness (rather than to force
+     * refreshes etc), it is OK for callers to exit early if
+     * contending with another signaller.
+     */
+    static final class WaitQueueNode {
+        WaitQueueNode next; // only written before enqueued
+        volatile ForkJoinWorkerThread thread; // nulled to cancel wait
+        final long count; // unused for spare stack
+
+        WaitQueueNode(long c, ForkJoinWorkerThread w) {
+            count = c;
+            thread = w;
+        }
+
+        /**
+         * Wakes up waiter, returning false if known to already
+         */
+        boolean signal() {
+            ForkJoinWorkerThread t = thread;
+            if (t == null)
+                return false;
+            thread = null;
+            LockSupport.unpark(t);
+            return true;
+        }
+
+        /**
+         * Awaits release on sync.
+         */
+        void awaitSyncRelease(ForkJoinPool p) {
+            while (thread != null && !p.syncIsReleasable(this))
+                LockSupport.park(this);
+        }
+
+        /**
+         * Awaits resumption as spare.
+         */
+        void awaitSpareRelease() {
+            while (thread != null) {
+                if (!Thread.interrupted())
+                    LockSupport.park(this);
+            }
+        }
+    }
+
+    /**
+     * Ensures that no thread is waiting for count to advance from the
+     * current value of eventCount read on entry to this method, by
+     * releasing waiting threads if necessary.
+     *
+     * @return the count
+     */
+    final long ensureSync() {
+        long c = eventCount;
+        WaitQueueNode q;
+        while ((q = syncStack) != null && q.count < c) {
+            if (casBarrierStack(q, null)) {
+                do {
+                    q.signal();
+                } while ((q = q.next) != null);
+                break;
+            }
+        }
+        return c;
+    }
+
+    /**
+     * Increments event count and releases waiting threads.
+     */
+    private void signalIdleWorkers() {
+        long c;
+        do {} while (!casEventCount(c = eventCount, c+1));
+        ensureSync();
+    }
+
+    /**
+     * Signals threads waiting to poll a task. Because method sync
+     * rechecks availability, it is OK to only proceed if queue
+     * appears to be non-empty, and OK to skip under contention to
+     * increment count (since some other thread succeeded).
+     */
+    final void signalWork() {
+        long c;
+        WaitQueueNode q;
+        if (syncStack != null &&
+            casEventCount(c = eventCount, c+1) &&
+            (((q = syncStack) != null && q.count <= c) &&
+             (!casBarrierStack(q, q.next) || !q.signal())))
+            ensureSync();
+    }
+
+    /**
+     * Waits until event count advances from last value held by
+     * caller, or if excess threads, caller is resumed as spare, or
+     * caller or pool is terminating. Updates caller's event on exit.
+     *
+     * @param w the calling worker thread
+     */
+    final void sync(ForkJoinWorkerThread w) {
+        updateStealCount(w); // Transfer w's count while it is idle
+
+        while (!w.isShutdown() && isProcessingTasks() && !suspendIfSpare(w)) {
+            long prev = w.lastEventCount;
+            WaitQueueNode node = null;
+            WaitQueueNode h;
+            while (eventCount == prev &&
+                   ((h = syncStack) == null || h.count == prev)) {
+                if (node == null)
+                    node = new WaitQueueNode(prev, w);
+                if (casBarrierStack(node.next = h, node)) {
+                    node.awaitSyncRelease(this);
+                    break;
+                }
+            }
+            long ec = ensureSync();
+            if (ec != prev) {
+                w.lastEventCount = ec;
+                break;
+            }
+        }
+    }
+
+    /**
+     * Returns {@code true} if worker waiting on sync can proceed:
+     *  - on signal (thread == null)
+     *  - on event count advance (winning race to notify vs signaller)
+     *  - on interrupt
+     *  - if the first queued node, we find work available
+     * If node was not signalled and event count not advanced on exit,
+     * then we also help advance event count.
+     *
+     * @return {@code true} if node can be released
+     */
+    final boolean syncIsReleasable(WaitQueueNode node) {
+        long prev = node.count;
+        if (!Thread.interrupted() && node.thread != null &&
+            (node.next != null ||
+             !ForkJoinWorkerThread.hasQueuedTasks(workers)) &&
+            eventCount == prev)
+            return false;
+        if (node.thread != null) {
+            node.thread = null;
+            long ec = eventCount;
+            if (prev <= ec) // help signal
+                casEventCount(ec, ec+1);
+        }
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if a new sync event occurred since last
+     * call to sync or this method, if so, updating caller's count.
+     */
+    final boolean hasNewSyncEvent(ForkJoinWorkerThread w) {
+        long lc = w.lastEventCount;
+        long ec = ensureSync();
+        if (ec == lc)
+            return false;
+        w.lastEventCount = ec;
+        return true;
+    }
+
+    //  Parallelism maintenance
+
+    /**
+     * Decrements running count; if too low, adds spare.
+     *
+     * Conceptually, all we need to do here is add or resume a
+     * spare thread when one is about to block (and remove or
+     * suspend it later when unblocked -- see suspendIfSpare).
+     * However, implementing this idea requires coping with
+     * several problems: we have imperfect information about the
+     * states of threads. Some count updates can and usually do
+     * lag run state changes, despite arrangements to keep them
+     * accurate (for example, when possible, updating counts
+     * before signalling or resuming), especially when running on
+     * dynamic JVMs that don't optimize the infrequent paths that
+     * update counts. Generating too many threads can make these
+     * problems become worse, because excess threads are more
+     * likely to be context-switched with others, slowing them all
+     * down, especially if there is no work available, so all are
+     * busy scanning or idling.  Also, excess spare threads can
+     * only be suspended or removed when they are idle, not
+     * immediately when they aren't needed. So adding threads will
+     * raise parallelism level for longer than necessary.  Also,
+     * FJ applications often encounter highly transient peaks when
+     * many threads are blocked joining, but for less time than it
+     * takes to create or resume spares.
+     *
+     * @param joinMe if non-null, return early if done
+     * @param maintainParallelism if true, try to stay within
+     * target counts, else create only to avoid starvation
+     * @return true if joinMe known to be done
+     */
+    final boolean preJoin(ForkJoinTask<?> joinMe,
+                          boolean maintainParallelism) {
+        maintainParallelism &= maintainsParallelism; // overrride
+        boolean dec = false;  // true when running count decremented
+        while (spareStack == null || !tryResumeSpare(dec)) {
+            int counts = workerCounts;
+            if (dec || (dec = casWorkerCounts(counts, --counts))) {
+                if (!needSpare(counts, maintainParallelism))
+                    break;
+                if (joinMe.status < 0)
+                    return true;
+                if (tryAddSpare(counts))
+                    break;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Same idea as preJoin
+     */
+    final boolean preBlock(ManagedBlocker blocker,
+                           boolean maintainParallelism) {
+        maintainParallelism &= maintainsParallelism;
+        boolean dec = false;
+        while (spareStack == null || !tryResumeSpare(dec)) {
+            int counts = workerCounts;
+            if (dec || (dec = casWorkerCounts(counts, --counts))) {
+                if (!needSpare(counts, maintainParallelism))
+                    break;
+                if (blocker.isReleasable())
+                    return true;
+                if (tryAddSpare(counts))
+                    break;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if a spare thread appears to be needed.
+     * If maintaining parallelism, returns true when the deficit in
+     * running threads is more than the surplus of total threads, and
+     * there is apparently some work to do.  This self-limiting rule
+     * means that the more threads that have already been added, the
+     * less parallelism we will tolerate before adding another.
+     *
+     * @param counts current worker counts
+     * @param maintainParallelism try to maintain parallelism
+     */
+    private boolean needSpare(int counts, boolean maintainParallelism) {
+        int ps = parallelism;
+        int rc = runningCountOf(counts);
+        int tc = totalCountOf(counts);
+        int runningDeficit = ps - rc;
+        int totalSurplus = tc - ps;
+        return (tc < maxPoolSize &&
+                (rc == 0 || totalSurplus < 0 ||
+                 (maintainParallelism &&
+                  runningDeficit > totalSurplus &&
+                  ForkJoinWorkerThread.hasQueuedTasks(workers))));
+    }
+
+    /**
+     * Adds a spare worker if lock available and no more than the
+     * expected numbers of threads exist.
+     *
+     * @return true if successful
+     */
+    private boolean tryAddSpare(int expectedCounts) {
+        final ReentrantLock lock = this.workerLock;
+        int expectedRunning = runningCountOf(expectedCounts);
+        int expectedTotal = totalCountOf(expectedCounts);
+        boolean success = false;
+        boolean locked = false;
+        // confirm counts while locking; CAS after obtaining lock
+        try {
+            for (;;) {
+                int s = workerCounts;
+                int tc = totalCountOf(s);
+                int rc = runningCountOf(s);
+                if (rc > expectedRunning || tc > expectedTotal)
+                    break;
+                if (!locked && !(locked = lock.tryLock()))
+                    break;
+                if (casWorkerCounts(s, workerCountsFor(tc+1, rc+1))) {
+                    createAndStartSpare(tc);
+                    success = true;
+                    break;
+                }
+            }
+        } finally {
+            if (locked)
+                lock.unlock();
+        }
+        return success;
+    }
+
+    /**
+     * Adds the kth spare worker. On entry, pool counts are already
+     * adjusted to reflect addition.
+     */
+    private void createAndStartSpare(int k) {
+        ForkJoinWorkerThread w = null;
+        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(k + 1);
+        int len = ws.length;
+        // Probably, we can place at slot k. If not, find empty slot
+        if (k < len && ws[k] != null) {
+            for (k = 0; k < len && ws[k] != null; ++k)
+                ;
+        }
+        if (k < len && isProcessingTasks() && (w = createWorker(k)) != null) {
+            ws[k] = w;
+            w.start();
+        }
+        else
+            updateWorkerCount(-1); // adjust on failure
+        signalIdleWorkers();
+    }
+
+    /**
+     * Suspends calling thread w if there are excess threads.  Called
+     * only from sync.  Spares are enqueued in a Treiber stack using
+     * the same WaitQueueNodes as barriers.  They are resumed mainly
+     * in preJoin, but are also woken on pool events that require all
+     * threads to check run state.
+     *
+     * @param w the caller
+     */
+    private boolean suspendIfSpare(ForkJoinWorkerThread w) {
+        WaitQueueNode node = null;
+        int s;
+        while (parallelism < runningCountOf(s = workerCounts)) {
+            if (node == null)
+                node = new WaitQueueNode(0, w);
+            if (casWorkerCounts(s, s-1)) { // representation-dependent
+                // push onto stack
+                do {} while (!casSpareStack(node.next = spareStack, node));
+                // block until released by resumeSpare
+                node.awaitSpareRelease();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tries to pop and resume a spare thread.
+     *
+     * @param updateCount if true, increment running count on success
+     * @return true if successful
+     */
+    private boolean tryResumeSpare(boolean updateCount) {
+        WaitQueueNode q;
+        while ((q = spareStack) != null) {
+            if (casSpareStack(q, q.next)) {
+                if (updateCount)
+                    updateRunningCount(1);
+                q.signal();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Pops and resumes all spare threads. Same idea as ensureSync.
+     *
+     * @return true if any spares released
+     */
+    private boolean resumeAllSpares() {
+        WaitQueueNode q;
+        while ( (q = spareStack) != null) {
+            if (casSpareStack(q, null)) {
+                do {
+                    updateRunningCount(1);
+                    q.signal();
+                } while ((q = q.next) != null);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Pops and shuts down excessive spare threads. Call only while
+     * holding lock. This is not guaranteed to eliminate all excess
+     * threads, only those suspended as spares, which are the ones
+     * unlikely to be needed in the future.
+     */
+    private void trimSpares() {
+        int surplus = totalCountOf(workerCounts) - parallelism;
+        WaitQueueNode q;
+        while (surplus > 0 && (q = spareStack) != null) {
+            if (casSpareStack(q, null)) {
+                do {
+                    updateRunningCount(1);
+                    ForkJoinWorkerThread w = q.thread;
+                    if (w != null && surplus > 0 &&
+                        runningCountOf(workerCounts) > 0 && w.shutdown())
+                        --surplus;
+                    q.signal();
+                } while ((q = q.next) != null);
+            }
+        }
+    }
+
+    /**
+     * Interface for extending managed parallelism for tasks running
+     * in {@link ForkJoinPool}s.
+     *
+     * <p>A {@code ManagedBlocker} provides two methods.
+     * Method {@code isReleasable} must return {@code true} if
+     * blocking is not necessary. Method {@code block} blocks the
+     * current thread if necessary (perhaps internally invoking
+     * {@code isReleasable} before actually blocking).
+     *
+     * <p>For example, here is a ManagedBlocker based on a
+     * ReentrantLock:
+     *  <pre> {@code
+     * class ManagedLocker implements ManagedBlocker {
+     *   final ReentrantLock lock;
+     *   boolean hasLock = false;
+     *   ManagedLocker(ReentrantLock lock) { this.lock = lock; }
+     *   public boolean block() {
+     *     if (!hasLock)
+     *       lock.lock();
+     *     return true;
+     *   }
+     *   public boolean isReleasable() {
+     *     return hasLock || (hasLock = lock.tryLock());
+     *   }
+     * }}</pre>
+     */
+    public static interface ManagedBlocker {
+        /**
+         * Possibly blocks the current thread, for example waiting for
+         * a lock or condition.
+         *
+         * @return {@code true} if no additional blocking is necessary
+         * (i.e., if isReleasable would return true)
+         * @throws InterruptedException if interrupted while waiting
+         * (the method is not required to do so, but is allowed to)
+         */
+        boolean block() throws InterruptedException;
+
+        /**
+         * Returns {@code true} if blocking is unnecessary.
+         */
+        boolean isReleasable();
+    }
+
+    /**
+     * Blocks in accord with the given blocker.  If the current thread
+     * is a {@link ForkJoinWorkerThread}, this method possibly
+     * arranges for a spare thread to be activated if necessary to
+     * ensure parallelism while the current thread is blocked.
+     *
+     * <p>If {@code maintainParallelism} is {@code true} and the pool
+     * supports it ({@link #getMaintainsParallelism}), this method
+     * attempts to maintain the pool's nominal parallelism. Otherwise
+     * it activates a thread only if necessary to avoid complete
+     * starvation. This option may be preferable when blockages use
+     * timeouts, or are almost always brief.
+     *
+     * <p>If the caller is not a {@link ForkJoinTask}, this method is
+     * behaviorally equivalent to
+     *  <pre> {@code
+     * while (!blocker.isReleasable())
+     *   if (blocker.block())
+     *     return;
+     * }</pre>
+     *
+     * If the caller is a {@code ForkJoinTask}, then the pool may
+     * first be expanded to ensure parallelism, and later adjusted.
+     *
+     * @param blocker the blocker
+     * @param maintainParallelism if {@code true} and supported by
+     * this pool, attempt to maintain the pool's nominal parallelism;
+     * otherwise activate a thread only if necessary to avoid
+     * complete starvation.
+     * @throws InterruptedException if blocker.block did so
+     */
+    public static void managedBlock(ManagedBlocker blocker,
+                                    boolean maintainParallelism)
+        throws InterruptedException {
+        Thread t = Thread.currentThread();
+        ForkJoinPool pool = ((t instanceof ForkJoinWorkerThread) ?
+                             ((ForkJoinWorkerThread) t).pool : null);
+        if (!blocker.isReleasable()) {
+            try {
+                if (pool == null ||
+                    !pool.preBlock(blocker, maintainParallelism))
+                    awaitBlocker(blocker);
+            } finally {
+                if (pool != null)
+                    pool.updateRunningCount(1);
+            }
+        }
+    }
+
+    private static void awaitBlocker(ManagedBlocker blocker)
+        throws InterruptedException {
+        do {} while (!blocker.isReleasable() && !blocker.block());
+    }
+
+    // AbstractExecutorService overrides.  These rely on undocumented
+    // fact that ForkJoinTask.adapt returns ForkJoinTasks that also
+    // implement RunnableFuture.
+
+    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+        return (RunnableFuture<T>) ForkJoinTask.adapt(runnable, value);
+    }
+
+    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
+        return (RunnableFuture<T>) ForkJoinTask.adapt(callable);
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long eventCountOffset =
+        objectFieldOffset("eventCount", ForkJoinPool.class);
+    private static final long workerCountsOffset =
+        objectFieldOffset("workerCounts", ForkJoinPool.class);
+    private static final long runControlOffset =
+        objectFieldOffset("runControl", ForkJoinPool.class);
+    private static final long syncStackOffset =
+        objectFieldOffset("syncStack",ForkJoinPool.class);
+    private static final long spareStackOffset =
+        objectFieldOffset("spareStack", ForkJoinPool.class);
+
+    private boolean casEventCount(long cmp, long val) {
+        return UNSAFE.compareAndSwapLong(this, eventCountOffset, cmp, val);
+    }
+    private boolean casWorkerCounts(int cmp, int val) {
+        return UNSAFE.compareAndSwapInt(this, workerCountsOffset, cmp, val);
+    }
+    private boolean casRunControl(int cmp, int val) {
+        return UNSAFE.compareAndSwapInt(this, runControlOffset, cmp, val);
+    }
+    private boolean casSpareStack(WaitQueueNode cmp, WaitQueueNode val) {
+        return UNSAFE.compareAndSwapObject(this, spareStackOffset, cmp, val);
+    }
+    private boolean casBarrierStack(WaitQueueNode cmp, WaitQueueNode val) {
+        return UNSAFE.compareAndSwapObject(this, syncStackOffset, cmp, val);
+    }
+
+    private static long objectFieldOffset(String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,1292 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.RandomAccess;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * Abstract base class for tasks that run within a {@link ForkJoinPool}.
+ * A {@code ForkJoinTask} is a thread-like entity that is much
+ * lighter weight than a normal thread.  Huge numbers of tasks and
+ * subtasks may be hosted by a small number of actual threads in a
+ * ForkJoinPool, at the price of some usage limitations.
+ *
+ * <p>A "main" {@code ForkJoinTask} begins execution when submitted
+ * to a {@link ForkJoinPool}.  Once started, it will usually in turn
+ * start other subtasks.  As indicated by the name of this class,
+ * many programs using {@code ForkJoinTask} employ only methods
+ * {@link #fork} and {@link #join}, or derivatives such as {@link
+ * #invokeAll}.  However, this class also provides a number of other
+ * methods that can come into play in advanced usages, as well as
+ * extension mechanics that allow support of new forms of fork/join
+ * processing.
+ *
+ * <p>A {@code ForkJoinTask} is a lightweight form of {@link Future}.
+ * The efficiency of {@code ForkJoinTask}s stems from a set of
+ * restrictions (that are only partially statically enforceable)
+ * reflecting their intended use as computational tasks calculating
+ * pure functions or operating on purely isolated objects.  The
+ * primary coordination mechanisms are {@link #fork}, that arranges
+ * asynchronous execution, and {@link #join}, that doesn't proceed
+ * until the task's result has been computed.  Computations should
+ * avoid {@code synchronized} methods or blocks, and should minimize
+ * other blocking synchronization apart from joining other tasks or
+ * using synchronizers such as Phasers that are advertised to
+ * cooperate with fork/join scheduling. Tasks should also not perform
+ * blocking IO, and should ideally access variables that are
+ * completely independent of those accessed by other running
+ * tasks. Minor breaches of these restrictions, for example using
+ * shared output streams, may be tolerable in practice, but frequent
+ * use may result in poor performance, and the potential to
+ * indefinitely stall if the number of threads not waiting for IO or
+ * other external synchronization becomes exhausted. This usage
+ * restriction is in part enforced by not permitting checked
+ * exceptions such as {@code IOExceptions} to be thrown. However,
+ * computations may still encounter unchecked exceptions, that are
+ * rethrown to callers attempting to join them. These exceptions may
+ * additionally include {@link RejectedExecutionException} stemming
+ * from internal resource exhaustion, such as failure to allocate
+ * internal task queues.
+ *
+ * <p>The primary method for awaiting completion and extracting
+ * results of a task is {@link #join}, but there are several variants:
+ * The {@link Future#get} methods support interruptible and/or timed
+ * waits for completion and report results using {@code Future}
+ * conventions. Method {@link #helpJoin} enables callers to actively
+ * execute other tasks while awaiting joins, which is sometimes more
+ * efficient but only applies when all subtasks are known to be
+ * strictly tree-structured. Method {@link #invoke} is semantically
+ * equivalent to {@code fork(); join()} but always attempts to begin
+ * execution in the current thread. The "<em>quiet</em>" forms of
+ * these methods do not extract results or report exceptions. These
+ * may be useful when a set of tasks are being executed, and you need
+ * to delay processing of results or exceptions until all complete.
+ * Method {@code invokeAll} (available in multiple versions)
+ * performs the most common form of parallel invocation: forking a set
+ * of tasks and joining them all.
+ *
+ * <p>The execution status of tasks may be queried at several levels
+ * of detail: {@link #isDone} is true if a task completed in any way
+ * (including the case where a task was cancelled without executing);
+ * {@link #isCompletedNormally} is true if a task completed without
+ * cancellation or encountering an exception; {@link #isCancelled} is
+ * true if the task was cancelled (in which case {@link #getException}
+ * returns a {@link java.util.concurrent.CancellationException}); and
+ * {@link #isCompletedAbnormally} is true if a task was either
+ * cancelled or encountered an exception, in which case {@link
+ * #getException} will return either the encountered exception or
+ * {@link java.util.concurrent.CancellationException}.
+ *
+ * <p>The ForkJoinTask class is not usually directly subclassed.
+ * Instead, you subclass one of the abstract classes that support a
+ * particular style of fork/join processing, typically {@link
+ * RecursiveAction} for computations that do not return results, or
+ * {@link RecursiveTask} for those that do.  Normally, a concrete
+ * ForkJoinTask subclass declares fields comprising its parameters,
+ * established in a constructor, and then defines a {@code compute}
+ * method that somehow uses the control methods supplied by this base
+ * class. While these methods have {@code public} access (to allow
+ * instances of different task subclasses to call each other's
+ * methods), some of them may only be called from within other
+ * ForkJoinTasks (as may be determined using method {@link
+ * #inForkJoinPool}).  Attempts to invoke them in other contexts
+ * result in exceptions or errors, possibly including
+ * ClassCastException.
+ *
+ * <p>Most base support methods are {@code final}, to prevent
+ * overriding of implementations that are intrinsically tied to the
+ * underlying lightweight task scheduling framework.  Developers
+ * creating new basic styles of fork/join processing should minimally
+ * implement {@code protected} methods {@link #exec}, {@link
+ * #setRawResult}, and {@link #getRawResult}, while also introducing
+ * an abstract computational method that can be implemented in its
+ * subclasses, possibly relying on other {@code protected} methods
+ * provided by this class.
+ *
+ * <p>ForkJoinTasks should perform relatively small amounts of
+ * computation. Large tasks should be split into smaller subtasks,
+ * usually via recursive decomposition. As a very rough rule of thumb,
+ * a task should perform more than 100 and less than 10000 basic
+ * computational steps. If tasks are too big, then parallelism cannot
+ * improve throughput. If too small, then memory and internal task
+ * maintenance overhead may overwhelm processing.
+ *
+ * <p>This class provides {@code adapt} methods for {@link Runnable}
+ * and {@link Callable}, that may be of use when mixing execution of
+ * {@code ForkJoinTasks} with other kinds of tasks. When all tasks
+ * are of this form, consider using a pool in
+ * {@linkplain ForkJoinPool#setAsyncMode async mode}.
+ *
+ * <p>ForkJoinTasks are {@code Serializable}, which enables them to be
+ * used in extensions such as remote execution frameworks. It is
+ * sensible to serialize tasks only before or after, but not during,
+ * execution. Serialization is not relied on during execution itself.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
+
+    /**
+     * Run control status bits packed into a single int to minimize
+     * footprint and to ensure atomicity (via CAS).  Status is
+     * initially zero, and takes on nonnegative values until
+     * completed, upon which status holds COMPLETED. CANCELLED, or
+     * EXCEPTIONAL, which use the top 3 bits.  Tasks undergoing
+     * blocking waits by other threads have SIGNAL_MASK bits set --
+     * bit 15 for external (nonFJ) waits, and the rest a count of
+     * waiting FJ threads.  (This representation relies on
+     * ForkJoinPool max thread limits). Completion of a stolen task
+     * with SIGNAL_MASK bits set awakens waiter via notifyAll. Even
+     * though suboptimal for some purposes, we use basic builtin
+     * wait/notify to take advantage of "monitor inflation" in JVMs
+     * that we would otherwise need to emulate to avoid adding further
+     * per-task bookkeeping overhead. Note that bits 16-28 are
+     * currently unused. Also value 0x80000000 is available as spare
+     * completion value.
+     */
+    volatile int status; // accessed directly by pool and workers
+
+    static final int COMPLETION_MASK      = 0xe0000000;
+    static final int NORMAL               = 0xe0000000; // == mask
+    static final int CANCELLED            = 0xc0000000;
+    static final int EXCEPTIONAL          = 0xa0000000;
+    static final int SIGNAL_MASK          = 0x0000ffff;
+    static final int INTERNAL_SIGNAL_MASK = 0x00007fff;
+    static final int EXTERNAL_SIGNAL      = 0x00008000; // top bit of low word
+
+    /**
+     * Table of exceptions thrown by tasks, to enable reporting by
+     * callers. Because exceptions are rare, we don't directly keep
+     * them with task objects, but instead use a weak ref table.  Note
+     * that cancellation exceptions don't appear in the table, but are
+     * instead recorded as status values.
+     * TODO: Use ConcurrentReferenceHashMap
+     */
+    static final Map<ForkJoinTask<?>, Throwable> exceptionMap =
+        Collections.synchronizedMap
+        (new WeakHashMap<ForkJoinTask<?>, Throwable>());
+
+    // within-package utilities
+
+    /**
+     * Gets current worker thread, or null if not a worker thread.
+     */
+    static ForkJoinWorkerThread getWorker() {
+        Thread t = Thread.currentThread();
+        return ((t instanceof ForkJoinWorkerThread) ?
+                (ForkJoinWorkerThread) t : null);
+    }
+
+    final boolean casStatus(int cmp, int val) {
+        return UNSAFE.compareAndSwapInt(this, statusOffset, cmp, val);
+    }
+
+    /**
+     * Workaround for not being able to rethrow unchecked exceptions.
+     */
+    static void rethrowException(Throwable ex) {
+        if (ex != null)
+            UNSAFE.throwException(ex);
+    }
+
+    // Setting completion status
+
+    /**
+     * Marks completion and wakes up threads waiting to join this task.
+     *
+     * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
+     */
+    final void setCompletion(int completion) {
+        ForkJoinPool pool = getPool();
+        if (pool != null) {
+            int s; // Clear signal bits while setting completion status
+            do {} while ((s = status) >= 0 && !casStatus(s, completion));
+
+            if ((s & SIGNAL_MASK) != 0) {
+                if ((s &= INTERNAL_SIGNAL_MASK) != 0)
+                    pool.updateRunningCount(s);
+                synchronized (this) { notifyAll(); }
+            }
+        }
+        else
+            externallySetCompletion(completion);
+    }
+
+    /**
+     * Version of setCompletion for non-FJ threads.  Leaves signal
+     * bits for unblocked threads to adjust, and always notifies.
+     */
+    private void externallySetCompletion(int completion) {
+        int s;
+        do {} while ((s = status) >= 0 &&
+                     !casStatus(s, (s & SIGNAL_MASK) | completion));
+        synchronized (this) { notifyAll(); }
+    }
+
+    /**
+     * Sets status to indicate normal completion.
+     */
+    final void setNormalCompletion() {
+        // Try typical fast case -- single CAS, no signal, not already done.
+        // Manually expand casStatus to improve chances of inlining it
+        if (!UNSAFE.compareAndSwapInt(this, statusOffset, 0, NORMAL))
+            setCompletion(NORMAL);
+    }
+
+    // internal waiting and notification
+
+    /**
+     * Performs the actual monitor wait for awaitDone.
+     */
+    private void doAwaitDone() {
+        // Minimize lock bias and in/de-flation effects by maximizing
+        // chances of waiting inside sync
+        try {
+            while (status >= 0)
+                synchronized (this) { if (status >= 0) wait(); }
+        } catch (InterruptedException ie) {
+            onInterruptedWait();
+        }
+    }
+
+    /**
+     * Performs the actual timed monitor wait for awaitDone.
+     */
+    private void doAwaitDone(long startTime, long nanos) {
+        synchronized (this) {
+            try {
+                while (status >= 0) {
+                    long nt = nanos - (System.nanoTime() - startTime);
+                    if (nt <= 0)
+                        break;
+                    wait(nt / 1000000, (int) (nt % 1000000));
+                }
+            } catch (InterruptedException ie) {
+                onInterruptedWait();
+            }
+        }
+    }
+
+    // Awaiting completion
+
+    /**
+     * Sets status to indicate there is joiner, then waits for join,
+     * surrounded with pool notifications.
+     *
+     * @return status upon exit
+     */
+    private int awaitDone(ForkJoinWorkerThread w,
+                          boolean maintainParallelism) {
+        ForkJoinPool pool = (w == null) ? null : w.pool;
+        int s;
+        while ((s = status) >= 0) {
+            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
+                if (pool == null || !pool.preJoin(this, maintainParallelism))
+                    doAwaitDone();
+                if (((s = status) & INTERNAL_SIGNAL_MASK) != 0)
+                    adjustPoolCountsOnUnblock(pool);
+                break;
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Timed version of awaitDone
+     *
+     * @return status upon exit
+     */
+    private int awaitDone(ForkJoinWorkerThread w, long nanos) {
+        ForkJoinPool pool = (w == null) ? null : w.pool;
+        int s;
+        while ((s = status) >= 0) {
+            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
+                long startTime = System.nanoTime();
+                if (pool == null || !pool.preJoin(this, false))
+                    doAwaitDone(startTime, nanos);
+                if ((s = status) >= 0) {
+                    adjustPoolCountsOnCancelledWait(pool);
+                    s = status;
+                }
+                if (s < 0 && (s & INTERNAL_SIGNAL_MASK) != 0)
+                    adjustPoolCountsOnUnblock(pool);
+                break;
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Notifies pool that thread is unblocked. Called by signalled
+     * threads when woken by non-FJ threads (which is atypical).
+     */
+    private void adjustPoolCountsOnUnblock(ForkJoinPool pool) {
+        int s;
+        do {} while ((s = status) < 0 && !casStatus(s, s & COMPLETION_MASK));
+        if (pool != null && (s &= INTERNAL_SIGNAL_MASK) != 0)
+            pool.updateRunningCount(s);
+    }
+
+    /**
+     * Notifies pool to adjust counts on cancelled or timed out wait.
+     */
+    private void adjustPoolCountsOnCancelledWait(ForkJoinPool pool) {
+        if (pool != null) {
+            int s;
+            while ((s = status) >= 0 && (s & INTERNAL_SIGNAL_MASK) != 0) {
+                if (casStatus(s, s - 1)) {
+                    pool.updateRunningCount(1);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles interruptions during waits.
+     */
+    private void onInterruptedWait() {
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null)
+            Thread.currentThread().interrupt(); // re-interrupt
+        else if (w.isTerminating())
+            cancelIgnoringExceptions();
+        // else if FJworker, ignore interrupt
+    }
+
+    // Recording and reporting exceptions
+
+    private void setDoneExceptionally(Throwable rex) {
+        exceptionMap.put(this, rex);
+        setCompletion(EXCEPTIONAL);
+    }
+
+    /**
+     * Throws the exception associated with status s.
+     *
+     * @throws the exception
+     */
+    private void reportException(int s) {
+        if ((s &= COMPLETION_MASK) < NORMAL) {
+            if (s == CANCELLED)
+                throw new CancellationException();
+            else
+                rethrowException(exceptionMap.get(this));
+        }
+    }
+
+    /**
+     * Returns result or throws exception using j.u.c.Future conventions.
+     * Only call when {@code isDone} known to be true or thread known
+     * to be interrupted.
+     */
+    private V reportFutureResult()
+        throws InterruptedException, ExecutionException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        int s = status & COMPLETION_MASK;
+        if (s < NORMAL) {
+            Throwable ex;
+            if (s == CANCELLED)
+                throw new CancellationException();
+            if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+                throw new ExecutionException(ex);
+        }
+        return getRawResult();
+    }
+
+    /**
+     * Returns result or throws exception using j.u.c.Future conventions
+     * with timeouts.
+     */
+    private V reportTimedFutureResult()
+        throws InterruptedException, ExecutionException, TimeoutException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        Throwable ex;
+        int s = status & COMPLETION_MASK;
+        if (s == NORMAL)
+            return getRawResult();
+        else if (s == CANCELLED)
+            throw new CancellationException();
+        else if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+            throw new ExecutionException(ex);
+        else
+            throw new TimeoutException();
+    }
+
+    // internal execution methods
+
+    /**
+     * Calls exec, recording completion, and rethrowing exception if
+     * encountered. Caller should normally check status before calling.
+     *
+     * @return true if completed normally
+     */
+    private boolean tryExec() {
+        try { // try block must contain only call to exec
+            if (!exec())
+                return false;
+        } catch (Throwable rex) {
+            setDoneExceptionally(rex);
+            rethrowException(rex);
+            return false; // not reached
+        }
+        setNormalCompletion();
+        return true;
+    }
+
+    /**
+     * Main execution method used by worker threads. Invokes
+     * base computation unless already complete.
+     */
+    final void quietlyExec() {
+        if (status >= 0) {
+            try {
+                if (!exec())
+                    return;
+            } catch (Throwable rex) {
+                setDoneExceptionally(rex);
+                return;
+            }
+            setNormalCompletion();
+        }
+    }
+
+    /**
+     * Calls exec(), recording but not rethrowing exception.
+     * Caller should normally check status before calling.
+     *
+     * @return true if completed normally
+     */
+    private boolean tryQuietlyInvoke() {
+        try {
+            if (!exec())
+                return false;
+        } catch (Throwable rex) {
+            setDoneExceptionally(rex);
+            return false;
+        }
+        setNormalCompletion();
+        return true;
+    }
+
+    /**
+     * Cancels, ignoring any exceptions it throws.
+     */
+    final void cancelIgnoringExceptions() {
+        try {
+            cancel(false);
+        } catch (Throwable ignore) {
+        }
+    }
+
+    /**
+     * Main implementation of helpJoin
+     */
+    private int busyJoin(ForkJoinWorkerThread w) {
+        int s;
+        ForkJoinTask<?> t;
+        while ((s = status) >= 0 && (t = w.scanWhileJoining(this)) != null)
+            t.quietlyExec();
+        return (s >= 0) ? awaitDone(w, false) : s; // block if no work
+    }
+
+    // public methods
+
+    /**
+     * Arranges to asynchronously execute this task.  While it is not
+     * necessarily enforced, it is a usage error to fork a task more
+     * than once unless it has completed and been reinitialized.
+     * Subsequent modifications to the state of this task or any data
+     * it operates on are not necessarily consistently observable by
+     * any thread other than the one executing it unless preceded by a
+     * call to {@link #join} or related methods, or a call to {@link
+     * #isDone} returning {@code true}.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return {@code this}, to simplify usage
+     */
+    public final ForkJoinTask<V> fork() {
+        ((ForkJoinWorkerThread) Thread.currentThread())
+            .pushTask(this);
+        return this;
+    }
+
+    /**
+     * Returns the result of the computation when it {@link #isDone is done}.
+     * This method differs from {@link #get()} in that
+     * abnormal completion results in {@code RuntimeException} or
+     * {@code Error}, not {@code ExecutionException}.
+     *
+     * @return the computed result
+     */
+    public final V join() {
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null || status < 0 || !w.unpushTask(this) || !tryExec())
+            reportException(awaitDone(w, true));
+        return getRawResult();
+    }
+
+    /**
+     * Commences performing this task, awaits its completion if
+     * necessary, and return its result, or throws an (unchecked)
+     * exception if the underlying computation did so.
+     *
+     * @return the computed result
+     */
+    public final V invoke() {
+        if (status >= 0 && tryExec())
+            return getRawResult();
+        else
+            return join();
+    }
+
+    /**
+     * Forks the given tasks, returning when {@code isDone} holds for
+     * each task or an (unchecked) exception is encountered, in which
+     * case the exception is rethrown.  If either task encounters an
+     * exception, the other one may be, but is not guaranteed to be,
+     * cancelled.  If both tasks throw an exception, then this method
+     * throws one of them.  The individual status of each task may be
+     * checked using {@link #getException()} and related methods.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @param t1 the first task
+     * @param t2 the second task
+     * @throws NullPointerException if any task is null
+     */
+    public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
+        t2.fork();
+        t1.invoke();
+        t2.join();
+    }
+
+    /**
+     * Forks the given tasks, returning when {@code isDone} holds for
+     * each task or an (unchecked) exception is encountered, in which
+     * case the exception is rethrown. If any task encounters an
+     * exception, others may be, but are not guaranteed to be,
+     * cancelled.  If more than one task encounters an exception, then
+     * this method throws any one of these exceptions.  The individual
+     * status of each task may be checked using {@link #getException()}
+     * and related methods.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @param tasks the tasks
+     * @throws NullPointerException if any task is null
+     */
+    public static void invokeAll(ForkJoinTask<?>... tasks) {
+        Throwable ex = null;
+        int last = tasks.length - 1;
+        for (int i = last; i >= 0; --i) {
+            ForkJoinTask<?> t = tasks[i];
+            if (t == null) {
+                if (ex == null)
+                    ex = new NullPointerException();
+            }
+            else if (i != 0)
+                t.fork();
+            else {
+                t.quietlyInvoke();
+                if (ex == null)
+                    ex = t.getException();
+            }
+        }
+        for (int i = 1; i <= last; ++i) {
+            ForkJoinTask<?> t = tasks[i];
+            if (t != null) {
+                if (ex != null)
+                    t.cancel(false);
+                else {
+                    t.quietlyJoin();
+                    if (ex == null)
+                        ex = t.getException();
+                }
+            }
+        }
+        if (ex != null)
+            rethrowException(ex);
+    }
+
+    /**
+     * Forks all tasks in the specified collection, returning when
+     * {@code isDone} holds for each task or an (unchecked) exception
+     * is encountered.  If any task encounters an exception, others
+     * may be, but are not guaranteed to be, cancelled.  If more than
+     * one task encounters an exception, then this method throws any
+     * one of these exceptions.  The individual status of each task
+     * may be checked using {@link #getException()} and related
+     * methods.  The behavior of this operation is undefined if the
+     * specified collection is modified while the operation is in
+     * progress.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @param tasks the collection of tasks
+     * @return the tasks argument, to simplify usage
+     * @throws NullPointerException if tasks or any element are null
+     */
+    public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
+        if (!(tasks instanceof RandomAccess) || !(tasks instanceof List<?>)) {
+            invokeAll(tasks.toArray(new ForkJoinTask<?>[tasks.size()]));
+            return tasks;
+        }
+        @SuppressWarnings("unchecked")
+        List<? extends ForkJoinTask<?>> ts =
+            (List<? extends ForkJoinTask<?>>) tasks;
+        Throwable ex = null;
+        int last = ts.size() - 1;
+        for (int i = last; i >= 0; --i) {
+            ForkJoinTask<?> t = ts.get(i);
+            if (t == null) {
+                if (ex == null)
+                    ex = new NullPointerException();
+            }
+            else if (i != 0)
+                t.fork();
+            else {
+                t.quietlyInvoke();
+                if (ex == null)
+                    ex = t.getException();
+            }
+        }
+        for (int i = 1; i <= last; ++i) {
+            ForkJoinTask<?> t = ts.get(i);
+            if (t != null) {
+                if (ex != null)
+                    t.cancel(false);
+                else {
+                    t.quietlyJoin();
+                    if (ex == null)
+                        ex = t.getException();
+                }
+            }
+        }
+        if (ex != null)
+            rethrowException(ex);
+        return tasks;
+    }
+
+    /**
+     * Attempts to cancel execution of this task. This attempt will
+     * fail if the task has already completed, has already been
+     * cancelled, or could not be cancelled for some other reason. If
+     * successful, and this task has not started when cancel is
+     * called, execution of this task is suppressed, {@link
+     * #isCancelled} will report true, and {@link #join} will result
+     * in a {@code CancellationException} being thrown.
+     *
+     * <p>This method may be overridden in subclasses, but if so, must
+     * still ensure that these minimal properties hold. In particular,
+     * the {@code cancel} method itself must not throw exceptions.
+     *
+     * <p>This method is designed to be invoked by <em>other</em>
+     * tasks. To terminate the current task, you can just return or
+     * throw an unchecked exception from its computation method, or
+     * invoke {@link #completeExceptionally}.
+     *
+     * @param mayInterruptIfRunning this value is ignored in the
+     * default implementation because tasks are not
+     * cancelled via interruption
+     *
+     * @return {@code true} if this task is now cancelled
+     */
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        setCompletion(CANCELLED);
+        return (status & COMPLETION_MASK) == CANCELLED;
+    }
+
+    public final boolean isDone() {
+        return status < 0;
+    }
+
+    public final boolean isCancelled() {
+        return (status & COMPLETION_MASK) == CANCELLED;
+    }
+
+    /**
+     * Returns {@code true} if this task threw an exception or was cancelled.
+     *
+     * @return {@code true} if this task threw an exception or was cancelled
+     */
+    public final boolean isCompletedAbnormally() {
+        return (status & COMPLETION_MASK) < NORMAL;
+    }
+
+    /**
+     * Returns {@code true} if this task completed without throwing an
+     * exception and was not cancelled.
+     *
+     * @return {@code true} if this task completed without throwing an
+     * exception and was not cancelled
+     */
+    public final boolean isCompletedNormally() {
+        return (status & COMPLETION_MASK) == NORMAL;
+    }
+
+    /**
+     * Returns the exception thrown by the base computation, or a
+     * {@code CancellationException} if cancelled, or {@code null} if
+     * none or if the method has not yet completed.
+     *
+     * @return the exception, or {@code null} if none
+     */
+    public final Throwable getException() {
+        int s = status & COMPLETION_MASK;
+        return ((s >= NORMAL)    ? null :
+                (s == CANCELLED) ? new CancellationException() :
+                exceptionMap.get(this));
+    }
+
+    /**
+     * Completes this task abnormally, and if not already aborted or
+     * cancelled, causes it to throw the given exception upon
+     * {@code join} and related operations. This method may be used
+     * to induce exceptions in asynchronous tasks, or to force
+     * completion of tasks that would not otherwise complete.  Its use
+     * in other situations is discouraged.  This method is
+     * overridable, but overridden versions must invoke {@code super}
+     * implementation to maintain guarantees.
+     *
+     * @param ex the exception to throw. If this exception is not a
+     * {@code RuntimeException} or {@code Error}, the actual exception
+     * thrown will be a {@code RuntimeException} with cause {@code ex}.
+     */
+    public void completeExceptionally(Throwable ex) {
+        setDoneExceptionally((ex instanceof RuntimeException) ||
+                             (ex instanceof Error) ? ex :
+                             new RuntimeException(ex));
+    }
+
+    /**
+     * Completes this task, and if not already aborted or cancelled,
+     * returning a {@code null} result upon {@code join} and related
+     * operations. This method may be used to provide results for
+     * asynchronous tasks, or to provide alternative handling for
+     * tasks that would not otherwise complete normally. Its use in
+     * other situations is discouraged. This method is
+     * overridable, but overridden versions must invoke {@code super}
+     * implementation to maintain guarantees.
+     *
+     * @param value the result value for this task
+     */
+    public void complete(V value) {
+        try {
+            setRawResult(value);
+        } catch (Throwable rex) {
+            setDoneExceptionally(rex);
+            return;
+        }
+        setNormalCompletion();
+    }
+
+    public final V get() throws InterruptedException, ExecutionException {
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
+            awaitDone(w, true);
+        return reportFutureResult();
+    }
+
+    public final V get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        long nanos = unit.toNanos(timeout);
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
+            awaitDone(w, nanos);
+        return reportTimedFutureResult();
+    }
+
+    /**
+     * Possibly executes other tasks until this task {@link #isDone is
+     * done}, then returns the result of the computation.  This method
+     * may be more efficient than {@code join}, but is only applicable
+     * when there are no potential dependencies between continuation
+     * of the current task and that of any other task that might be
+     * executed while helping. (This usually holds for pure
+     * divide-and-conquer tasks).
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the computed result
+     */
+    public final V helpJoin() {
+        ForkJoinWorkerThread w = (ForkJoinWorkerThread) Thread.currentThread();
+        if (status < 0 || !w.unpushTask(this) || !tryExec())
+            reportException(busyJoin(w));
+        return getRawResult();
+    }
+
+    /**
+     * Possibly executes other tasks until this task {@link #isDone is
+     * done}.  This method may be useful when processing collections
+     * of tasks when some have been cancelled or otherwise known to
+     * have aborted.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     */
+    public final void quietlyHelpJoin() {
+        if (status >= 0) {
+            ForkJoinWorkerThread w =
+                (ForkJoinWorkerThread) Thread.currentThread();
+            if (!w.unpushTask(this) || !tryQuietlyInvoke())
+                busyJoin(w);
+        }
+    }
+
+    /**
+     * Joins this task, without returning its result or throwing an
+     * exception. This method may be useful when processing
+     * collections of tasks when some have been cancelled or otherwise
+     * known to have aborted.
+     */
+    public final void quietlyJoin() {
+        if (status >= 0) {
+            ForkJoinWorkerThread w = getWorker();
+            if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
+                awaitDone(w, true);
+        }
+    }
+
+    /**
+     * Commences performing this task and awaits its completion if
+     * necessary, without returning its result or throwing an
+     * exception. This method may be useful when processing
+     * collections of tasks when some have been cancelled or otherwise
+     * known to have aborted.
+     */
+    public final void quietlyInvoke() {
+        if (status >= 0 && !tryQuietlyInvoke())
+            quietlyJoin();
+    }
+
+    /**
+     * Possibly executes tasks until the pool hosting the current task
+     * {@link ForkJoinPool#isQuiescent is quiescent}. This method may
+     * be of use in designs in which many tasks are forked, but none
+     * are explicitly joined, instead executing them until all are
+     * processed.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     */
+    public static void helpQuiesce() {
+        ((ForkJoinWorkerThread) Thread.currentThread())
+            .helpQuiescePool();
+    }
+
+    /**
+     * Resets the internal bookkeeping state of this task, allowing a
+     * subsequent {@code fork}. This method allows repeated reuse of
+     * this task, but only if reuse occurs when this task has either
+     * never been forked, or has been forked, then completed and all
+     * outstanding joins of this task have also completed. Effects
+     * under any other usage conditions are not guaranteed.
+     * This method may be useful when executing
+     * pre-constructed trees of subtasks in loops.
+     */
+    public void reinitialize() {
+        if ((status & COMPLETION_MASK) == EXCEPTIONAL)
+            exceptionMap.remove(this);
+        status = 0;
+    }
+
+    /**
+     * Returns the pool hosting the current task execution, or null
+     * if this task is executing outside of any ForkJoinPool.
+     *
+     * @see #inForkJoinPool
+     * @return the pool, or {@code null} if none
+     */
+    public static ForkJoinPool getPool() {
+        Thread t = Thread.currentThread();
+        return (t instanceof ForkJoinWorkerThread) ?
+            ((ForkJoinWorkerThread) t).pool : null;
+    }
+
+    /**
+     * Returns {@code true} if the current thread is executing as a
+     * ForkJoinPool computation.
+     *
+     * @return {@code true} if the current thread is executing as a
+     * ForkJoinPool computation, or false otherwise
+     */
+    public static boolean inForkJoinPool() {
+        return Thread.currentThread() instanceof ForkJoinWorkerThread;
+    }
+
+    /**
+     * Tries to unschedule this task for execution. This method will
+     * typically succeed if this task is the most recently forked task
+     * by the current thread, and has not commenced executing in
+     * another thread.  This method may be useful when arranging
+     * alternative local processing of tasks that could have been, but
+     * were not, stolen.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return {@code true} if unforked
+     */
+    public boolean tryUnfork() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .unpushTask(this);
+    }
+
+    /**
+     * Returns an estimate of the number of tasks that have been
+     * forked by the current worker thread but not yet executed. This
+     * value may be useful for heuristic decisions about whether to
+     * fork other tasks.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the number of tasks
+     */
+    public static int getQueuedTaskCount() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .getQueueSize();
+    }
+
+    /**
+     * Returns an estimate of how many more locally queued tasks are
+     * held by the current worker thread than there are other worker
+     * threads that might steal them.  This value may be useful for
+     * heuristic decisions about whether to fork other tasks. In many
+     * usages of ForkJoinTasks, at steady state, each worker should
+     * aim to maintain a small constant surplus (for example, 3) of
+     * tasks, and to process computations locally if this threshold is
+     * exceeded.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the surplus number of tasks, which may be negative
+     */
+    public static int getSurplusQueuedTaskCount() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .getEstimatedSurplusTaskCount();
+    }
+
+    // Extension methods
+
+    /**
+     * Returns the result that would be returned by {@link #join}, even
+     * if this task completed abnormally, or {@code null} if this task
+     * is not known to have been completed.  This method is designed
+     * to aid debugging, as well as to support extensions. Its use in
+     * any other context is discouraged.
+     *
+     * @return the result, or {@code null} if not completed
+     */
+    public abstract V getRawResult();
+
+    /**
+     * Forces the given value to be returned as a result.  This method
+     * is designed to support extensions, and should not in general be
+     * called otherwise.
+     *
+     * @param value the value
+     */
+    protected abstract void setRawResult(V value);
+
+    /**
+     * Immediately performs the base action of this task.  This method
+     * is designed to support extensions, and should not in general be
+     * called otherwise. The return value controls whether this task
+     * is considered to be done normally. It may return false in
+     * asynchronous actions that require explicit invocations of
+     * {@link #complete} to become joinable. It may also throw an
+     * (unchecked) exception to indicate abnormal exit.
+     *
+     * @return {@code true} if completed normally
+     */
+    protected abstract boolean exec();
+
+    /**
+     * Returns, but does not unschedule or execute, a task queued by
+     * the current thread but not yet executed, if one is immediately
+     * available. There is no guarantee that this task will actually
+     * be polled or executed next. Conversely, this method may return
+     * null even if a task exists but cannot be accessed without
+     * contention with other threads.  This method is designed
+     * primarily to support extensions, and is unlikely to be useful
+     * otherwise.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the next task, or {@code null} if none are available
+     */
+    protected static ForkJoinTask<?> peekNextLocalTask() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .peekTask();
+    }
+
+    /**
+     * Unschedules and returns, without executing, the next task
+     * queued by the current thread but not yet executed.  This method
+     * is designed primarily to support extensions, and is unlikely to
+     * be useful otherwise.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the next task, or {@code null} if none are available
+     */
+    protected static ForkJoinTask<?> pollNextLocalTask() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .pollLocalTask();
+    }
+
+    /**
+     * Unschedules and returns, without executing, the next task
+     * queued by the current thread but not yet executed, if one is
+     * available, or if not available, a task that was forked by some
+     * other thread, if available. Availability may be transient, so a
+     * {@code null} result does not necessarily imply quiescence
+     * of the pool this task is operating in.  This method is designed
+     * primarily to support extensions, and is unlikely to be useful
+     * otherwise.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return a task, or {@code null} if none are available
+     */
+    protected static ForkJoinTask<?> pollTask() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .pollTask();
+    }
+
+    /**
+     * Adaptor for Runnables. This implements RunnableFuture
+     * to be compliant with AbstractExecutorService constraints
+     * when used in ForkJoinPool.
+     */
+    static final class AdaptedRunnable<T> extends ForkJoinTask<T>
+        implements RunnableFuture<T> {
+        final Runnable runnable;
+        final T resultOnCompletion;
+        T result;
+        AdaptedRunnable(Runnable runnable, T result) {
+            if (runnable == null) throw new NullPointerException();
+            this.runnable = runnable;
+            this.resultOnCompletion = result;
+        }
+        public T getRawResult() { return result; }
+        public void setRawResult(T v) { result = v; }
+        public boolean exec() {
+            runnable.run();
+            result = resultOnCompletion;
+            return true;
+        }
+        public void run() { invoke(); }
+        private static final long serialVersionUID = 5232453952276885070L;
+    }
+
+    /**
+     * Adaptor for Callables
+     */
+    static final class AdaptedCallable<T> extends ForkJoinTask<T>
+        implements RunnableFuture<T> {
+        final Callable<? extends T> callable;
+        T result;
+        AdaptedCallable(Callable<? extends T> callable) {
+            if (callable == null) throw new NullPointerException();
+            this.callable = callable;
+        }
+        public T getRawResult() { return result; }
+        public void setRawResult(T v) { result = v; }
+        public boolean exec() {
+            try {
+                result = callable.call();
+                return true;
+            } catch (Error err) {
+                throw err;
+            } catch (RuntimeException rex) {
+                throw rex;
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+        public void run() { invoke(); }
+        private static final long serialVersionUID = 2838392045355241008L;
+    }
+
+    /**
+     * Returns a new {@code ForkJoinTask} that performs the {@code run}
+     * method of the given {@code Runnable} as its action, and returns
+     * a null result upon {@link #join}.
+     *
+     * @param runnable the runnable action
+     * @return the task
+     */
+    public static ForkJoinTask<?> adapt(Runnable runnable) {
+        return new AdaptedRunnable<Void>(runnable, null);
+    }
+
+    /**
+     * Returns a new {@code ForkJoinTask} that performs the {@code run}
+     * method of the given {@code Runnable} as its action, and returns
+     * the given result upon {@link #join}.
+     *
+     * @param runnable the runnable action
+     * @param result the result upon completion
+     * @return the task
+     */
+    public static <T> ForkJoinTask<T> adapt(Runnable runnable, T result) {
+        return new AdaptedRunnable<T>(runnable, result);
+    }
+
+    /**
+     * Returns a new {@code ForkJoinTask} that performs the {@code call}
+     * method of the given {@code Callable} as its action, and returns
+     * its result upon {@link #join}, translating any checked exceptions
+     * encountered into {@code RuntimeException}.
+     *
+     * @param callable the callable action
+     * @return the task
+     */
+    public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) {
+        return new AdaptedCallable<T>(callable);
+    }
+
+    // Serialization support
+
+    private static final long serialVersionUID = -7721805057305804111L;
+
+    /**
+     * Saves the state to a stream.
+     *
+     * @serialData the current run status and the exception thrown
+     * during execution, or {@code null} if none
+     * @param s the stream
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+        throws java.io.IOException {
+        s.defaultWriteObject();
+        s.writeObject(getException());
+    }
+
+    /**
+     * Reconstitutes the instance from a stream.
+     *
+     * @param s the stream
+     */
+    private void readObject(java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        status &= ~INTERNAL_SIGNAL_MASK; // clear internal signal counts
+        status |= EXTERNAL_SIGNAL; // conservatively set external signal
+        Object ex = s.readObject();
+        if (ex != null)
+            setDoneExceptionally((Throwable) ex);
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long statusOffset =
+        objectFieldOffset("status", ForkJoinTask.class);
+
+    private static long objectFieldOffset(String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,827 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.Collection;
+
+/**
+ * A thread managed by a {@link ForkJoinPool}.  This class is
+ * subclassable solely for the sake of adding functionality -- there
+ * are no overridable methods dealing with scheduling or execution.
+ * However, you can override initialization and termination methods
+ * surrounding the main task processing loop.  If you do create such a
+ * subclass, you will also need to supply a custom {@link
+ * ForkJoinPool.ForkJoinWorkerThreadFactory} to use it in a {@code
+ * ForkJoinPool}.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ForkJoinWorkerThread extends Thread {
+    /*
+     * Algorithm overview:
+     *
+     * 1. Work-Stealing: Work-stealing queues are special forms of
+     * Deques that support only three of the four possible
+     * end-operations -- push, pop, and deq (aka steal), and only do
+     * so under the constraints that push and pop are called only from
+     * the owning thread, while deq may be called from other threads.
+     * (If you are unfamiliar with them, you probably want to read
+     * Herlihy and Shavit's book "The Art of Multiprocessor
+     * programming", chapter 16 describing these in more detail before
+     * proceeding.)  The main work-stealing queue design is roughly
+     * similar to "Dynamic Circular Work-Stealing Deque" by David
+     * Chase and Yossi Lev, SPAA 2005
+     * (http://research.sun.com/scalable/pubs/index.html).  The main
+     * difference ultimately stems from gc requirements that we null
+     * out taken slots as soon as we can, to maintain as small a
+     * footprint as possible even in programs generating huge numbers
+     * of tasks. To accomplish this, we shift the CAS arbitrating pop
+     * vs deq (steal) from being on the indices ("base" and "sp") to
+     * the slots themselves (mainly via method "casSlotNull()"). So,
+     * both a successful pop and deq mainly entail CAS'ing a non-null
+     * slot to null.  Because we rely on CASes of references, we do
+     * not need tag bits on base or sp.  They are simple ints as used
+     * in any circular array-based queue (see for example ArrayDeque).
+     * Updates to the indices must still be ordered in a way that
+     * guarantees that (sp - base) > 0 means the queue is empty, but
+     * otherwise may err on the side of possibly making the queue
+     * appear nonempty when a push, pop, or deq have not fully
+     * committed. Note that this means that the deq operation,
+     * considered individually, is not wait-free. One thief cannot
+     * successfully continue until another in-progress one (or, if
+     * previously empty, a push) completes.  However, in the
+     * aggregate, we ensure at least probabilistic
+     * non-blockingness. If an attempted steal fails, a thief always
+     * chooses a different random victim target to try next. So, in
+     * order for one thief to progress, it suffices for any
+     * in-progress deq or new push on any empty queue to complete. One
+     * reason this works well here is that apparently-nonempty often
+     * means soon-to-be-stealable, which gives threads a chance to
+     * activate if necessary before stealing (see below).
+     *
+     * This approach also enables support for "async mode" where local
+     * task processing is in FIFO, not LIFO order; simply by using a
+     * version of deq rather than pop when locallyFifo is true (as set
+     * by the ForkJoinPool).  This allows use in message-passing
+     * frameworks in which tasks are never joined.
+     *
+     * Efficient implementation of this approach currently relies on
+     * an uncomfortable amount of "Unsafe" mechanics. To maintain
+     * correct orderings, reads and writes of variable base require
+     * volatile ordering.  Variable sp does not require volatile write
+     * but needs cheaper store-ordering on writes.  Because they are
+     * protected by volatile base reads, reads of the queue array and
+     * its slots do not need volatile load semantics, but writes (in
+     * push) require store order and CASes (in pop and deq) require
+     * (volatile) CAS semantics.  (See "Idempotent work stealing" by
+     * Michael, Saraswat, and Vechev, PPoPP 2009
+     * http://portal.acm.org/citation.cfm?id=1504186 for an algorithm
+     * with similar properties, but without support for nulling
+     * slots.)  Since these combinations aren't supported using
+     * ordinary volatiles, the only way to accomplish these
+     * efficiently is to use direct Unsafe calls. (Using external
+     * AtomicIntegers and AtomicReferenceArrays for the indices and
+     * array is significantly slower because of memory locality and
+     * indirection effects.)
+     *
+     * Further, performance on most platforms is very sensitive to
+     * placement and sizing of the (resizable) queue array.  Even
+     * though these queues don't usually become all that big, the
+     * initial size must be large enough to counteract cache
+     * contention effects across multiple queues (especially in the
+     * presence of GC cardmarking). Also, to improve thread-locality,
+     * queues are currently initialized immediately after the thread
+     * gets the initial signal to start processing tasks.  However,
+     * all queue-related methods except pushTask are written in a way
+     * that allows them to instead be lazily allocated and/or disposed
+     * of when empty. All together, these low-level implementation
+     * choices produce as much as a factor of 4 performance
+     * improvement compared to naive implementations, and enable the
+     * processing of billions of tasks per second, sometimes at the
+     * expense of ugliness.
+     *
+     * 2. Run control: The primary run control is based on a global
+     * counter (activeCount) held by the pool. It uses an algorithm
+     * similar to that in Herlihy and Shavit section 17.6 to cause
+     * threads to eventually block when all threads declare they are
+     * inactive. For this to work, threads must be declared active
+     * when executing tasks, and before stealing a task. They must be
+     * inactive before blocking on the Pool Barrier (awaiting a new
+     * submission or other Pool event). In between, there is some free
+     * play which we take advantage of to avoid contention and rapid
+     * flickering of the global activeCount: If inactive, we activate
+     * only if a victim queue appears to be nonempty (see above).
+     * Similarly, a thread tries to inactivate only after a full scan
+     * of other threads.  The net effect is that contention on
+     * activeCount is rarely a measurable performance issue. (There
+     * are also a few other cases where we scan for work rather than
+     * retry/block upon contention.)
+     *
+     * 3. Selection control. We maintain policy of always choosing to
+     * run local tasks rather than stealing, and always trying to
+     * steal tasks before trying to run a new submission. All steals
+     * are currently performed in randomly-chosen deq-order. It may be
+     * worthwhile to bias these with locality / anti-locality
+     * information, but doing this well probably requires more
+     * lower-level information from JVMs than currently provided.
+     */
+
+    /**
+     * Capacity of work-stealing queue array upon initialization.
+     * Must be a power of two. Initial size must be at least 2, but is
+     * padded to minimize cache effects.
+     */
+    private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
+
+    /**
+     * Maximum work-stealing queue array size.  Must be less than or
+     * equal to 1 << 28 to ensure lack of index wraparound. (This
+     * is less than usual bounds, because we need leftshift by 3
+     * to be in int range).
+     */
+    private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 28;
+
+    /**
+     * The pool this thread works in. Accessed directly by ForkJoinTask.
+     */
+    final ForkJoinPool pool;
+
+    /**
+     * The work-stealing queue array. Size must be a power of two.
+     * Initialized when thread starts, to improve memory locality.
+     */
+    private ForkJoinTask<?>[] queue;
+
+    /**
+     * Index (mod queue.length) of next queue slot to push to or pop
+     * from. It is written only by owner thread, via ordered store.
+     * Both sp and base are allowed to wrap around on overflow, but
+     * (sp - base) still estimates size.
+     */
+    private volatile int sp;
+
+    /**
+     * Index (mod queue.length) of least valid queue slot, which is
+     * always the next position to steal from if nonempty.
+     */
+    private volatile int base;
+
+    /**
+     * Activity status. When true, this worker is considered active.
+     * Must be false upon construction. It must be true when executing
+     * tasks, and BEFORE stealing a task. It must be false before
+     * calling pool.sync.
+     */
+    private boolean active;
+
+    /**
+     * Run state of this worker. Supports simple versions of the usual
+     * shutdown/shutdownNow control.
+     */
+    private volatile int runState;
+
+    /**
+     * Seed for random number generator for choosing steal victims.
+     * Uses Marsaglia xorshift. Must be nonzero upon initialization.
+     */
+    private int seed;
+
+    /**
+     * Number of steals, transferred to pool when idle
+     */
+    private int stealCount;
+
+    /**
+     * Index of this worker in pool array. Set once by pool before
+     * running, and accessed directly by pool during cleanup etc.
+     */
+    int poolIndex;
+
+    /**
+     * The last barrier event waited for. Accessed in pool callback
+     * methods, but only by current thread.
+     */
+    long lastEventCount;
+
+    /**
+     * True if use local fifo, not default lifo, for local polling
+     */
+    private boolean locallyFifo;
+
+    /**
+     * Creates a ForkJoinWorkerThread operating in the given pool.
+     *
+     * @param pool the pool this thread works in
+     * @throws NullPointerException if pool is null
+     */
+    protected ForkJoinWorkerThread(ForkJoinPool pool) {
+        if (pool == null) throw new NullPointerException();
+        this.pool = pool;
+        // Note: poolIndex is set by pool during construction
+        // Remaining initialization is deferred to onStart
+    }
+
+    // Public access methods
+
+    /**
+     * Returns the pool hosting this thread.
+     *
+     * @return the pool
+     */
+    public ForkJoinPool getPool() {
+        return pool;
+    }
+
+    /**
+     * Returns the index number of this thread in its pool.  The
+     * returned value ranges from zero to the maximum number of
+     * threads (minus one) that have ever been created in the pool.
+     * This method may be useful for applications that track status or
+     * collect results per-worker rather than per-task.
+     *
+     * @return the index number
+     */
+    public int getPoolIndex() {
+        return poolIndex;
+    }
+
+    /**
+     * Establishes local first-in-first-out scheduling mode for forked
+     * tasks that are never joined.
+     *
+     * @param async if true, use locally FIFO scheduling
+     */
+    void setAsyncMode(boolean async) {
+        locallyFifo = async;
+    }
+
+    // Runstate management
+
+    // Runstate values. Order matters
+    private static final int RUNNING     = 0;
+    private static final int SHUTDOWN    = 1;
+    private static final int TERMINATING = 2;
+    private static final int TERMINATED  = 3;
+
+    final boolean isShutdown()    { return runState >= SHUTDOWN;  }
+    final boolean isTerminating() { return runState >= TERMINATING;  }
+    final boolean isTerminated()  { return runState == TERMINATED; }
+    final boolean shutdown()      { return transitionRunStateTo(SHUTDOWN); }
+    final boolean shutdownNow()   { return transitionRunStateTo(TERMINATING); }
+
+    /**
+     * Transitions to at least the given state.
+     *
+     * @return {@code true} if not already at least at given state
+     */
+    private boolean transitionRunStateTo(int state) {
+        for (;;) {
+            int s = runState;
+            if (s >= state)
+                return false;
+            if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, state))
+                return true;
+        }
+    }
+
+    /**
+     * Tries to set status to active; fails on contention.
+     */
+    private boolean tryActivate() {
+        if (!active) {
+            if (!pool.tryIncrementActiveCount())
+                return false;
+            active = true;
+        }
+        return true;
+    }
+
+    /**
+     * Tries to set status to inactive; fails on contention.
+     */
+    private boolean tryInactivate() {
+        if (active) {
+            if (!pool.tryDecrementActiveCount())
+                return false;
+            active = false;
+        }
+        return true;
+    }
+
+    /**
+     * Computes next value for random victim probe.  Scans don't
+     * require a very high quality generator, but also not a crummy
+     * one.  Marsaglia xor-shift is cheap and works well.
+     */
+    private static int xorShift(int r) {
+        r ^= (r << 13);
+        r ^= (r >>> 17);
+        return r ^ (r << 5);
+    }
+
+    // Lifecycle methods
+
+    /**
+     * This method is required to be public, but should never be
+     * called explicitly. It performs the main run loop to execute
+     * ForkJoinTasks.
+     */
+    public void run() {
+        Throwable exception = null;
+        try {
+            onStart();
+            pool.sync(this); // await first pool event
+            mainLoop();
+        } catch (Throwable ex) {
+            exception = ex;
+        } finally {
+            onTermination(exception);
+        }
+    }
+
+    /**
+     * Executes tasks until shut down.
+     */
+    private void mainLoop() {
+        while (!isShutdown()) {
+            ForkJoinTask<?> t = pollTask();
+            if (t != null || (t = pollSubmission()) != null)
+                t.quietlyExec();
+            else if (tryInactivate())
+                pool.sync(this);
+        }
+    }
+
+    /**
+     * Initializes internal state after construction but before
+     * processing any tasks. If you override this method, you must
+     * invoke super.onStart() at the beginning of the method.
+     * Initialization requires care: Most fields must have legal
+     * default values, to ensure that attempted accesses from other
+     * threads work correctly even before this thread starts
+     * processing tasks.
+     */
+    protected void onStart() {
+        // Allocate while starting to improve chances of thread-local
+        // isolation
+        queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
+        // Initial value of seed need not be especially random but
+        // should differ across workers and must be nonzero
+        int p = poolIndex + 1;
+        seed = p + (p << 8) + (p << 16) + (p << 24); // spread bits
+    }
+
+    /**
+     * Performs cleanup associated with termination of this worker
+     * thread.  If you override this method, you must invoke
+     * {@code super.onTermination} at the end of the overridden method.
+     *
+     * @param exception the exception causing this thread to abort due
+     * to an unrecoverable error, or {@code null} if completed normally
+     */
+    protected void onTermination(Throwable exception) {
+        // Execute remaining local tasks unless aborting or terminating
+        while (exception == null && pool.isProcessingTasks() && base != sp) {
+            try {
+                ForkJoinTask<?> t = popTask();
+                if (t != null)
+                    t.quietlyExec();
+            } catch (Throwable ex) {
+                exception = ex;
+            }
+        }
+        // Cancel other tasks, transition status, notify pool, and
+        // propagate exception to uncaught exception handler
+        try {
+            do {} while (!tryInactivate()); // ensure inactive
+            cancelTasks();
+            runState = TERMINATED;
+            pool.workerTerminated(this);
+        } catch (Throwable ex) {        // Shouldn't ever happen
+            if (exception == null)      // but if so, at least rethrown
+                exception = ex;
+        } finally {
+            if (exception != null)
+                ForkJoinTask.rethrowException(exception);
+        }
+    }
+
+    // Intrinsics-based support for queue operations.
+
+    private static long slotOffset(int i) {
+        return ((long) i << qShift) + qBase;
+    }
+
+    /**
+     * Adds in store-order the given task at given slot of q to null.
+     * Caller must ensure q is non-null and index is in range.
+     */
+    private static void setSlot(ForkJoinTask<?>[] q, int i,
+                                ForkJoinTask<?> t) {
+        UNSAFE.putOrderedObject(q, slotOffset(i), t);
+    }
+
+    /**
+     * CAS given slot of q to null. Caller must ensure q is non-null
+     * and index is in range.
+     */
+    private static boolean casSlotNull(ForkJoinTask<?>[] q, int i,
+                                       ForkJoinTask<?> t) {
+        return UNSAFE.compareAndSwapObject(q, slotOffset(i), t, null);
+    }
+
+    /**
+     * Sets sp in store-order.
+     */
+    private void storeSp(int s) {
+        UNSAFE.putOrderedInt(this, spOffset, s);
+    }
+
+    // Main queue methods
+
+    /**
+     * Pushes a task. Called only by current thread.
+     *
+     * @param t the task. Caller must ensure non-null.
+     */
+    final void pushTask(ForkJoinTask<?> t) {
+        ForkJoinTask<?>[] q = queue;
+        int mask = q.length - 1;
+        int s = sp;
+        setSlot(q, s & mask, t);
+        storeSp(++s);
+        if ((s -= base) == 1)
+            pool.signalWork();
+        else if (s >= mask)
+            growQueue();
+    }
+
+    /**
+     * Tries to take a task from the base of the queue, failing if
+     * either empty or contended.
+     *
+     * @return a task, or null if none or contended
+     */
+    final ForkJoinTask<?> deqTask() {
+        ForkJoinTask<?> t;
+        ForkJoinTask<?>[] q;
+        int i;
+        int b;
+        if (sp != (b = base) &&
+            (q = queue) != null && // must read q after b
+            (t = q[i = (q.length - 1) & b]) != null &&
+            casSlotNull(q, i, t)) {
+            base = b + 1;
+            return t;
+        }
+        return null;
+    }
+
+    /**
+     * Tries to take a task from the base of own queue, activating if
+     * necessary, failing only if empty. Called only by current thread.
+     *
+     * @return a task, or null if none
+     */
+    final ForkJoinTask<?> locallyDeqTask() {
+        int b;
+        while (sp != (b = base)) {
+            if (tryActivate()) {
+                ForkJoinTask<?>[] q = queue;
+                int i = (q.length - 1) & b;
+                ForkJoinTask<?> t = q[i];
+                if (t != null && casSlotNull(q, i, t)) {
+                    base = b + 1;
+                    return t;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a popped task, or null if empty. Ensures active status
+     * if non-null. Called only by current thread.
+     */
+    final ForkJoinTask<?> popTask() {
+        int s = sp;
+        while (s != base) {
+            if (tryActivate()) {
+                ForkJoinTask<?>[] q = queue;
+                int mask = q.length - 1;
+                int i = (s - 1) & mask;
+                ForkJoinTask<?> t = q[i];
+                if (t == null || !casSlotNull(q, i, t))
+                    break;
+                storeSp(s - 1);
+                return t;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Specialized version of popTask to pop only if
+     * topmost element is the given task. Called only
+     * by current thread while active.
+     *
+     * @param t the task. Caller must ensure non-null.
+     */
+    final boolean unpushTask(ForkJoinTask<?> t) {
+        ForkJoinTask<?>[] q = queue;
+        int mask = q.length - 1;
+        int s = sp - 1;
+        if (casSlotNull(q, s & mask, t)) {
+            storeSp(s);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns next task or null if empty or contended
+     */
+    final ForkJoinTask<?> peekTask() {
+        ForkJoinTask<?>[] q = queue;
+        if (q == null)
+            return null;
+        int mask = q.length - 1;
+        int i = locallyFifo ? base : (sp - 1);
+        return q[i & mask];
+    }
+
+    /**
+     * Doubles queue array size. Transfers elements by emulating
+     * steals (deqs) from old array and placing, oldest first, into
+     * new array.
+     */
+    private void growQueue() {
+        ForkJoinTask<?>[] oldQ = queue;
+        int oldSize = oldQ.length;
+        int newSize = oldSize << 1;
+        if (newSize > MAXIMUM_QUEUE_CAPACITY)
+            throw new RejectedExecutionException("Queue capacity exceeded");
+        ForkJoinTask<?>[] newQ = queue = new ForkJoinTask<?>[newSize];
+
+        int b = base;
+        int bf = b + oldSize;
+        int oldMask = oldSize - 1;
+        int newMask = newSize - 1;
+        do {
+            int oldIndex = b & oldMask;
+            ForkJoinTask<?> t = oldQ[oldIndex];
+            if (t != null && !casSlotNull(oldQ, oldIndex, t))
+                t = null;
+            setSlot(newQ, b & newMask, t);
+        } while (++b != bf);
+        pool.signalWork();
+    }
+
+    /**
+     * Tries to steal a task from another worker. Starts at a random
+     * index of workers array, and probes workers until finding one
+     * with non-empty queue or finding that all are empty.  It
+     * randomly selects the first n probes. If these are empty, it
+     * resorts to a full circular traversal, which is necessary to
+     * accurately set active status by caller. Also restarts if pool
+     * events occurred since last scan, which forces refresh of
+     * workers array, in case barrier was associated with resize.
+     *
+     * This method must be both fast and quiet -- usually avoiding
+     * memory accesses that could disrupt cache sharing etc other than
+     * those needed to check for and take tasks. This accounts for,
+     * among other things, updating random seed in place without
+     * storing it until exit.
+     *
+     * @return a task, or null if none found
+     */
+    private ForkJoinTask<?> scan() {
+        ForkJoinTask<?> t = null;
+        int r = seed;                    // extract once to keep scan quiet
+        ForkJoinWorkerThread[] ws;       // refreshed on outer loop
+        int mask;                        // must be power 2 minus 1 and > 0
+        outer:do {
+            if ((ws = pool.workers) != null && (mask = ws.length - 1) > 0) {
+                int idx = r;
+                int probes = ~mask;      // use random index while negative
+                for (;;) {
+                    r = xorShift(r);     // update random seed
+                    ForkJoinWorkerThread v = ws[mask & idx];
+                    if (v == null || v.sp == v.base) {
+                        if (probes <= mask)
+                            idx = (probes++ < 0) ? r : (idx + 1);
+                        else
+                            break;
+                    }
+                    else if (!tryActivate() || (t = v.deqTask()) == null)
+                        continue outer;  // restart on contention
+                    else
+                        break outer;
+                }
+            }
+        } while (pool.hasNewSyncEvent(this)); // retry on pool events
+        seed = r;
+        return t;
+    }
+
+    /**
+     * Gets and removes a local or stolen task.
+     *
+     * @return a task, if available
+     */
+    final ForkJoinTask<?> pollTask() {
+        ForkJoinTask<?> t = locallyFifo ? locallyDeqTask() : popTask();
+        if (t == null && (t = scan()) != null)
+            ++stealCount;
+        return t;
+    }
+
+    /**
+     * Gets a local task.
+     *
+     * @return a task, if available
+     */
+    final ForkJoinTask<?> pollLocalTask() {
+        return locallyFifo ? locallyDeqTask() : popTask();
+    }
+
+    /**
+     * Returns a pool submission, if one exists, activating first.
+     *
+     * @return a submission, if available
+     */
+    private ForkJoinTask<?> pollSubmission() {
+        ForkJoinPool p = pool;
+        while (p.hasQueuedSubmissions()) {
+            ForkJoinTask<?> t;
+            if (tryActivate() && (t = p.pollSubmission()) != null)
+                return t;
+        }
+        return null;
+    }
+
+    // Methods accessed only by Pool
+
+    /**
+     * Removes and cancels all tasks in queue.  Can be called from any
+     * thread.
+     */
+    final void cancelTasks() {
+        ForkJoinTask<?> t;
+        while (base != sp && (t = deqTask()) != null)
+            t.cancelIgnoringExceptions();
+    }
+
+    /**
+     * Drains tasks to given collection c.
+     *
+     * @return the number of tasks drained
+     */
+    final int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
+        int n = 0;
+        ForkJoinTask<?> t;
+        while (base != sp && (t = deqTask()) != null) {
+            c.add(t);
+            ++n;
+        }
+        return n;
+    }
+
+    /**
+     * Gets and clears steal count for accumulation by pool.  Called
+     * only when known to be idle (in pool.sync and termination).
+     */
+    final int getAndClearStealCount() {
+        int sc = stealCount;
+        stealCount = 0;
+        return sc;
+    }
+
+    /**
+     * Returns {@code true} if at least one worker in the given array
+     * appears to have at least one queued task.
+     *
+     * @param ws array of workers
+     */
+    static boolean hasQueuedTasks(ForkJoinWorkerThread[] ws) {
+        if (ws != null) {
+            int len = ws.length;
+            for (int j = 0; j < 2; ++j) { // need two passes for clean sweep
+                for (int i = 0; i < len; ++i) {
+                    ForkJoinWorkerThread w = ws[i];
+                    if (w != null && w.sp != w.base)
+                        return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    // Support methods for ForkJoinTask
+
+    /**
+     * Returns an estimate of the number of tasks in the queue.
+     */
+    final int getQueueSize() {
+        // suppress momentarily negative values
+        return Math.max(0, sp - base);
+    }
+
+    /**
+     * Returns an estimate of the number of tasks, offset by a
+     * function of number of idle workers.
+     */
+    final int getEstimatedSurplusTaskCount() {
+        // The halving approximates weighting idle vs non-idle workers
+        return (sp - base) - (pool.getIdleThreadCount() >>> 1);
+    }
+
+    /**
+     * Scans, returning early if joinMe done.
+     */
+    final ForkJoinTask<?> scanWhileJoining(ForkJoinTask<?> joinMe) {
+        ForkJoinTask<?> t = pollTask();
+        if (t != null && joinMe.status < 0 && sp == base) {
+            pushTask(t); // unsteal if done and this task would be stealable
+            t = null;
+        }
+        return t;
+    }
+
+    /**
+     * Runs tasks until {@code pool.isQuiescent()}.
+     */
+    final void helpQuiescePool() {
+        for (;;) {
+            ForkJoinTask<?> t = pollTask();
+            if (t != null)
+                t.quietlyExec();
+            else if (tryInactivate() && pool.isQuiescent())
+                break;
+        }
+        do {} while (!tryActivate()); // re-activate on exit
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long spOffset =
+        objectFieldOffset("sp", ForkJoinWorkerThread.class);
+    private static final long runStateOffset =
+        objectFieldOffset("runState", ForkJoinWorkerThread.class);
+    private static final long qBase;
+    private static final int qShift;
+
+    static {
+        qBase = UNSAFE.arrayBaseOffset(ForkJoinTask[].class);
+        int s = UNSAFE.arrayIndexScale(ForkJoinTask[].class);
+        if ((s & (s-1)) != 0)
+            throw new Error("data type scale not a power of two");
+        qShift = 31 - Integer.numberOfLeadingZeros(s);
+    }
+
+    private static long objectFieldOffset(String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,1270 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.concurrent.locks.LockSupport;
+/**
+ * An unbounded {@link TransferQueue} based on linked nodes.
+ * This queue orders elements FIFO (first-in-first-out) with respect
+ * to any given producer.  The <em>head</em> of the queue is that
+ * element that has been on the queue the longest time for some
+ * producer.  The <em>tail</em> of the queue is that element that has
+ * been on the queue the shortest time for some producer.
+ *
+ * <p>Beware that, unlike in most collections, the {@code size}
+ * method is <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these queues, determining the current number
+ * of elements requires a traversal of the elements.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code LinkedTransferQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code LinkedTransferQueue} in another thread.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class LinkedTransferQueue<E> extends AbstractQueue<E>
+    implements TransferQueue<E>, java.io.Serializable {
+    private static final long serialVersionUID = -3223113410248163686L;
+
+    /*
+     * *** Overview of Dual Queues with Slack ***
+     *
+     * Dual Queues, introduced by Scherer and Scott
+     * (http://www.cs.rice.edu/~wns1/papers/2004-DISC-DDS.pdf) are
+     * (linked) queues in which nodes may represent either data or
+     * requests.  When a thread tries to enqueue a data node, but
+     * encounters a request node, it instead "matches" and removes it;
+     * and vice versa for enqueuing requests. Blocking Dual Queues
+     * arrange that threads enqueuing unmatched requests block until
+     * other threads provide the match. Dual Synchronous Queues (see
+     * Scherer, Lea, & Scott
+     * http://www.cs.rochester.edu/u/scott/papers/2009_Scherer_CACM_SSQ.pdf)
+     * additionally arrange that threads enqueuing unmatched data also
+     * block.  Dual Transfer Queues support all of these modes, as
+     * dictated by callers.
+     *
+     * A FIFO dual queue may be implemented using a variation of the
+     * Michael & Scott (M&S) lock-free queue algorithm
+     * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf).
+     * It maintains two pointer fields, "head", pointing to a
+     * (matched) node that in turn points to the first actual
+     * (unmatched) queue node (or null if empty); and "tail" that
+     * points to the last node on the queue (or again null if
+     * empty). For example, here is a possible queue with four data
+     * elements:
+     *
+     *  head                tail
+     *    |                   |
+     *    v                   v
+     *    M -> U -> U -> U -> U
+     *
+     * The M&S queue algorithm is known to be prone to scalability and
+     * overhead limitations when maintaining (via CAS) these head and
+     * tail pointers. This has led to the development of
+     * contention-reducing variants such as elimination arrays (see
+     * Moir et al http://portal.acm.org/citation.cfm?id=1074013) and
+     * optimistic back pointers (see Ladan-Mozes & Shavit
+     * http://people.csail.mit.edu/edya/publications/OptimisticFIFOQueue-journal.pdf).
+     * However, the nature of dual queues enables a simpler tactic for
+     * improving M&S-style implementations when dual-ness is needed.
+     *
+     * In a dual queue, each node must atomically maintain its match
+     * status. While there are other possible variants, we implement
+     * this here as: for a data-mode node, matching entails CASing an
+     * "item" field from a non-null data value to null upon match, and
+     * vice-versa for request nodes, CASing from null to a data
+     * value. (Note that the linearization properties of this style of
+     * queue are easy to verify -- elements are made available by
+     * linking, and unavailable by matching.) Compared to plain M&S
+     * queues, this property of dual queues requires one additional
+     * successful atomic operation per enq/deq pair. But it also
+     * enables lower cost variants of queue maintenance mechanics. (A
+     * variation of this idea applies even for non-dual queues that
+     * support deletion of interior elements, such as
+     * j.u.c.ConcurrentLinkedQueue.)
+     *
+     * Once a node is matched, its match status can never again
+     * change.  We may thus arrange that the linked list of them
+     * contain a prefix of zero or more matched nodes, followed by a
+     * suffix of zero or more unmatched nodes. (Note that we allow
+     * both the prefix and suffix to be zero length, which in turn
+     * means that we do not use a dummy header.)  If we were not
+     * concerned with either time or space efficiency, we could
+     * correctly perform enqueue and dequeue operations by traversing
+     * from a pointer to the initial node; CASing the item of the
+     * first unmatched node on match and CASing the next field of the
+     * trailing node on appends. (Plus some special-casing when
+     * initially empty).  While this would be a terrible idea in
+     * itself, it does have the benefit of not requiring ANY atomic
+     * updates on head/tail fields.
+     *
+     * We introduce here an approach that lies between the extremes of
+     * never versus always updating queue (head and tail) pointers.
+     * This offers a tradeoff between sometimes requiring extra
+     * traversal steps to locate the first and/or last unmatched
+     * nodes, versus the reduced overhead and contention of fewer
+     * updates to queue pointers. For example, a possible snapshot of
+     * a queue is:
+     *
+     *  head           tail
+     *    |              |
+     *    v              v
+     *    M -> M -> U -> U -> U -> U
+     *
+     * The best value for this "slack" (the targeted maximum distance
+     * between the value of "head" and the first unmatched node, and
+     * similarly for "tail") is an empirical matter. We have found
+     * that using very small constants in the range of 1-3 work best
+     * over a range of platforms. Larger values introduce increasing
+     * costs of cache misses and risks of long traversal chains, while
+     * smaller values increase CAS contention and overhead.
+     *
+     * Dual queues with slack differ from plain M&S dual queues by
+     * virtue of only sometimes updating head or tail pointers when
+     * matching, appending, or even traversing nodes; in order to
+     * maintain a targeted slack.  The idea of "sometimes" may be
+     * operationalized in several ways. The simplest is to use a
+     * per-operation counter incremented on each traversal step, and
+     * to try (via CAS) to update the associated queue pointer
+     * whenever the count exceeds a threshold. Another, that requires
+     * more overhead, is to use random number generators to update
+     * with a given probability per traversal step.
+     *
+     * In any strategy along these lines, because CASes updating
+     * fields may fail, the actual slack may exceed targeted
+     * slack. However, they may be retried at any time to maintain
+     * targets.  Even when using very small slack values, this
+     * approach works well for dual queues because it allows all
+     * operations up to the point of matching or appending an item
+     * (hence potentially allowing progress by another thread) to be
+     * read-only, thus not introducing any further contention. As
+     * described below, we implement this by performing slack
+     * maintenance retries only after these points.
+     *
+     * As an accompaniment to such techniques, traversal overhead can
+     * be further reduced without increasing contention of head
+     * pointer updates: Threads may sometimes shortcut the "next" link
+     * path from the current "head" node to be closer to the currently
+     * known first unmatched node, and similarly for tail. Again, this
+     * may be triggered with using thresholds or randomization.
+     *
+     * These ideas must be further extended to avoid unbounded amounts
+     * of costly-to-reclaim garbage caused by the sequential "next"
+     * links of nodes starting at old forgotten head nodes: As first
+     * described in detail by Boehm
+     * (http://portal.acm.org/citation.cfm?doid=503272.503282) if a GC
+     * delays noticing that any arbitrarily old node has become
+     * garbage, all newer dead nodes will also be unreclaimed.
+     * (Similar issues arise in non-GC environments.)  To cope with
+     * this in our implementation, upon CASing to advance the head
+     * pointer, we set the "next" link of the previous head to point
+     * only to itself; thus limiting the length of connected dead lists.
+     * (We also take similar care to wipe out possibly garbage
+     * retaining values held in other Node fields.)  However, doing so
+     * adds some further complexity to traversal: If any "next"
+     * pointer links to itself, it indicates that the current thread
+     * has lagged behind a head-update, and so the traversal must
+     * continue from the "head".  Traversals trying to find the
+     * current tail starting from "tail" may also encounter
+     * self-links, in which case they also continue at "head".
+     *
+     * It is tempting in slack-based scheme to not even use CAS for
+     * updates (similarly to Ladan-Mozes & Shavit). However, this
+     * cannot be done for head updates under the above link-forgetting
+     * mechanics because an update may leave head at a detached node.
+     * And while direct writes are possible for tail updates, they
+     * increase the risk of long retraversals, and hence long garbage
+     * chains, which can be much more costly than is worthwhile
+     * considering that the cost difference of performing a CAS vs
+     * write is smaller when they are not triggered on each operation
+     * (especially considering that writes and CASes equally require
+     * additional GC bookkeeping ("write barriers") that are sometimes
+     * more costly than the writes themselves because of contention).
+     *
+     * Removal of interior nodes (due to timed out or interrupted
+     * waits, or calls to remove(x) or Iterator.remove) can use a
+     * scheme roughly similar to that described in Scherer, Lea, and
+     * Scott's SynchronousQueue. Given a predecessor, we can unsplice
+     * any node except the (actual) tail of the queue. To avoid
+     * build-up of cancelled trailing nodes, upon a request to remove
+     * a trailing node, it is placed in field "cleanMe" to be
+     * unspliced upon the next call to unsplice any other node.
+     * Situations needing such mechanics are not common but do occur
+     * in practice; for example when an unbounded series of short
+     * timed calls to poll repeatedly time out but never otherwise
+     * fall off the list because of an untimed call to take at the
+     * front of the queue. Note that maintaining field cleanMe does
+     * not otherwise much impact garbage retention even if never
+     * cleared by some other call because the held node will
+     * eventually either directly or indirectly lead to a self-link
+     * once off the list.
+     *
+     * *** Overview of implementation ***
+     *
+     * We use a threshold-based approach to updates, with a slack
+     * threshold of two -- that is, we update head/tail when the
+     * current pointer appears to be two or more steps away from the
+     * first/last node. The slack value is hard-wired: a path greater
+     * than one is naturally implemented by checking equality of
+     * traversal pointers except when the list has only one element,
+     * in which case we keep slack threshold at one. Avoiding tracking
+     * explicit counts across method calls slightly simplifies an
+     * already-messy implementation. Using randomization would
+     * probably work better if there were a low-quality dirt-cheap
+     * per-thread one available, but even ThreadLocalRandom is too
+     * heavy for these purposes.
+     *
+     * With such a small slack threshold value, it is rarely
+     * worthwhile to augment this with path short-circuiting; i.e.,
+     * unsplicing nodes between head and the first unmatched node, or
+     * similarly for tail, rather than advancing head or tail
+     * proper. However, it is used (in awaitMatch) immediately before
+     * a waiting thread starts to block, as a final bit of helping at
+     * a point when contention with others is extremely unlikely
+     * (since if other threads that could release it are operating,
+     * then the current thread wouldn't be blocking).
+     *
+     * We allow both the head and tail fields to be null before any
+     * nodes are enqueued; initializing upon first append.  This
+     * simplifies some other logic, as well as providing more
+     * efficient explicit control paths instead of letting JVMs insert
+     * implicit NullPointerExceptions when they are null.  While not
+     * currently fully implemented, we also leave open the possibility
+     * of re-nulling these fields when empty (which is complicated to
+     * arrange, for little benefit.)
+     *
+     * All enqueue/dequeue operations are handled by the single method
+     * "xfer" with parameters indicating whether to act as some form
+     * of offer, put, poll, take, or transfer (each possibly with
+     * timeout). The relative complexity of using one monolithic
+     * method outweighs the code bulk and maintenance problems of
+     * using separate methods for each case.
+     *
+     * Operation consists of up to three phases. The first is
+     * implemented within method xfer, the second in tryAppend, and
+     * the third in method awaitMatch.
+     *
+     * 1. Try to match an existing node
+     *
+     *    Starting at head, skip already-matched nodes until finding
+     *    an unmatched node of opposite mode, if one exists, in which
+     *    case matching it and returning, also if necessary updating
+     *    head to one past the matched node (or the node itself if the
+     *    list has no other unmatched nodes). If the CAS misses, then
+     *    a loop retries advancing head by two steps until either
+     *    success or the slack is at most two. By requiring that each
+     *    attempt advances head by two (if applicable), we ensure that
+     *    the slack does not grow without bound. Traversals also check
+     *    if the initial head is now off-list, in which case they
+     *    start at the new head.
+     *
+     *    If no candidates are found and the call was untimed
+     *    poll/offer, (argument "how" is NOW) return.
+     *
+     * 2. Try to append a new node (method tryAppend)
+     *
+     *    Starting at current tail pointer, find the actual last node
+     *    and try to append a new node (or if head was null, establish
+     *    the first node). Nodes can be appended only if their
+     *    predecessors are either already matched or are of the same
+     *    mode. If we detect otherwise, then a new node with opposite
+     *    mode must have been appended during traversal, so we must
+     *    restart at phase 1. The traversal and update steps are
+     *    otherwise similar to phase 1: Retrying upon CAS misses and
+     *    checking for staleness.  In particular, if a self-link is
+     *    encountered, then we can safely jump to a node on the list
+     *    by continuing the traversal at current head.
+     *
+     *    On successful append, if the call was ASYNC, return.
+     *
+     * 3. Await match or cancellation (method awaitMatch)
+     *
+     *    Wait for another thread to match node; instead cancelling if
+     *    the current thread was interrupted or the wait timed out. On
+     *    multiprocessors, we use front-of-queue spinning: If a node
+     *    appears to be the first unmatched node in the queue, it
+     *    spins a bit before blocking. In either case, before blocking
+     *    it tries to unsplice any nodes between the current "head"
+     *    and the first unmatched node.
+     *
+     *    Front-of-queue spinning vastly improves performance of
+     *    heavily contended queues. And so long as it is relatively
+     *    brief and "quiet", spinning does not much impact performance
+     *    of less-contended queues.  During spins threads check their
+     *    interrupt status and generate a thread-local random number
+     *    to decide to occasionally perform a Thread.yield. While
+     *    yield has underdefined specs, we assume that might it help,
+     *    and will not hurt in limiting impact of spinning on busy
+     *    systems.  We also use smaller (1/2) spins for nodes that are
+     *    not known to be front but whose predecessors have not
+     *    blocked -- these "chained" spins avoid artifacts of
+     *    front-of-queue rules which otherwise lead to alternating
+     *    nodes spinning vs blocking. Further, front threads that
+     *    represent phase changes (from data to request node or vice
+     *    versa) compared to their predecessors receive additional
+     *    chained spins, reflecting longer paths typically required to
+     *    unblock threads during phase changes.
+     */
+
+    /** True if on multiprocessor */
+    private static final boolean MP =
+        Runtime.getRuntime().availableProcessors() > 1;
+
+    /**
+     * The number of times to spin (with randomly interspersed calls
+     * to Thread.yield) on multiprocessor before blocking when a node
+     * is apparently the first waiter in the queue.  See above for
+     * explanation. Must be a power of two. The value is empirically
+     * derived -- it works pretty well across a variety of processors,
+     * numbers of CPUs, and OSes.
+     */
+    private static final int FRONT_SPINS   = 1 << 7;
+
+    /**
+     * The number of times to spin before blocking when a node is
+     * preceded by another node that is apparently spinning.  Also
+     * serves as an increment to FRONT_SPINS on phase changes, and as
+     * base average frequency for yielding during spins. Must be a
+     * power of two.
+     */
+    private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;
+
+    /**
+     * Queue nodes. Uses Object, not E, for items to allow forgetting
+     * them after use.  Relies heavily on Unsafe mechanics to minimize
+     * unnecessary ordering constraints: Writes that intrinsically
+     * precede or follow CASes use simple relaxed forms.  Other
+     * cleanups use releasing/lazy writes.
+     */
+    static final class Node {
+        final boolean isData;   // false if this is a request node
+        volatile Object item;   // initially non-null if isData; CASed to match
+        volatile Node next;
+        volatile Thread waiter; // null until waiting
+
+        // CAS methods for fields
+        final boolean casNext(Node cmp, Node val) {
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+        }
+
+        final boolean casItem(Object cmp, Object val) {
+            // assert cmp == null || cmp.getClass() != Node.class;
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+        }
+
+        /**
+         * Creates a new node. Uses relaxed write because item can only
+         * be seen if followed by CAS.
+         */
+        Node(Object item, boolean isData) {
+            UNSAFE.putObject(this, itemOffset, item); // relaxed write
+            this.isData = isData;
+        }
+
+        /**
+         * Links node to itself to avoid garbage retention.  Called
+         * only after CASing head field, so uses relaxed write.
+         */
+        final void forgetNext() {
+            UNSAFE.putObject(this, nextOffset, this);
+        }
+
+        /**
+         * Sets item to self (using a releasing/lazy write) and waiter
+         * to null, to avoid garbage retention after extracting or
+         * cancelling.
+         */
+        final void forgetContents() {
+            UNSAFE.putOrderedObject(this, itemOffset, this);
+            UNSAFE.putOrderedObject(this, waiterOffset, null);
+        }
+
+        /**
+         * Returns true if this node has been matched, including the
+         * case of artificial matches due to cancellation.
+         */
+        final boolean isMatched() {
+            Object x = item;
+            return (x == this) || ((x == null) == isData);
+        }
+
+        /**
+         * Returns true if this is an unmatched request node.
+         */
+        final boolean isUnmatchedRequest() {
+            return !isData && item == null;
+        }
+
+        /**
+         * Returns true if a node with the given mode cannot be
+         * appended to this node because this node is unmatched and
+         * has opposite data mode.
+         */
+        final boolean cannotPrecede(boolean haveData) {
+            boolean d = isData;
+            Object x;
+            return d != haveData && (x = item) != this && (x != null) == d;
+        }
+
+        /**
+         * Tries to artificially match a data node -- used by remove.
+         */
+        final boolean tryMatchData() {
+            // assert isData;
+            Object x = item;
+            if (x != null && x != this && casItem(x, null)) {
+                LockSupport.unpark(waiter);
+                return true;
+            }
+            return false;
+        }
+
+        // Unsafe mechanics
+        private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+        private static final long nextOffset =
+            objectFieldOffset(UNSAFE, "next", Node.class);
+        private static final long itemOffset =
+            objectFieldOffset(UNSAFE, "item", Node.class);
+        private static final long waiterOffset =
+            objectFieldOffset(UNSAFE, "waiter", Node.class);
+
+        private static final long serialVersionUID = -3375979862319811754L;
+    }
+
+    /** head of the queue; null until first enqueue */
+    transient volatile Node head;
+
+    /** predecessor of dangling unspliceable node */
+    private transient volatile Node cleanMe; // decl here reduces contention
+
+    /** tail of the queue; null until first append */
+    private transient volatile Node tail;
+
+    // CAS methods for fields
+    private boolean casTail(Node cmp, Node val) {
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+    }
+
+    private boolean casHead(Node cmp, Node val) {
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+    }
+
+    private boolean casCleanMe(Node cmp, Node val) {
+        return UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
+    }
+
+    /*
+     * Possible values for "how" argument in xfer method.
+     */
+    private static final int NOW   = 0; // for untimed poll, tryTransfer
+    private static final int ASYNC = 1; // for offer, put, add
+    private static final int SYNC  = 2; // for transfer, take
+    private static final int TIMED = 3; // for timed poll, tryTransfer
+
+    @SuppressWarnings("unchecked")
+    static <E> E cast(Object item) {
+        // assert item == null || item.getClass() != Node.class;
+        return (E) item;
+    }
+
+    /**
+     * Implements all queuing methods. See above for explanation.
+     *
+     * @param e the item or null for take
+     * @param haveData true if this is a put, else a take
+     * @param how NOW, ASYNC, SYNC, or TIMED
+     * @param nanos timeout in nanosecs, used only if mode is TIMED
+     * @return an item if matched, else e
+     * @throws NullPointerException if haveData mode but e is null
+     */
+    private E xfer(E e, boolean haveData, int how, long nanos) {
+        if (haveData && (e == null))
+            throw new NullPointerException();
+        Node s = null;                        // the node to append, if needed
+
+        retry: for (;;) {                     // restart on append race
+
+            for (Node h = head, p = h; p != null;) { // find & match first node
+                boolean isData = p.isData;
+                Object item = p.item;
+                if (item != p && (item != null) == isData) { // unmatched
+                    if (isData == haveData)   // can't match
+                        break;
+                    if (p.casItem(item, e)) { // match
+                        for (Node q = p; q != h;) {
+                            Node n = q.next;  // update head by 2
+                            if (n != null)    // unless singleton
+                                q = n;
+                            if (head == h && casHead(h, q)) {
+                                h.forgetNext();
+                                break;
+                            }                 // advance and retry
+                            if ((h = head)   == null ||
+                                (q = h.next) == null || !q.isMatched())
+                                break;        // unless slack < 2
+                        }
+                        LockSupport.unpark(p.waiter);
+                        return this.<E>cast(item);
+                    }
+                }
+                Node n = p.next;
+                p = (p != n) ? n : (h = head); // Use head if p offlist
+            }
+
+            if (how != NOW) {                 // No matches available
+                if (s == null)
+                    s = new Node(e, haveData);
+                Node pred = tryAppend(s, haveData);
+                if (pred == null)
+                    continue retry;           // lost race vs opposite mode
+                if (how != ASYNC)
+                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
+            }
+            return e; // not waiting
+        }
+    }
+
+    /**
+     * Tries to append node s as tail.
+     *
+     * @param s the node to append
+     * @param haveData true if appending in data mode
+     * @return null on failure due to losing race with append in
+     * different mode, else s's predecessor, or s itself if no
+     * predecessor
+     */
+    private Node tryAppend(Node s, boolean haveData) {
+        for (Node t = tail, p = t;;) {        // move p to last node and append
+            Node n, u;                        // temps for reads of next & tail
+            if (p == null && (p = head) == null) {
+                if (casHead(null, s))
+                    return s;                 // initialize
+            }
+            else if (p.cannotPrecede(haveData))
+                return null;                  // lost race vs opposite mode
+            else if ((n = p.next) != null)    // not last; keep traversing
+                p = p != t && t != (u = tail) ? (t = u) : // stale tail
+                    (p != n) ? n : null;      // restart if off list
+            else if (!p.casNext(null, s))
+                p = p.next;                   // re-read on CAS failure
+            else {
+                if (p != t) {                 // update if slack now >= 2
+                    while ((tail != t || !casTail(t, s)) &&
+                           (t = tail)   != null &&
+                           (s = t.next) != null && // advance and retry
+                           (s = s.next) != null && s != t);
+                }
+                return p;
+            }
+        }
+    }
+
+    /**
+     * Spins/yields/blocks until node s is matched or caller gives up.
+     *
+     * @param s the waiting node
+     * @param pred the predecessor of s, or s itself if it has no
+     * predecessor, or null if unknown (the null case does not occur
+     * in any current calls but may in possible future extensions)
+     * @param e the comparison value for checking match
+     * @param timed if true, wait only until timeout elapses
+     * @param nanos timeout in nanosecs, used only if timed is true
+     * @return matched item, or e if unmatched on interrupt or timeout
+     */
+    private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
+        long lastTime = timed ? System.nanoTime() : 0L;
+        Thread w = Thread.currentThread();
+        int spins = -1; // initialized after first item and cancel checks
+        ThreadLocalRandom randomYields = null; // bound if needed
+
+        for (;;) {
+            Object item = s.item;
+            if (item != e) {                  // matched
+                // assert item != s;
+                s.forgetContents();           // avoid garbage
+                return this.<E>cast(item);
+            }
+            if ((w.isInterrupted() || (timed && nanos <= 0)) &&
+                    s.casItem(e, s)) {       // cancel
+                unsplice(pred, s);
+                return e;
+            }
+
+            if (spins < 0) {                  // establish spins at/near front
+                if ((spins = spinsFor(pred, s.isData)) > 0)
+                    randomYields = ThreadLocalRandom.current();
+            }
+            else if (spins > 0) {             // spin
+                if (--spins == 0)
+                    shortenHeadPath();        // reduce slack before blocking
+                else if (randomYields.nextInt(CHAINED_SPINS) == 0)
+                    Thread.yield();           // occasionally yield
+            }
+            else if (s.waiter == null) {
+                s.waiter = w;                 // request unpark then recheck
+            }
+            else if (timed) {
+                long now = System.nanoTime();
+                if ((nanos -= now - lastTime) > 0)
+                    LockSupport.parkNanos(this, nanos);
+                lastTime = now;
+            }
+            else {
+                LockSupport.park(this);
+                s.waiter = null;
+                spins = -1;                   // spin if front upon wakeup
+            }
+        }
+    }
+
+    /**
+     * Returns spin/yield value for a node with given predecessor and
+     * data mode. See above for explanation.
+     */
+    private static int spinsFor(Node pred, boolean haveData) {
+        if (MP && pred != null) {
+            if (pred.isData != haveData)      // phase change
+                return FRONT_SPINS + CHAINED_SPINS;
+            if (pred.isMatched())             // probably at front
+                return FRONT_SPINS;
+            if (pred.waiter == null)          // pred apparently spinning
+                return CHAINED_SPINS;
+        }
+        return 0;
+    }
+
+    /**
+     * Tries (once) to unsplice nodes between head and first unmatched
+     * or trailing node; failing on contention.
+     */
+    private void shortenHeadPath() {
+        Node h, hn, p, q;
+        if ((p = h = head) != null && h.isMatched() &&
+            (q = hn = h.next) != null) {
+            Node n;
+            while ((n = q.next) != q) {
+                if (n == null || !q.isMatched()) {
+                    if (hn != q && h.next == hn)
+                        h.casNext(hn, q);
+                    break;
+                }
+                p = q;
+                q = n;
+            }
+        }
+    }
+
+    /* -------------- Traversal methods -------------- */
+
+    /**
+     * Returns the successor of p, or the head node if p.next has been
+     * linked to self, which will only be true if traversing with a
+     * stale pointer that is now off the list.
+     */
+    final Node succ(Node p) {
+        Node next = p.next;
+        return (p == next) ? head : next;
+    }
+
+    /**
+     * Returns the first unmatched node of the given mode, or null if
+     * none.  Used by methods isEmpty, hasWaitingConsumer.
+     */
+    private Node firstOfMode(boolean isData) {
+        for (Node p = head; p != null; p = succ(p)) {
+            if (!p.isMatched())
+                return (p.isData == isData) ? p : null;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the item in the first unmatched node with isData; or
+     * null if none.  Used by peek.
+     */
+    private E firstDataItem() {
+        for (Node p = head; p != null; p = succ(p)) {
+            Object item = p.item;
+            if (p.isData) {
+                if (item != null && item != p)
+                    return this.<E>cast(item);
+            }
+            else if (item == null)
+                return null;
+        }
+        return null;
+    }
+
+    /**
+     * Traverses and counts unmatched nodes of the given mode.
+     * Used by methods size and getWaitingConsumerCount.
+     */
+    private int countOfMode(boolean data) {
+        int count = 0;
+        for (Node p = head; p != null; ) {
+            if (!p.isMatched()) {
+                if (p.isData != data)
+                    return 0;
+                if (++count == Integer.MAX_VALUE) // saturated
+                    break;
+            }
+            Node n = p.next;
+            if (n != p)
+                p = n;
+            else {
+                count = 0;
+                p = head;
+            }
+        }
+        return count;
+    }
+
+    final class Itr implements Iterator<E> {
+        private Node nextNode;   // next node to return item for
+        private E nextItem;      // the corresponding item
+        private Node lastRet;    // last returned node, to support remove
+        private Node lastPred;   // predecessor to unlink lastRet
+
+        /**
+         * Moves to next node after prev, or first node if prev null.
+         */
+        private void advance(Node prev) {
+            lastPred = lastRet;
+            lastRet = prev;
+            for (Node p = (prev == null) ? head : succ(prev);
+                 p != null; p = succ(p)) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p) {
+                        nextItem = LinkedTransferQueue.this.<E>cast(item);
+                        nextNode = p;
+                        return;
+                    }
+                }
+                else if (item == null)
+                    break;
+            }
+            nextNode = null;
+        }
+
+        Itr() {
+            advance(null);
+        }
+
+        public final boolean hasNext() {
+            return nextNode != null;
+        }
+
+        public final E next() {
+            Node p = nextNode;
+            if (p == null) throw new NoSuchElementException();
+            E e = nextItem;
+            advance(p);
+            return e;
+        }
+
+        public final void remove() {
+            Node p = lastRet;
+            if (p == null) throw new IllegalStateException();
+            findAndRemoveDataNode(lastPred, p);
+        }
+    }
+
+    /* -------------- Removal methods -------------- */
+
+    /**
+     * Unsplices (now or later) the given deleted/cancelled node with
+     * the given predecessor.
+     *
+     * @param pred predecessor of node to be unspliced
+     * @param s the node to be unspliced
+     */
+    private void unsplice(Node pred, Node s) {
+        s.forgetContents(); // clear unneeded fields
+        /*
+         * At any given time, exactly one node on list cannot be
+         * unlinked -- the last inserted node. To accommodate this, if
+         * we cannot unlink s, we save its predecessor as "cleanMe",
+         * processing the previously saved version first. Because only
+         * one node in the list can have a null next, at least one of
+         * node s or the node previously saved can always be
+         * processed, so this always terminates.
+         */
+        if (pred != null && pred != s) {
+            while (pred.next == s) {
+                Node oldpred = (cleanMe == null) ? null : reclean();
+                Node n = s.next;
+                if (n != null) {
+                    if (n != s)
+                        pred.casNext(s, n);
+                    break;
+                }
+                if (oldpred == pred ||      // Already saved
+                    ((oldpred == null || oldpred.next == s) &&
+                     casCleanMe(oldpred, pred))) {
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Tries to unsplice the deleted/cancelled node held in cleanMe
+     * that was previously uncleanable because it was at tail.
+     *
+     * @return current cleanMe node (or null)
+     */
+    private Node reclean() {
+        /*
+         * cleanMe is, or at one time was, predecessor of a cancelled
+         * node s that was the tail so could not be unspliced.  If it
+         * is no longer the tail, try to unsplice if necessary and
+         * make cleanMe slot available.  This differs from similar
+         * code in unsplice() because we must check that pred still
+         * points to a matched node that can be unspliced -- if not,
+         * we can (must) clear cleanMe without unsplicing.  This can
+         * loop only due to contention.
+         */
+        Node pred;
+        while ((pred = cleanMe) != null) {
+            Node s = pred.next;
+            Node n;
+            if (s == null || s == pred || !s.isMatched())
+                casCleanMe(pred, null); // already gone
+            else if ((n = s.next) != null) {
+                if (n != s)
+                    pred.casNext(s, n);
+                casCleanMe(pred, null);
+            }
+            else
+                break;
+        }
+        return pred;
+    }
+
+    /**
+     * Main implementation of Iterator.remove(). Finds
+     * and unsplices the given data node.
+     *
+     * @param possiblePred possible predecessor of s
+     * @param s the node to remove
+     */
+    final void findAndRemoveDataNode(Node possiblePred, Node s) {
+        // assert s.isData;
+        if (s.tryMatchData()) {
+            if (possiblePred != null && possiblePred.next == s)
+                unsplice(possiblePred, s); // was actual predecessor
+            else {
+                for (Node pred = null, p = head; p != null; ) {
+                    if (p == s) {
+                        unsplice(pred, p);
+                        break;
+                    }
+                    if (p.isUnmatchedRequest())
+                        break;
+                    pred = p;
+                    if ((p = p.next) == pred) { // stale
+                        pred = null;
+                        p = head;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Main implementation of remove(Object)
+     */
+    private boolean findAndRemove(Object e) {
+        if (e != null) {
+            for (Node pred = null, p = head; p != null; ) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p && e.equals(item) &&
+                        p.tryMatchData()) {
+                        unsplice(pred, p);
+                        return true;
+                    }
+                }
+                else if (item == null)
+                    break;
+                pred = p;
+                if ((p = p.next) == pred) { // stale
+                    pred = null;
+                    p = head;
+                }
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * Creates an initially empty {@code LinkedTransferQueue}.
+     */
+    public LinkedTransferQueue() {
+    }
+
+    /**
+     * Creates a {@code LinkedTransferQueue}
+     * initially containing the elements of the given collection,
+     * added in traversal order of the collection's iterator.
+     *
+     * @param c the collection of elements to initially contain
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
+     */
+    public LinkedTransferQueue(Collection<? extends E> c) {
+        this();
+        addAll(c);
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never block.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public void put(E e) {
+        xfer(e, true, ASYNC, 0);
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never block or
+     * return {@code false}.
+     *
+     * @return {@code true} (as specified by
+     *  {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e, long timeout, TimeUnit unit) {
+        xfer(e, true, ASYNC, 0);
+        return true;
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never return {@code false}.
+     *
+     * @return {@code true} (as specified by
+     *         {@link BlockingQueue#offer(Object) BlockingQueue.offer})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
+        xfer(e, true, ASYNC, 0);
+        return true;
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never throw
+     * {@link IllegalStateException} or return {@code false}.
+     *
+     * @return {@code true} (as specified by {@link Collection#add})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean add(E e) {
+        xfer(e, true, ASYNC, 0);
+        return true;
+    }
+
+    /**
+     * Transfers the element to a waiting consumer immediately, if possible.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * otherwise returning {@code false} without enqueuing the element.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean tryTransfer(E e) {
+        return xfer(e, true, NOW, 0) == null;
+    }
+
+    /**
+     * Transfers the element to a consumer, waiting if necessary to do so.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else inserts the specified element at the tail of this queue
+     * and waits until the element is received by a consumer.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public void transfer(E e) throws InterruptedException {
+        if (xfer(e, true, SYNC, 0) != null) {
+            Thread.interrupted(); // failure possible only due to interrupt
+            throw new InterruptedException();
+        }
+    }
+
+    /**
+     * Transfers the element to a consumer if it is possible to do so
+     * before the timeout elapses.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else inserts the specified element at the tail of this queue
+     * and waits until the element is received by a consumer,
+     * returning {@code false} if the specified wait time elapses
+     * before the element can be transferred.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean tryTransfer(E e, long timeout, TimeUnit unit)
+        throws InterruptedException {
+        if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null)
+            return true;
+        if (!Thread.interrupted())
+            return false;
+        throw new InterruptedException();
+    }
+
+    public E take() throws InterruptedException {
+        E e = xfer(null, false, SYNC, 0);
+        if (e != null)
+            return e;
+        Thread.interrupted();
+        throw new InterruptedException();
+    }
+
+    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+        E e = xfer(null, false, TIMED, unit.toNanos(timeout));
+        if (e != null || !Thread.interrupted())
+            return e;
+        throw new InterruptedException();
+    }
+
+    public E poll() {
+        return xfer(null, false, NOW, 0);
+    }
+
+    /**
+     * @throws NullPointerException     {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
+     */
+    public int drainTo(Collection<? super E> c) {
+        if (c == null)
+            throw new NullPointerException();
+        if (c == this)
+            throw new IllegalArgumentException();
+        int n = 0;
+        E e;
+        while ( (e = poll()) != null) {
+            c.add(e);
+            ++n;
+        }
+        return n;
+    }
+
+    /**
+     * @throws NullPointerException     {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
+     */
+    public int drainTo(Collection<? super E> c, int maxElements) {
+        if (c == null)
+            throw new NullPointerException();
+        if (c == this)
+            throw new IllegalArgumentException();
+        int n = 0;
+        E e;
+        while (n < maxElements && (e = poll()) != null) {
+            c.add(e);
+            ++n;
+        }
+        return n;
+    }
+
+    /**
+     * Returns an iterator over the elements in this queue in proper
+     * sequence, from head to tail.
+     *
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw
+     * {@link ConcurrentModificationException ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed
+     * to) reflect any modifications subsequent to construction.
+     *
+     * @return an iterator over the elements in this queue in proper sequence
+     */
+    public Iterator<E> iterator() {
+        return new Itr();
+    }
+
+    public E peek() {
+        return firstDataItem();
+    }
+
+    /**
+     * Returns {@code true} if this queue contains no elements.
+     *
+     * @return {@code true} if this queue contains no elements
+     */
+    public boolean isEmpty() {
+        return firstOfMode(true) == null;
+    }
+
+    public boolean hasWaitingConsumer() {
+        return firstOfMode(false) != null;
+    }
+
+    /**
+     * Returns the number of elements in this queue.  If this queue
+     * contains more than {@code Integer.MAX_VALUE} elements, returns
+     * {@code Integer.MAX_VALUE}.
+     *
+     * <p>Beware that, unlike in most collections, this method is
+     * <em>NOT</em> a constant-time operation. Because of the
+     * asynchronous nature of these queues, determining the current
+     * number of elements requires an O(n) traversal.
+     *
+     * @return the number of elements in this queue
+     */
+    public int size() {
+        return countOfMode(true);
+    }
+
+    public int getWaitingConsumerCount() {
+        return countOfMode(false);
+    }
+
+    /**
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
+     * elements.
+     * Returns {@code true} if this queue contained the specified element
+     * (or equivalently, if this queue changed as a result of the call).
+     *
+     * @param o element to be removed from this queue, if present
+     * @return {@code true} if this queue changed as a result of the call
+     */
+    public boolean remove(Object o) {
+        return findAndRemove(o);
+    }
+
+    /**
+     * Always returns {@code Integer.MAX_VALUE} because a
+     * {@code LinkedTransferQueue} is not capacity constrained.
+     *
+     * @return {@code Integer.MAX_VALUE} (as specified by
+     *         {@link BlockingQueue#remainingCapacity()})
+     */
+    public int remainingCapacity() {
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * Saves the state to a stream (that is, serializes it).
+     *
+     * @serialData All of the elements (each an {@code E}) in
+     * the proper order, followed by a null
+     * @param s the stream
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+        throws java.io.IOException {
+        s.defaultWriteObject();
+        for (E e : this)
+            s.writeObject(e);
+        // Use trailing null as sentinel
+        s.writeObject(null);
+    }
+
+    /**
+     * Reconstitutes the Queue instance from a stream (that is,
+     * deserializes it).
+     *
+     * @param s the stream
+     */
+    private void readObject(java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        for (;;) {
+            @SuppressWarnings("unchecked") E item = (E) s.readObject();
+            if (item == null)
+                break;
+            else
+                offer(item);
+        }
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long headOffset =
+        objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class);
+    private static final long tailOffset =
+        objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class);
+    private static final long cleanMeOffset =
+        objectFieldOffset(UNSAFE, "cleanMe", LinkedTransferQueue.class);
+
+    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+                                  String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/Phaser.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,1042 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * A reusable synchronization barrier, similar in functionality to
+ * {@link java.util.concurrent.CyclicBarrier CyclicBarrier} and
+ * {@link java.util.concurrent.CountDownLatch CountDownLatch}
+ * but supporting more flexible usage.
+ *
+ * <p> <b>Registration.</b> Unlike the case for other barriers, the
+ * number of parties <em>registered</em> to synchronize on a phaser
+ * may vary over time.  Tasks may be registered at any time (using
+ * methods {@link #register}, {@link #bulkRegister}, or forms of
+ * constructors establishing initial numbers of parties), and
+ * optionally deregistered upon any arrival (using {@link
+ * #arriveAndDeregister}).  As is the case with most basic
+ * synchronization constructs, registration and deregistration affect
+ * only internal counts; they do not establish any further internal
+ * bookkeeping, so tasks cannot query whether they are registered.
+ * (However, you can introduce such bookkeeping by subclassing this
+ * class.)
+ *
+ * <p> <b>Synchronization.</b> Like a {@code CyclicBarrier}, a {@code
+ * Phaser} may be repeatedly awaited.  Method {@link
+ * #arriveAndAwaitAdvance} has effect analogous to {@link
+ * java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each
+ * generation of a {@code Phaser} has an associated phase number. The
+ * phase number starts at zero, and advances when all parties arrive
+ * at the barrier, wrapping around to zero after reaching {@code
+ * Integer.MAX_VALUE}. The use of phase numbers enables independent
+ * control of actions upon arrival at a barrier and upon awaiting
+ * others, via two kinds of methods that may be invoked by any
+ * registered party:
+ *
+ * <ul>
+ *
+ *   <li> <b>Arrival.</b> Methods {@link #arrive} and
+ *       {@link #arriveAndDeregister} record arrival at a
+ *       barrier. These methods do not block, but return an associated
+ *       <em>arrival phase number</em>; that is, the phase number of
+ *       the barrier to which the arrival applied. When the final
+ *       party for a given phase arrives, an optional barrier action
+ *       is performed and the phase advances.  Barrier actions,
+ *       performed by the party triggering a phase advance, are
+ *       arranged by overriding method {@link #onAdvance(int, int)},
+ *       which also controls termination. Overriding this method is
+ *       similar to, but more flexible than, providing a barrier
+ *       action to a {@code CyclicBarrier}.
+ *
+ *   <li> <b>Waiting.</b> Method {@link #awaitAdvance} requires an
+ *       argument indicating an arrival phase number, and returns when
+ *       the barrier advances to (or is already at) a different phase.
+ *       Unlike similar constructions using {@code CyclicBarrier},
+ *       method {@code awaitAdvance} continues to wait even if the
+ *       waiting thread is interrupted. Interruptible and timeout
+ *       versions are also available, but exceptions encountered while
+ *       tasks wait interruptibly or with timeout do not change the
+ *       state of the barrier. If necessary, you can perform any
+ *       associated recovery within handlers of those exceptions,
+ *       often after invoking {@code forceTermination}.  Phasers may
+ *       also be used by tasks executing in a {@link ForkJoinPool},
+ *       which will ensure sufficient parallelism to execute tasks
+ *       when others are blocked waiting for a phase to advance.
+ *
+ * </ul>
+ *
+ * <p> <b>Termination.</b> A {@code Phaser} may enter a
+ * <em>termination</em> state in which all synchronization methods
+ * immediately return without updating phaser state or waiting for
+ * advance, and indicating (via a negative phase value) that execution
+ * is complete.  Termination is triggered when an invocation of {@code
+ * onAdvance} returns {@code true}.  As illustrated below, when
+ * phasers control actions with a fixed number of iterations, it is
+ * often convenient to override this method to cause termination when
+ * the current phase number reaches a threshold. Method {@link
+ * #forceTermination} is also available to abruptly release waiting
+ * threads and allow them to terminate.
+ *
+ * <p> <b>Tiering.</b> Phasers may be <em>tiered</em> (i.e., arranged
+ * in tree structures) to reduce contention. Phasers with large
+ * numbers of parties that would otherwise experience heavy
+ * synchronization contention costs may instead be set up so that
+ * groups of sub-phasers share a common parent.  This may greatly
+ * increase throughput even though it incurs greater per-operation
+ * overhead.
+ *
+ * <p><b>Monitoring.</b> While synchronization methods may be invoked
+ * only by registered parties, the current state of a phaser may be
+ * monitored by any caller.  At any given moment there are {@link
+ * #getRegisteredParties} parties in total, of which {@link
+ * #getArrivedParties} have arrived at the current phase ({@link
+ * #getPhase}).  When the remaining ({@link #getUnarrivedParties})
+ * parties arrive, the phase advances.  The values returned by these
+ * methods may reflect transient states and so are not in general
+ * useful for synchronization control.  Method {@link #toString}
+ * returns snapshots of these state queries in a form convenient for
+ * informal monitoring.
+ *
+ * <p><b>Sample usages:</b>
+ *
+ * <p>A {@code Phaser} may be used instead of a {@code CountDownLatch}
+ * to control a one-shot action serving a variable number of
+ * parties. The typical idiom is for the method setting this up to
+ * first register, then start the actions, then deregister, as in:
+ *
+ *  <pre> {@code
+ * void runTasks(List<Runnable> tasks) {
+ *   final Phaser phaser = new Phaser(1); // "1" to register self
+ *   // create and start threads
+ *   for (Runnable task : tasks) {
+ *     phaser.register();
+ *     new Thread() {
+ *       public void run() {
+ *         phaser.arriveAndAwaitAdvance(); // await all creation
+ *         task.run();
+ *       }
+ *     }.start();
+ *   }
+ *
+ *   // allow threads to start and deregister self
+ *   phaser.arriveAndDeregister();
+ * }}</pre>
+ *
+ * <p>One way to cause a set of threads to repeatedly perform actions
+ * for a given number of iterations is to override {@code onAdvance}:
+ *
+ *  <pre> {@code
+ * void startTasks(List<Runnable> tasks, final int iterations) {
+ *   final Phaser phaser = new Phaser() {
+ *     protected boolean onAdvance(int phase, int registeredParties) {
+ *       return phase >= iterations || registeredParties == 0;
+ *     }
+ *   };
+ *   phaser.register();
+ *   for (final Runnable task : tasks) {
+ *     phaser.register();
+ *     new Thread() {
+ *       public void run() {
+ *         do {
+ *           task.run();
+ *           phaser.arriveAndAwaitAdvance();
+ *         } while (!phaser.isTerminated());
+ *       }
+ *     }.start();
+ *   }
+ *   phaser.arriveAndDeregister(); // deregister self, don't wait
+ * }}</pre>
+ *
+ * If the main task must later await termination, it
+ * may re-register and then execute a similar loop:
+ *  <pre> {@code
+ *   // ...
+ *   phaser.register();
+ *   while (!phaser.isTerminated())
+ *     phaser.arriveAndAwaitAdvance();}</pre>
+ *
+ * <p>Related constructions may be used to await particular phase numbers
+ * in contexts where you are sure that the phase will never wrap around
+ * {@code Integer.MAX_VALUE}. For example:
+ *
+ *  <pre> {@code
+ * void awaitPhase(Phaser phaser, int phase) {
+ *   int p = phaser.register(); // assumes caller not already registered
+ *   while (p < phase) {
+ *     if (phaser.isTerminated())
+ *       // ... deal with unexpected termination
+ *     else
+ *       p = phaser.arriveAndAwaitAdvance();
+ *   }
+ *   phaser.arriveAndDeregister();
+ * }}</pre>
+ *
+ *
+ * <p>To create a set of tasks using a tree of phasers,
+ * you could use code of the following form, assuming a
+ * Task class with a constructor accepting a phaser that
+ * it registers for upon construction:
+ *
+ *  <pre> {@code
+ * void build(Task[] actions, int lo, int hi, Phaser ph) {
+ *   if (hi - lo > TASKS_PER_PHASER) {
+ *     for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
+ *       int j = Math.min(i + TASKS_PER_PHASER, hi);
+ *       build(actions, i, j, new Phaser(ph));
+ *     }
+ *   } else {
+ *     for (int i = lo; i < hi; ++i)
+ *       actions[i] = new Task(ph);
+ *       // assumes new Task(ph) performs ph.register()
+ *   }
+ * }
+ * // .. initially called, for n tasks via
+ * build(new Task[n], 0, n, new Phaser());}</pre>
+ *
+ * The best value of {@code TASKS_PER_PHASER} depends mainly on
+ * expected barrier synchronization rates. A value as low as four may
+ * be appropriate for extremely small per-barrier task bodies (thus
+ * high rates), or up to hundreds for extremely large ones.
+ *
+ * </pre>
+ *
+ * <p><b>Implementation notes</b>: This implementation restricts the
+ * maximum number of parties to 65535. Attempts to register additional
+ * parties result in {@code IllegalStateException}. However, you can and
+ * should create tiered phasers to accommodate arbitrarily large sets
+ * of participants.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class Phaser {
+    /*
+     * This class implements an extension of X10 "clocks".  Thanks to
+     * Vijay Saraswat for the idea, and to Vivek Sarkar for
+     * enhancements to extend functionality.
+     */
+
+    /**
+     * Barrier state representation. Conceptually, a barrier contains
+     * four values:
+     *
+     * * parties -- the number of parties to wait (16 bits)
+     * * unarrived -- the number of parties yet to hit barrier (16 bits)
+     * * phase -- the generation of the barrier (31 bits)
+     * * terminated -- set if barrier is terminated (1 bit)
+     *
+     * However, to efficiently maintain atomicity, these values are
+     * packed into a single (atomic) long. Termination uses the sign
+     * bit of 32 bit representation of phase, so phase is set to -1 on
+     * termination. Good performance relies on keeping state decoding
+     * and encoding simple, and keeping race windows short.
+     *
+     * Note: there are some cheats in arrive() that rely on unarrived
+     * count being lowest 16 bits.
+     */
+    private volatile long state;
+
+    private static final int ushortMask = 0xffff;
+    private static final int phaseMask  = 0x7fffffff;
+
+    private static int unarrivedOf(long s) {
+        return (int) (s & ushortMask);
+    }
+
+    private static int partiesOf(long s) {
+        return ((int) s) >>> 16;
+    }
+
+    private static int phaseOf(long s) {
+        return (int) (s >>> 32);
+    }
+
+    private static int arrivedOf(long s) {
+        return partiesOf(s) - unarrivedOf(s);
+    }
+
+    private static long stateFor(int phase, int parties, int unarrived) {
+        return ((((long) phase) << 32) | (((long) parties) << 16) |
+                (long) unarrived);
+    }
+
+    private static long trippedStateFor(int phase, int parties) {
+        long lp = (long) parties;
+        return (((long) phase) << 32) | (lp << 16) | lp;
+    }
+
+    /**
+     * Returns message string for bad bounds exceptions.
+     */
+    private static String badBounds(int parties, int unarrived) {
+        return ("Attempt to set " + unarrived +
+                " unarrived of " + parties + " parties");
+    }
+
+    /**
+     * The parent of this phaser, or null if none
+     */
+    private final Phaser parent;
+
+    /**
+     * The root of phaser tree. Equals this if not in a tree.  Used to
+     * support faster state push-down.
+     */
+    private final Phaser root;
+
+    // Wait queues
+
+    /**
+     * Heads of Treiber stacks for waiting threads. To eliminate
+     * contention while releasing some threads while adding others, we
+     * use two of them, alternating across even and odd phases.
+     */
+    private final AtomicReference<QNode> evenQ = new AtomicReference<QNode>();
+    private final AtomicReference<QNode> oddQ  = new AtomicReference<QNode>();
+
+    private AtomicReference<QNode> queueFor(int phase) {
+        return ((phase & 1) == 0) ? evenQ : oddQ;
+    }
+
+    /**
+     * Returns current state, first resolving lagged propagation from
+     * root if necessary.
+     */
+    private long getReconciledState() {
+        return (parent == null) ? state : reconcileState();
+    }
+
+    /**
+     * Recursively resolves state.
+     */
+    private long reconcileState() {
+        Phaser p = parent;
+        long s = state;
+        if (p != null) {
+            while (unarrivedOf(s) == 0 && phaseOf(s) != phaseOf(root.state)) {
+                long parentState = p.getReconciledState();
+                int parentPhase = phaseOf(parentState);
+                int phase = phaseOf(s = state);
+                if (phase != parentPhase) {
+                    long next = trippedStateFor(parentPhase, partiesOf(s));
+                    if (casState(s, next)) {
+                        releaseWaiters(phase);
+                        s = next;
+                    }
+                }
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Creates a new phaser without any initially registered parties,
+     * initial phase number 0, and no parent. Any thread using this
+     * phaser will need to first register for it.
+     */
+    public Phaser() {
+        this(null);
+    }
+
+    /**
+     * Creates a new phaser with the given numbers of registered
+     * unarrived parties, initial phase number 0, and no parent.
+     *
+     * @param parties the number of parties required to trip barrier
+     * @throws IllegalArgumentException if parties less than zero
+     * or greater than the maximum number of parties supported
+     */
+    public Phaser(int parties) {
+        this(null, parties);
+    }
+
+    /**
+     * Creates a new phaser with the given parent, without any
+     * initially registered parties. If parent is non-null this phaser
+     * is registered with the parent and its initial phase number is
+     * the same as that of parent phaser.
+     *
+     * @param parent the parent phaser
+     */
+    public Phaser(Phaser parent) {
+        int phase = 0;
+        this.parent = parent;
+        if (parent != null) {
+            this.root = parent.root;
+            phase = parent.register();
+        }
+        else
+            this.root = this;
+        this.state = trippedStateFor(phase, 0);
+    }
+
+    /**
+     * Creates a new phaser with the given parent and numbers of
+     * registered unarrived parties. If parent is non-null, this phaser
+     * is registered with the parent and its initial phase number is
+     * the same as that of parent phaser.
+     *
+     * @param parent the parent phaser
+     * @param parties the number of parties required to trip barrier
+     * @throws IllegalArgumentException if parties less than zero
+     * or greater than the maximum number of parties supported
+     */
+    public Phaser(Phaser parent, int parties) {
+        if (parties < 0 || parties > ushortMask)
+            throw new IllegalArgumentException("Illegal number of parties");
+        int phase = 0;
+        this.parent = parent;
+        if (parent != null) {
+            this.root = parent.root;
+            phase = parent.register();
+        }
+        else
+            this.root = this;
+        this.state = trippedStateFor(phase, parties);
+    }
+
+    /**
+     * Adds a new unarrived party to this phaser.
+     *
+     * @return the arrival phase number to which this registration applied
+     * @throws IllegalStateException if attempting to register more
+     * than the maximum supported number of parties
+     */
+    public int register() {
+        return doRegister(1);
+    }
+
+    /**
+     * Adds the given number of new unarrived parties to this phaser.
+     *
+     * @param parties the number of parties required to trip barrier
+     * @return the arrival phase number to which this registration applied
+     * @throws IllegalStateException if attempting to register more
+     * than the maximum supported number of parties
+     */
+    public int bulkRegister(int parties) {
+        if (parties < 0)
+            throw new IllegalArgumentException();
+        if (parties == 0)
+            return getPhase();
+        return doRegister(parties);
+    }
+
+    /**
+     * Shared code for register, bulkRegister
+     */
+    private int doRegister(int registrations) {
+        int phase;
+        for (;;) {
+            long s = getReconciledState();
+            phase = phaseOf(s);
+            int unarrived = unarrivedOf(s) + registrations;
+            int parties = partiesOf(s) + registrations;
+            if (phase < 0)
+                break;
+            if (parties > ushortMask || unarrived > ushortMask)
+                throw new IllegalStateException(badBounds(parties, unarrived));
+            if (phase == phaseOf(root.state) &&
+                casState(s, stateFor(phase, parties, unarrived)))
+                break;
+        }
+        return phase;
+    }
+
+    /**
+     * Arrives at the barrier, but does not wait for others.  (You can
+     * in turn wait for others via {@link #awaitAdvance}).  It is an
+     * unenforced usage error for an unregistered party to invoke this
+     * method.
+     *
+     * @return the arrival phase number, or a negative value if terminated
+     * @throws IllegalStateException if not terminated and the number
+     * of unarrived parties would become negative
+     */
+    public int arrive() {
+        int phase;
+        for (;;) {
+            long s = state;
+            phase = phaseOf(s);
+            if (phase < 0)
+                break;
+            int parties = partiesOf(s);
+            int unarrived = unarrivedOf(s) - 1;
+            if (unarrived > 0) {        // Not the last arrival
+                if (casState(s, s - 1)) // s-1 adds one arrival
+                    break;
+            }
+            else if (unarrived == 0) {  // the last arrival
+                Phaser par = parent;
+                if (par == null) {      // directly trip
+                    if (casState
+                        (s,
+                         trippedStateFor(onAdvance(phase, parties) ? -1 :
+                                         ((phase + 1) & phaseMask), parties))) {
+                        releaseWaiters(phase);
+                        break;
+                    }
+                }
+                else {                  // cascade to parent
+                    if (casState(s, s - 1)) { // zeroes unarrived
+                        par.arrive();
+                        reconcileState();
+                        break;
+                    }
+                }
+            }
+            else if (phase != phaseOf(root.state)) // or if unreconciled
+                reconcileState();
+            else
+                throw new IllegalStateException(badBounds(parties, unarrived));
+        }
+        return phase;
+    }
+
+    /**
+     * Arrives at the barrier and deregisters from it without waiting
+     * for others. Deregistration reduces the number of parties
+     * required to trip the barrier in future phases.  If this phaser
+     * has a parent, and deregistration causes this phaser to have
+     * zero parties, this phaser also arrives at and is deregistered
+     * from its parent.  It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @return the arrival phase number, or a negative value if terminated
+     * @throws IllegalStateException if not terminated and the number
+     * of registered or unarrived parties would become negative
+     */
+    public int arriveAndDeregister() {
+        // similar code to arrive, but too different to merge
+        Phaser par = parent;
+        int phase;
+        for (;;) {
+            long s = state;
+            phase = phaseOf(s);
+            if (phase < 0)
+                break;
+            int parties = partiesOf(s) - 1;
+            int unarrived = unarrivedOf(s) - 1;
+            if (parties >= 0) {
+                if (unarrived > 0 || (unarrived == 0 && par != null)) {
+                    if (casState
+                        (s,
+                         stateFor(phase, parties, unarrived))) {
+                        if (unarrived == 0) {
+                            par.arriveAndDeregister();
+                            reconcileState();
+                        }
+                        break;
+                    }
+                    continue;
+                }
+                if (unarrived == 0) {
+                    if (casState
+                        (s,
+                         trippedStateFor(onAdvance(phase, parties) ? -1 :
+                                         ((phase + 1) & phaseMask), parties))) {
+                        releaseWaiters(phase);
+                        break;
+                    }
+                    continue;
+                }
+                if (par != null && phase != phaseOf(root.state)) {
+                    reconcileState();
+                    continue;
+                }
+            }
+            throw new IllegalStateException(badBounds(parties, unarrived));
+        }
+        return phase;
+    }
+
+    /**
+     * Arrives at the barrier and awaits others. Equivalent in effect
+     * to {@code awaitAdvance(arrive())}.  If you need to await with
+     * interruption or timeout, you can arrange this with an analogous
+     * construction using one of the other forms of the awaitAdvance
+     * method.  If instead you need to deregister upon arrival use
+     * {@code arriveAndDeregister}. It is an unenforced usage error
+     * for an unregistered party to invoke this method.
+     *
+     * @return the arrival phase number, or a negative number if terminated
+     * @throws IllegalStateException if not terminated and the number
+     * of unarrived parties would become negative
+     */
+    public int arriveAndAwaitAdvance() {
+        return awaitAdvance(arrive());
+    }
+
+    /**
+     * Awaits the phase of the barrier to advance from the given phase
+     * value, returning immediately if the current phase of the
+     * barrier is not equal to the given phase value or this barrier
+     * is terminated.  It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @param phase an arrival phase number, or negative value if
+     * terminated; this argument is normally the value returned by a
+     * previous call to {@code arrive} or its variants
+     * @return the next arrival phase number, or a negative value
+     * if terminated or argument is negative
+     */
+    public int awaitAdvance(int phase) {
+        if (phase < 0)
+            return phase;
+        long s = getReconciledState();
+        int p = phaseOf(s);
+        if (p != phase)
+            return p;
+        if (unarrivedOf(s) == 0 && parent != null)
+            parent.awaitAdvance(phase);
+        // Fall here even if parent waited, to reconcile and help release
+        return untimedWait(phase);
+    }
+
+    /**
+     * Awaits the phase of the barrier to advance from the given phase
+     * value, throwing {@code InterruptedException} if interrupted
+     * while waiting, or returning immediately if the current phase of
+     * the barrier is not equal to the given phase value or this
+     * barrier is terminated. It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @param phase an arrival phase number, or negative value if
+     * terminated; this argument is normally the value returned by a
+     * previous call to {@code arrive} or its variants
+     * @return the next arrival phase number, or a negative value
+     * if terminated or argument is negative
+     * @throws InterruptedException if thread interrupted while waiting
+     */
+    public int awaitAdvanceInterruptibly(int phase)
+        throws InterruptedException {
+        if (phase < 0)
+            return phase;
+        long s = getReconciledState();
+        int p = phaseOf(s);
+        if (p != phase)
+            return p;
+        if (unarrivedOf(s) == 0 && parent != null)
+            parent.awaitAdvanceInterruptibly(phase);
+        return interruptibleWait(phase);
+    }
+
+    /**
+     * Awaits the phase of the barrier to advance from the given phase
+     * value or the given timeout to elapse, throwing {@code
+     * InterruptedException} if interrupted while waiting, or
+     * returning immediately if the current phase of the barrier is
+     * not equal to the given phase value or this barrier is
+     * terminated.  It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @param phase an arrival phase number, or negative value if
+     * terminated; this argument is normally the value returned by a
+     * previous call to {@code arrive} or its variants
+     * @param timeout how long to wait before giving up, in units of
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the next arrival phase number, or a negative value
+     * if terminated or argument is negative
+     * @throws InterruptedException if thread interrupted while waiting
+     * @throws TimeoutException if timed out while waiting
+     */
+    public int awaitAdvanceInterruptibly(int phase,
+                                         long timeout, TimeUnit unit)
+        throws InterruptedException, TimeoutException {
+        if (phase < 0)
+            return phase;
+        long s = getReconciledState();
+        int p = phaseOf(s);
+        if (p != phase)
+            return p;
+        if (unarrivedOf(s) == 0 && parent != null)
+            parent.awaitAdvanceInterruptibly(phase, timeout, unit);
+        return timedWait(phase, unit.toNanos(timeout));
+    }
+
+    /**
+     * Forces this barrier to enter termination state. Counts of
+     * arrived and registered parties are unaffected. If this phaser
+     * has a parent, it too is terminated. This method may be useful
+     * for coordinating recovery after one or more tasks encounter
+     * unexpected exceptions.
+     */
+    public void forceTermination() {
+        for (;;) {
+            long s = getReconciledState();
+            int phase = phaseOf(s);
+            int parties = partiesOf(s);
+            int unarrived = unarrivedOf(s);
+            if (phase < 0 ||
+                casState(s, stateFor(-1, parties, unarrived))) {
+                releaseWaiters(0);
+                releaseWaiters(1);
+                if (parent != null)
+                    parent.forceTermination();
+                return;
+            }
+        }
+    }
+
+    /**
+     * Returns the current phase number. The maximum phase number is
+     * {@code Integer.MAX_VALUE}, after which it restarts at
+     * zero. Upon termination, the phase number is negative.
+     *
+     * @return the phase number, or a negative value if terminated
+     */
+    public final int getPhase() {
+        return phaseOf(getReconciledState());
+    }
+
+    /**
+     * Returns the number of parties registered at this barrier.
+     *
+     * @return the number of parties
+     */
+    public int getRegisteredParties() {
+        return partiesOf(state);
+    }
+
+    /**
+     * Returns the number of registered parties that have arrived at
+     * the current phase of this barrier.
+     *
+     * @return the number of arrived parties
+     */
+    public int getArrivedParties() {
+        return arrivedOf(state);
+    }
+
+    /**
+     * Returns the number of registered parties that have not yet
+     * arrived at the current phase of this barrier.
+     *
+     * @return the number of unarrived parties
+     */
+    public int getUnarrivedParties() {
+        return unarrivedOf(state);
+    }
+
+    /**
+     * Returns the parent of this phaser, or {@code null} if none.
+     *
+     * @return the parent of this phaser, or {@code null} if none
+     */
+    public Phaser getParent() {
+        return parent;
+    }
+
+    /**
+     * Returns the root ancestor of this phaser, which is the same as
+     * this phaser if it has no parent.
+     *
+     * @return the root ancestor of this phaser
+     */
+    public Phaser getRoot() {
+        return root;
+    }
+
+    /**
+     * Returns {@code true} if this barrier has been terminated.
+     *
+     * @return {@code true} if this barrier has been terminated
+     */
+    public boolean isTerminated() {
+        return getPhase() < 0;
+    }
+
+    /**
+     * Overridable method to perform an action upon impending phase
+     * advance, and to control termination. This method is invoked
+     * upon arrival of the party tripping the barrier (when all other
+     * waiting parties are dormant).  If this method returns {@code
+     * true}, then, rather than advance the phase number, this barrier
+     * will be set to a final termination state, and subsequent calls
+     * to {@link #isTerminated} will return true. Any (unchecked)
+     * Exception or Error thrown by an invocation of this method is
+     * propagated to the party attempting to trip the barrier, in
+     * which case no advance occurs.
+     *
+     * <p>The arguments to this method provide the state of the phaser
+     * prevailing for the current transition. (When called from within
+     * an implementation of {@code onAdvance} the values returned by
+     * methods such as {@code getPhase} may or may not reliably
+     * indicate the state to which this transition applies.)
+     *
+     * <p>The default version returns {@code true} when the number of
+     * registered parties is zero. Normally, overrides that arrange
+     * termination for other reasons should also preserve this
+     * property.
+     *
+     * <p>You may override this method to perform an action with side
+     * effects visible to participating tasks, but it is only sensible
+     * to do so in designs where all parties register before any
+     * arrive, and all {@link #awaitAdvance} at each phase.
+     * Otherwise, you cannot ensure lack of interference from other
+     * parties during the invocation of this method. Additionally,
+     * method {@code onAdvance} may be invoked more than once per
+     * transition if registrations are intermixed with arrivals.
+     *
+     * @param phase the phase number on entering the barrier
+     * @param registeredParties the current number of registered parties
+     * @return {@code true} if this barrier should terminate
+     */
+    protected boolean onAdvance(int phase, int registeredParties) {
+        return registeredParties <= 0;
+    }
+
+    /**
+     * Returns a string identifying this phaser, as well as its
+     * state.  The state, in brackets, includes the String {@code
+     * "phase = "} followed by the phase number, {@code "parties = "}
+     * followed by the number of registered parties, and {@code
+     * "arrived = "} followed by the number of arrived parties.
+     *
+     * @return a string identifying this barrier, as well as its state
+     */
+    public String toString() {
+        long s = getReconciledState();
+        return super.toString() +
+            "[phase = " + phaseOf(s) +
+            " parties = " + partiesOf(s) +
+            " arrived = " + arrivedOf(s) + "]";
+    }
+
+    // methods for waiting
+
+    /**
+     * Wait nodes for Treiber stack representing wait queue
+     */
+    static final class QNode implements ForkJoinPool.ManagedBlocker {
+        final Phaser phaser;
+        final int phase;
+        final long startTime;
+        final long nanos;
+        final boolean timed;
+        final boolean interruptible;
+        volatile boolean wasInterrupted = false;
+        volatile Thread thread; // nulled to cancel wait
+        QNode next;
+        QNode(Phaser phaser, int phase, boolean interruptible,
+              boolean timed, long startTime, long nanos) {
+            this.phaser = phaser;
+            this.phase = phase;
+            this.timed = timed;
+            this.interruptible = interruptible;
+            this.startTime = startTime;
+            this.nanos = nanos;
+            thread = Thread.currentThread();
+        }
+        public boolean isReleasable() {
+            return (thread == null ||
+                    phaser.getPhase() != phase ||
+                    (interruptible && wasInterrupted) ||
+                    (timed && (nanos - (System.nanoTime() - startTime)) <= 0));
+        }
+        public boolean block() {
+            if (Thread.interrupted()) {
+                wasInterrupted = true;
+                if (interruptible)
+                    return true;
+            }
+            if (!timed)
+                LockSupport.park(this);
+            else {
+                long waitTime = nanos - (System.nanoTime() - startTime);
+                if (waitTime <= 0)
+                    return true;
+                LockSupport.parkNanos(this, waitTime);
+            }
+            return isReleasable();
+        }
+        void signal() {
+            Thread t = thread;
+            if (t != null) {
+                thread = null;
+                LockSupport.unpark(t);
+            }
+        }
+        boolean doWait() {
+            if (thread != null) {
+                try {
+                    ForkJoinPool.managedBlock(this, false);
+                } catch (InterruptedException ie) {
+                }
+            }
+            return wasInterrupted;
+        }
+
+    }
+
+    /**
+     * Removes and signals waiting threads from wait queue.
+     */
+    private void releaseWaiters(int phase) {
+        AtomicReference<QNode> head = queueFor(phase);
+        QNode q;
+        while ((q = head.get()) != null) {
+            if (head.compareAndSet(q, q.next))
+                q.signal();
+        }
+    }
+
+    /**
+     * Tries to enqueue given node in the appropriate wait queue.
+     *
+     * @return true if successful
+     */
+    private boolean tryEnqueue(QNode node) {
+        AtomicReference<QNode> head = queueFor(node.phase);
+        return head.compareAndSet(node.next = head.get(), node);
+    }
+
+    /**
+     * Enqueues node and waits unless aborted or signalled.
+     *
+     * @return current phase
+     */
+    private int untimedWait(int phase) {
+        QNode node = null;
+        boolean queued = false;
+        boolean interrupted = false;
+        int p;
+        while ((p = getPhase()) == phase) {
+            if (Thread.interrupted())
+                interrupted = true;
+            else if (node == null)
+                node = new QNode(this, phase, false, false, 0, 0);
+            else if (!queued)
+                queued = tryEnqueue(node);
+            else
+                interrupted = node.doWait();
+        }
+        if (node != null)
+            node.thread = null;
+        releaseWaiters(phase);
+        if (interrupted)
+            Thread.currentThread().interrupt();
+        return p;
+    }
+
+    /**
+     * Interruptible version
+     * @return current phase
+     */
+    private int interruptibleWait(int phase) throws InterruptedException {
+        QNode node = null;
+        boolean queued = false;
+        boolean interrupted = false;
+        int p;
+        while ((p = getPhase()) == phase && !interrupted) {
+            if (Thread.interrupted())
+                interrupted = true;
+            else if (node == null)
+                node = new QNode(this, phase, true, false, 0, 0);
+            else if (!queued)
+                queued = tryEnqueue(node);
+            else
+                interrupted = node.doWait();
+        }
+        if (node != null)
+            node.thread = null;
+        if (p != phase || (p = getPhase()) != phase)
+            releaseWaiters(phase);
+        if (interrupted)
+            throw new InterruptedException();
+        return p;
+    }
+
+    /**
+     * Timeout version.
+     * @return current phase
+     */
+    private int timedWait(int phase, long nanos)
+        throws InterruptedException, TimeoutException {
+        long startTime = System.nanoTime();
+        QNode node = null;
+        boolean queued = false;
+        boolean interrupted = false;
+        int p;
+        while ((p = getPhase()) == phase && !interrupted) {
+            if (Thread.interrupted())
+                interrupted = true;
+            else if (nanos - (System.nanoTime() - startTime) <= 0)
+                break;
+            else if (node == null)
+                node = new QNode(this, phase, true, true, startTime, nanos);
+            else if (!queued)
+                queued = tryEnqueue(node);
+            else
+                interrupted = node.doWait();
+        }
+        if (node != null)
+            node.thread = null;
+        if (p != phase || (p = getPhase()) != phase)
+            releaseWaiters(phase);
+        if (interrupted)
+            throw new InterruptedException();
+        if (p == phase)
+            throw new TimeoutException();
+        return p;
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long stateOffset =
+        objectFieldOffset("state", Phaser.class);
+
+    private final boolean casState(long cmp, long val) {
+        return UNSAFE.compareAndSwapLong(this, stateOffset, cmp, val);
+    }
+
+    private static long objectFieldOffset(String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,179 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A recursive resultless {@link ForkJoinTask}.  This class
+ * establishes conventions to parameterize resultless actions as
+ * {@code Void} {@code ForkJoinTask}s. Because {@code null} is the
+ * only valid value of type {@code Void}, methods such as join always
+ * return {@code null} upon completion.
+ *
+ * <p><b>Sample Usages.</b> Here is a sketch of a ForkJoin sort that
+ * sorts a given {@code long[]} array:
+ *
+ *  <pre> {@code
+ * class SortTask extends RecursiveAction {
+ *   final long[] array; final int lo; final int hi;
+ *   SortTask(long[] array, int lo, int hi) {
+ *     this.array = array; this.lo = lo; this.hi = hi;
+ *   }
+ *   protected void compute() {
+ *     if (hi - lo < THRESHOLD)
+ *       sequentiallySort(array, lo, hi);
+ *     else {
+ *       int mid = (lo + hi) >>> 1;
+ *       invokeAll(new SortTask(array, lo, mid),
+ *                 new SortTask(array, mid, hi));
+ *       merge(array, lo, hi);
+ *     }
+ *   }
+ * }}</pre>
+ *
+ * You could then sort {@code anArray} by creating {@code new
+ * SortTask(anArray, 0, anArray.length-1) } and invoking it in a
+ * ForkJoinPool.  As a more concrete simple example, the following
+ * task increments each element of an array:
+ *  <pre> {@code
+ * class IncrementTask extends RecursiveAction {
+ *   final long[] array; final int lo; final int hi;
+ *   IncrementTask(long[] array, int lo, int hi) {
+ *     this.array = array; this.lo = lo; this.hi = hi;
+ *   }
+ *   protected void compute() {
+ *     if (hi - lo < THRESHOLD) {
+ *       for (int i = lo; i < hi; ++i)
+ *         array[i]++;
+ *     }
+ *     else {
+ *       int mid = (lo + hi) >>> 1;
+ *       invokeAll(new IncrementTask(array, lo, mid),
+ *                 new IncrementTask(array, mid, hi));
+ *     }
+ *   }
+ * }}</pre>
+ *
+ * <p>The following example illustrates some refinements and idioms
+ * that may lead to better performance: RecursiveActions need not be
+ * fully recursive, so long as they maintain the basic
+ * divide-and-conquer approach. Here is a class that sums the squares
+ * of each element of a double array, by subdividing out only the
+ * right-hand-sides of repeated divisions by two, and keeping track of
+ * them with a chain of {@code next} references. It uses a dynamic
+ * threshold based on method {@code getSurplusQueuedTaskCount}, but
+ * counterbalances potential excess partitioning by directly
+ * performing leaf actions on unstolen tasks rather than further
+ * subdividing.
+ *
+ *  <pre> {@code
+ * double sumOfSquares(ForkJoinPool pool, double[] array) {
+ *   int n = array.length;
+ *   Applyer a = new Applyer(array, 0, n, null);
+ *   pool.invoke(a);
+ *   return a.result;
+ * }
+ *
+ * class Applyer extends RecursiveAction {
+ *   final double[] array;
+ *   final int lo, hi;
+ *   double result;
+ *   Applyer next; // keeps track of right-hand-side tasks
+ *   Applyer(double[] array, int lo, int hi, Applyer next) {
+ *     this.array = array; this.lo = lo; this.hi = hi;
+ *     this.next = next;
+ *   }
+ *
+ *   double atLeaf(int l, int h) {
+ *     double sum = 0;
+ *     for (int i = l; i < h; ++i) // perform leftmost base step
+ *       sum += array[i] * array[i];
+ *     return sum;
+ *   }
+ *
+ *   protected void compute() {
+ *     int l = lo;
+ *     int h = hi;
+ *     Applyer right = null;
+ *     while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
+ *        int mid = (l + h) >>> 1;
+ *        right = new Applyer(array, mid, h, right);
+ *        right.fork();
+ *        h = mid;
+ *     }
+ *     double sum = atLeaf(l, h);
+ *     while (right != null) {
+ *        if (right.tryUnfork()) // directly calculate if not stolen
+ *          sum += right.atLeaf(right.lo, right.hi);
+ *       else {
+ *          right.helpJoin();
+ *          sum += right.result;
+ *        }
+ *        right = right.next;
+ *      }
+ *     result = sum;
+ *   }
+ * }}</pre>
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public abstract class RecursiveAction extends ForkJoinTask<Void> {
+    private static final long serialVersionUID = 5232453952276485070L;
+
+    /**
+     * The main computation performed by this task.
+     */
+    protected abstract void compute();
+
+    /**
+     * Always returns null.
+     */
+    public final Void getRawResult() { return null; }
+
+    /**
+     * Requires null completion value.
+     */
+    protected final void setRawResult(Void mustBeNull) { }
+
+    /**
+     * Implements execution conventions for RecursiveActions.
+     */
+    protected final boolean exec() {
+        compute();
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/RecursiveTask.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A recursive result-bearing {@link ForkJoinTask}.
+ *
+ * <p>For a classic example, here is a task computing Fibonacci numbers:
+ *
+ *  <pre> {@code
+ * class Fibonacci extends RecursiveTask<Integer> {
+ *   final int n;
+ *   Fibonacci(int n) { this.n = n; }
+ *   Integer compute() {
+ *     if (n <= 1)
+ *        return n;
+ *     Fibonacci f1 = new Fibonacci(n - 1);
+ *     f1.fork();
+ *     Fibonacci f2 = new Fibonacci(n - 2);
+ *     return f2.compute() + f1.join();
+ *   }
+ * }}</pre>
+ *
+ * However, besides being a dumb way to compute Fibonacci functions
+ * (there is a simple fast linear algorithm that you'd use in
+ * practice), this is likely to perform poorly because the smallest
+ * subtasks are too small to be worthwhile splitting up. Instead, as
+ * is the case for nearly all fork/join applications, you'd pick some
+ * minimum granularity size (for example 10 here) for which you always
+ * sequentially solve rather than subdividing.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
+    private static final long serialVersionUID = 5232453952276485270L;
+
+    /**
+     * The result of the computation.
+     */
+    V result;
+
+    /**
+     * The main computation performed by this task.
+     */
+    protected abstract V compute();
+
+    public final V getRawResult() {
+        return result;
+    }
+
+    protected final void setRawResult(V value) {
+        result = value;
+    }
+
+    /**
+     * Implements execution conventions for RecursiveTask.
+     */
+    protected final boolean exec() {
+        result = compute();
+        return true;
+    }
+
+}
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java	Wed Jul 05 17:02:54 2017 +0200
@@ -61,6 +61,14 @@
  * causes tasks to be immediately removed from the work queue at
  * time of cancellation.
  *
+ * <p>Successive executions of a task scheduled via
+ * <code>scheduleAtFixedRate</code> or
+ * <code>scheduleWithFixedDelay</code> do not overlap. While different
+ * executions may be performed by different threads, the effects of
+ * prior executions <a
+ * href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * those of subsequent ones.
+ *
  * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
  * of the inherited tuning methods are not useful for it. In
  * particular, because it acts as a fixed-sized pool using
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,228 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.Random;
+
+/**
+ * A random number generator isolated to the current thread.  Like the
+ * global {@link java.util.Random} generator used by the {@link
+ * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
+ * with an internally generated seed that may not otherwise be
+ * modified. When applicable, use of {@code ThreadLocalRandom} rather
+ * than shared {@code Random} objects in concurrent programs will
+ * typically encounter much less overhead and contention.  Use of
+ * {@code ThreadLocalRandom} is particularly appropriate when multiple
+ * tasks (for example, each a {@link ForkJoinTask}) use random numbers
+ * in parallel in thread pools.
+ *
+ * <p>Usages of this class should typically be of the form:
+ * {@code ThreadLocalRandom.current().nextX(...)} (where
+ * {@code X} is {@code Int}, {@code Long}, etc).
+ * When all usages are of this form, it is never possible to
+ * accidently share a {@code ThreadLocalRandom} across multiple threads.
+ *
+ * <p>This class also provides additional commonly used bounded random
+ * generation methods.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ThreadLocalRandom extends Random {
+    // same constants as Random, but must be redeclared because private
+    private final static long multiplier = 0x5DEECE66DL;
+    private final static long addend = 0xBL;
+    private final static long mask = (1L << 48) - 1;
+
+    /**
+     * The random seed. We can't use super.seed.
+     */
+    private long rnd;
+
+    /**
+     * Initialization flag to permit the first and only allowed call
+     * to setSeed (inside Random constructor) to succeed.  We can't
+     * allow others since it would cause setting seed in one part of a
+     * program to unintentionally impact other usages by the thread.
+     */
+    boolean initialized;
+
+    // Padding to help avoid memory contention among seed updates in
+    // different TLRs in the common case that they are located near
+    // each other.
+    private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
+
+    /**
+     * The actual ThreadLocal
+     */
+    private static final ThreadLocal<ThreadLocalRandom> localRandom =
+        new ThreadLocal<ThreadLocalRandom>() {
+            protected ThreadLocalRandom initialValue() {
+                return new ThreadLocalRandom();
+            }
+    };
+
+
+    /**
+     * Constructor called only by localRandom.initialValue.
+     * We rely on the fact that the superclass no-arg constructor
+     * invokes setSeed exactly once to initialize.
+     */
+    ThreadLocalRandom() {
+        super();
+    }
+
+    /**
+     * Returns the current thread's {@code ThreadLocalRandom}.
+     *
+     * @return the current thread's {@code ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom current() {
+        return localRandom.get();
+    }
+
+    /**
+     * Throws {@code UnsupportedOperationException}.  Setting seeds in
+     * this generator is not supported.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    public void setSeed(long seed) {
+        if (initialized)
+            throw new UnsupportedOperationException();
+        initialized = true;
+        rnd = (seed ^ multiplier) & mask;
+    }
+
+    protected int next(int bits) {
+        rnd = (rnd * multiplier + addend) & mask;
+        return (int) (rnd >>> (48-bits));
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
+     *
+     * @param least the least value returned
+     * @param bound the upper bound (exclusive)
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
+     * @return the next value
+     */
+    public int nextInt(int least, int bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextInt(bound - least) + least;
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value
+     * between 0 (inclusive) and the specified value (exclusive).
+     *
+     * @param n the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return the next value
+     * @throws IllegalArgumentException if n is not positive
+     */
+    public long nextLong(long n) {
+        if (n <= 0)
+            throw new IllegalArgumentException("n must be positive");
+        // Divide n by two until small enough for nextInt. On each
+        // iteration (at most 31 of them but usually much less),
+        // randomly choose both whether to include high bit in result
+        // (offset) and whether to continue with the lower vs upper
+        // half (which makes a difference only if odd).
+        long offset = 0;
+        while (n >= Integer.MAX_VALUE) {
+            int bits = next(2);
+            long half = n >>> 1;
+            long nextn = ((bits & 2) == 0) ? half : n - half;
+            if ((bits & 1) == 0)
+                offset += n - nextn;
+            n = nextn;
+        }
+        return offset + nextInt((int) n);
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
+     *
+     * @param least the least value returned
+     * @param bound the upper bound (exclusive)
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
+     */
+    public long nextLong(long least, long bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextLong(bound - least) + least;
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed {@code double} value
+     * between 0 (inclusive) and the specified value (exclusive).
+     *
+     * @param n the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return the next value
+     * @throws IllegalArgumentException if n is not positive
+     */
+    public double nextDouble(double n) {
+        if (n <= 0)
+            throw new IllegalArgumentException("n must be positive");
+        return nextDouble() * n;
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
+     *
+     * @param least the least value returned
+     * @param bound the upper bound (exclusive)
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
+     */
+    public double nextDouble(double least, double bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextDouble() * (bound - least) + least;
+    }
+
+    private static final long serialVersionUID = -5851777807851030925L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/TransferQueue.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,161 @@
+/*
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link BlockingQueue} in which producers may wait for consumers
+ * to receive elements.  A {@code TransferQueue} may be useful for
+ * example in message passing applications in which producers
+ * sometimes (using method {@link #transfer}) await receipt of
+ * elements by consumers invoking {@code take} or {@code poll}, while
+ * at other times enqueue elements (via method {@code put}) without
+ * waiting for receipt.
+ * {@linkplain #tryTransfer(Object) Non-blocking} and
+ * {@linkplain #tryTransfer(Object,long,TimeUnit) time-out} versions of
+ * {@code tryTransfer} are also available.
+ * A {@code TransferQueue} may also be queried, via {@link
+ * #hasWaitingConsumer}, whether there are any threads waiting for
+ * items, which is a converse analogy to a {@code peek} operation.
+ *
+ * <p>Like other blocking queues, a {@code TransferQueue} may be
+ * capacity bounded.  If so, an attempted transfer operation may
+ * initially block waiting for available space, and/or subsequently
+ * block waiting for reception by a consumer.  Note that in a queue
+ * with zero capacity, such as {@link SynchronousQueue}, {@code put}
+ * and {@code transfer} are effectively synonymous.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface TransferQueue<E> extends BlockingQueue<E> {
+    /**
+     * Transfers the element to a waiting consumer immediately, if possible.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * otherwise returning {@code false} without enqueuing the element.
+     *
+     * @param e the element to transfer
+     * @return {@code true} if the element was transferred, else
+     *         {@code false}
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    boolean tryTransfer(E e);
+
+    /**
+     * Transfers the element to a consumer, waiting if necessary to do so.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else waits until the element is received by a consumer.
+     *
+     * @param e the element to transfer
+     * @throws InterruptedException if interrupted while waiting,
+     *         in which case the element is not left enqueued
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    void transfer(E e) throws InterruptedException;
+
+    /**
+     * Transfers the element to a consumer if it is possible to do so
+     * before the timeout elapses.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else waits until the element is received by a consumer,
+     * returning {@code false} if the specified wait time elapses
+     * before the element can be transferred.
+     *
+     * @param e the element to transfer
+     * @param timeout how long to wait before giving up, in units of
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
+     *         the specified waiting time elapses before completion,
+     *         in which case the element is not left enqueued
+     * @throws InterruptedException if interrupted while waiting,
+     *         in which case the element is not left enqueued
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    boolean tryTransfer(E e, long timeout, TimeUnit unit)
+        throws InterruptedException;
+
+    /**
+     * Returns {@code true} if there is at least one consumer waiting
+     * to receive an element via {@link #take} or
+     * timed {@link #poll(long,TimeUnit) poll}.
+     * The return value represents a momentary state of affairs.
+     *
+     * @return {@code true} if there is at least one waiting consumer
+     */
+    boolean hasWaitingConsumer();
+
+    /**
+     * Returns an estimate of the number of consumers waiting to
+     * receive elements via {@link #take} or timed
+     * {@link #poll(long,TimeUnit) poll}.  The return value is an
+     * approximation of a momentary state of affairs, that may be
+     * inaccurate if consumers have completed or given up waiting.
+     * The value may be useful for monitoring and heuristics, but
+     * not for synchronization control.  Implementations of this
+     * method are likely to be noticeably slower than those for
+     * {@link #hasWaitingConsumer}.
+     *
+     * @return the number of consumers waiting to receive elements
+     */
+    int getWaitingConsumerCount();
+}
--- a/jdk/src/share/classes/java/util/concurrent/locks/Condition.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/locks/Condition.java	Wed Jul 05 17:02:54 2017 +0200
@@ -170,8 +170,8 @@
  * <p>As interruption generally implies cancellation, and checks for
  * interruption are often infrequent, an implementation can favor responding
  * to an interrupt over normal method return. This is true even if it can be
- * shown that the interrupt occurred after another action may have unblocked
- * the thread. An implementation should document this behavior.
+ * shown that the interrupt occurred after another action that may have
+ * unblocked the thread. An implementation should document this behavior.
  *
  * @since 1.5
  * @author Doug Lea
--- a/jdk/src/share/classes/java/util/concurrent/package-info.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/package-info.java	Wed Jul 05 17:02:54 2017 +0200
@@ -92,6 +92,13 @@
  * assists in coordinating the processing of groups of
  * asynchronous tasks.
  *
+ * <p>Class {@link java.util.concurrent.ForkJoinPool} provides an
+ * Executor primarily designed for processing instances of {@link
+ * java.util.concurrent.ForkJoinTask} and its subclasses.  These
+ * classes employ a work-stealing scheduler that attains high
+ * throughput for tasks conforming to restrictions that often hold in
+ * computation-intensive parallel processing.
+ *
  * <h2>Queues</h2>
  *
  * The {@link java.util.concurrent.ConcurrentLinkedQueue} class
@@ -110,6 +117,12 @@
  * for producer-consumer, messaging, parallel tasking, and
  * related concurrent designs.
  *
+ * <p> Extended interface {@link java.util.concurrent.TransferQueue},
+ * and implementation {@link java.util.concurrent.LinkedTransferQueue}
+ * introduce a synchronous {@code transfer} method (along with related
+ * features) in which a producer may optionally block awaiting its
+ * consumer.
+ *
  * <p>The {@link java.util.concurrent.BlockingDeque} interface
  * extends {@code BlockingQueue} to support both FIFO and LIFO
  * (stack-based) operations.
@@ -136,15 +149,28 @@
  *
  * <h2>Synchronizers</h2>
  *
- * Four classes aid common special-purpose synchronization idioms.
- * {@link java.util.concurrent.Semaphore} is a classic concurrency tool.
- * {@link java.util.concurrent.CountDownLatch} is a very simple yet very
- * common utility for blocking until a given number of signals, events,
- * or conditions hold.  A {@link java.util.concurrent.CyclicBarrier} is a
- * resettable multiway synchronization point useful in some styles of
- * parallel programming.  An {@link java.util.concurrent.Exchanger} allows
- * two threads to exchange objects at a rendezvous point, and is useful
- * in several pipeline designs.
+ * Five classes aid common special-purpose synchronization idioms.
+ * <ul>
+ *
+ * <li>{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
+ *
+ * <li>{@link java.util.concurrent.CountDownLatch} is a very simple yet
+ * very common utility for blocking until a given number of signals,
+ * events, or conditions hold.
+ *
+ * <li>A {@link java.util.concurrent.CyclicBarrier} is a resettable
+ * multiway synchronization point useful in some styles of parallel
+ * programming.
+ *
+ * <li>A {@link java.util.concurrent.Phaser} provides
+ * a more flexible form of barrier that may be used to control phased
+ * computation among multiple threads.
+ *
+ * <li>An {@link java.util.concurrent.Exchanger} allows two threads to
+ * exchange objects at a rendezvous point, and is useful in several
+ * pipeline designs.
+ *
+ * </ul>
  *
  * <h2>Concurrent Collections</h2>
  *
@@ -259,7 +285,8 @@
  *   in each thread <i>happen-before</i> those subsequent to the
  *   corresponding {@code exchange()} in another thread.
  *
- *   <li>Actions prior to calling {@code CyclicBarrier.await}
+ *   <li>Actions prior to calling {@code CyclicBarrier.await} and
+ *   {@code Phaser.awaitAdvance} (as well as its variants)
  *   <i>happen-before</i> actions performed by the barrier action, and
  *   actions performed by the barrier action <i>happen-before</i> actions
  *   subsequent to a successful return from the corresponding {@code await}
--- a/jdk/src/share/classes/sun/misc/Version-template.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +0,0 @@
-/*
- * Copyright 1999-2007 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-package sun.misc;
-import java.io.PrintStream;
-
-public class Version {
-
-
-    private static final String launcher_name =
-        "@@launcher_name@@";
-
-    private static final String java_version =
-        "@@java_version@@";
-
-    private static final String java_runtime_name =
-        "@@java_runtime_name@@";
-
-    private static final String java_runtime_version =
-        "@@java_runtime_version@@";
-
-    static {
-        init();
-    }
-
-    public static void init() {
-        System.setProperty("java.version", java_version);
-        System.setProperty("java.runtime.version", java_runtime_version);
-        System.setProperty("java.runtime.name", java_runtime_name);
-    }
-
-    private static boolean versionsInitialized = false;
-    private static int jvm_major_version = 0;
-    private static int jvm_minor_version = 0;
-    private static int jvm_micro_version = 0;
-    private static int jvm_update_version = 0;
-    private static int jvm_build_number = 0;
-    private static String jvm_special_version = null;
-    private static int jdk_major_version = 0;
-    private static int jdk_minor_version = 0;
-    private static int jdk_micro_version = 0;
-    private static int jdk_update_version = 0;
-    private static int jdk_build_number = 0;
-    private static String jdk_special_version = null;
-
-    /**
-     * In case you were wondering this method is called by java -version.
-     * Sad that it prints to stderr; would be nicer if default printed on
-     * stdout.
-     */
-    public static void print() {
-        print(System.err);
-    }
-
-    /**
-     * This is the same as print except that it adds an extra line-feed
-     * at the end, typically used by the -showversion in the launcher
-     */
-    public static void println() {
-        print(System.err);
-        System.err.println();
-    }
-
-    /**
-     * Give a stream, it will print version info on it.
-     */
-    public static void print(PrintStream ps) {
-        /* First line: platform version. */
-        ps.println(launcher_name + " version \"" + java_version + "\"");
-
-        /* Second line: runtime version (ie, libraries). */
-        ps.println(java_runtime_name + " (build " +
-                           java_runtime_version + ")");
-
-        /* Third line: JVM information. */
-        String java_vm_name    = System.getProperty("java.vm.name");
-        String java_vm_version = System.getProperty("java.vm.version");
-        String java_vm_info    = System.getProperty("java.vm.info");
-        ps.println(java_vm_name + " (build " + java_vm_version + ", " +
-                   java_vm_info + ")");
-    }
-
-
-    /**
-     * Returns the major version of the running JVM if it's 1.6 or newer
-     * or any RE VM build. It will return 0 if it's an internal 1.5 or
-     * 1.4.x build.
-     *
-     * @since 1.6
-     */
-    public static synchronized int jvmMajorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_major_version;
-    }
-
-    /**
-     * Returns the minor version of the running JVM if it's 1.6 or newer
-     * or any RE VM build. It will return 0 if it's an internal 1.5 or
-     * 1.4.x build.
-     * @since 1.6
-     */
-    public static synchronized int jvmMinorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_minor_version;
-    }
-
-
-    /**
-     * Returns the micro version of the running JVM if it's 1.6 or newer
-     * or any RE VM build. It will return 0 if it's an internal 1.5 or
-     * 1.4.x build.
-     * @since 1.6
-     */
-    public static synchronized int jvmMicroVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_micro_version;
-    }
-
-    /**
-     * Returns the update release version of the running JVM if it's
-     * a RE build. It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jvmUpdateVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_update_version;
-    }
-
-    public static synchronized String jvmSpecialVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        if (jvm_special_version == null) {
-            jvm_special_version = getJvmSpecialVersion();
-        }
-        return jvm_special_version;
-    }
-    public static native String getJvmSpecialVersion();
-
-    /**
-     * Returns the build number of the running JVM if it's a RE build
-     * It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jvmBuildNumber() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_build_number;
-    }
-
-    /**
-     * Returns the major version of the running JDK.
-     *
-     * @since 1.6
-     */
-    public static synchronized int jdkMajorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_major_version;
-    }
-
-    /**
-     * Returns the minor version of the running JDK.
-     * @since 1.6
-     */
-    public static synchronized int jdkMinorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_minor_version;
-    }
-
-    /**
-     * Returns the micro version of the running JDK.
-     * @since 1.6
-     */
-    public static synchronized int jdkMicroVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_micro_version;
-    }
-
-    /**
-     * Returns the update release version of the running JDK if it's
-     * a RE build. It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jdkUpdateVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_update_version;
-    }
-
-    public static synchronized String jdkSpecialVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        if (jdk_special_version == null) {
-            jdk_special_version = getJdkSpecialVersion();
-        }
-        return jdk_special_version;
-    }
-    public static native String getJdkSpecialVersion();
-
-    /**
-     * Returns the build number of the running JDK if it's a RE build
-     * It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jdkBuildNumber() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_build_number;
-    }
-
-    // true if JVM exports the version info including the capabilities
-    private static boolean jvmVersionInfoAvailable;
-    private static synchronized void initVersions() {
-        if (versionsInitialized) {
-            return;
-        }
-        jvmVersionInfoAvailable = getJvmVersionInfo();
-        if (!jvmVersionInfoAvailable) {
-            // parse java.vm.version for older JVM before the
-            // new JVM_GetVersionInfo is added.
-            // valid format of the version string is:
-            // n.n.n[_uu[c]][-<identifer>]-bxx
-            CharSequence cs = System.getProperty("java.vm.version");
-            if (cs.length() >= 5 &&
-                Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
-                Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
-                Character.isDigit(cs.charAt(4))) {
-                jvm_major_version = Character.digit(cs.charAt(0), 10);
-                jvm_minor_version = Character.digit(cs.charAt(2), 10);
-                jvm_micro_version = Character.digit(cs.charAt(4), 10);
-                cs = cs.subSequence(5, cs.length());
-                if (cs.charAt(0) == '_' && cs.length() >= 3 &&
-                    Character.isDigit(cs.charAt(1)) &&
-                    Character.isDigit(cs.charAt(2))) {
-                    int nextChar = 3;
-                    try {
-                        String uu = cs.subSequence(1, 3).toString();
-                        jvm_update_version = Integer.valueOf(uu).intValue();
-                        if (cs.length() >= 4) {
-                            char c = cs.charAt(3);
-                            if (c >= 'a' && c <= 'z') {
-                                jvm_special_version = Character.toString(c);
-                                nextChar++;
-                            }
-                        }
-                    } catch (NumberFormatException e) {
-                        // not conforming to the naming convention
-                        return;
-                    }
-                    cs = cs.subSequence(nextChar, cs.length());
-                }
-                if (cs.charAt(0) == '-') {
-                    // skip the first character
-                    // valid format: <identifier>-bxx or bxx
-                    // non-product VM will have -debug|-release appended
-                    cs = cs.subSequence(1, cs.length());
-                    String[] res = cs.toString().split("-");
-                    for (String s : res) {
-                        if (s.charAt(0) == 'b' && s.length() == 3 &&
-                            Character.isDigit(s.charAt(1)) &&
-                            Character.isDigit(s.charAt(2))) {
-                            jvm_build_number =
-                                Integer.valueOf(s.substring(1, 3)).intValue();
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        getJdkVersionInfo();
-        versionsInitialized = true;
-    }
-
-    // Gets the JVM version info if available and sets the jvm_*_version fields
-    // and its capabilities.
-    //
-    // Return false if not available which implies an old VM (Tiger or before).
-    private static native boolean getJvmVersionInfo();
-    private static native void getJdkVersionInfo();
-
-}
-
-// Help Emacs a little because this file doesn't end in .java.
-//
-// Local Variables: ***
-// mode: java ***
-// End: ***
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/Version.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,327 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+package sun.misc;
+import java.io.PrintStream;
+
+public class Version {
+
+
+    private static final String launcher_name =
+        "@@launcher_name@@";
+
+    private static final String java_version =
+        "@@java_version@@";
+
+    private static final String java_runtime_name =
+        "@@java_runtime_name@@";
+
+    private static final String java_runtime_version =
+        "@@java_runtime_version@@";
+
+    static {
+        init();
+    }
+
+    public static void init() {
+        System.setProperty("java.version", java_version);
+        System.setProperty("java.runtime.version", java_runtime_version);
+        System.setProperty("java.runtime.name", java_runtime_name);
+    }
+
+    private static boolean versionsInitialized = false;
+    private static int jvm_major_version = 0;
+    private static int jvm_minor_version = 0;
+    private static int jvm_micro_version = 0;
+    private static int jvm_update_version = 0;
+    private static int jvm_build_number = 0;
+    private static String jvm_special_version = null;
+    private static int jdk_major_version = 0;
+    private static int jdk_minor_version = 0;
+    private static int jdk_micro_version = 0;
+    private static int jdk_update_version = 0;
+    private static int jdk_build_number = 0;
+    private static String jdk_special_version = null;
+
+    /**
+     * In case you were wondering this method is called by java -version.
+     * Sad that it prints to stderr; would be nicer if default printed on
+     * stdout.
+     */
+    public static void print() {
+        print(System.err);
+    }
+
+    /**
+     * This is the same as print except that it adds an extra line-feed
+     * at the end, typically used by the -showversion in the launcher
+     */
+    public static void println() {
+        print(System.err);
+        System.err.println();
+    }
+
+    /**
+     * Give a stream, it will print version info on it.
+     */
+    public static void print(PrintStream ps) {
+        /* First line: platform version. */
+        ps.println(launcher_name + " version \"" + java_version + "\"");
+
+        /* Second line: runtime version (ie, libraries). */
+        ps.println(java_runtime_name + " (build " +
+                           java_runtime_version + ")");
+
+        /* Third line: JVM information. */
+        String java_vm_name    = System.getProperty("java.vm.name");
+        String java_vm_version = System.getProperty("java.vm.version");
+        String java_vm_info    = System.getProperty("java.vm.info");
+        ps.println(java_vm_name + " (build " + java_vm_version + ", " +
+                   java_vm_info + ")");
+    }
+
+
+    /**
+     * Returns the major version of the running JVM if it's 1.6 or newer
+     * or any RE VM build. It will return 0 if it's an internal 1.5 or
+     * 1.4.x build.
+     *
+     * @since 1.6
+     */
+    public static synchronized int jvmMajorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_major_version;
+    }
+
+    /**
+     * Returns the minor version of the running JVM if it's 1.6 or newer
+     * or any RE VM build. It will return 0 if it's an internal 1.5 or
+     * 1.4.x build.
+     * @since 1.6
+     */
+    public static synchronized int jvmMinorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_minor_version;
+    }
+
+
+    /**
+     * Returns the micro version of the running JVM if it's 1.6 or newer
+     * or any RE VM build. It will return 0 if it's an internal 1.5 or
+     * 1.4.x build.
+     * @since 1.6
+     */
+    public static synchronized int jvmMicroVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_micro_version;
+    }
+
+    /**
+     * Returns the update release version of the running JVM if it's
+     * a RE build. It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jvmUpdateVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_update_version;
+    }
+
+    public static synchronized String jvmSpecialVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        if (jvm_special_version == null) {
+            jvm_special_version = getJvmSpecialVersion();
+        }
+        return jvm_special_version;
+    }
+    public static native String getJvmSpecialVersion();
+
+    /**
+     * Returns the build number of the running JVM if it's a RE build
+     * It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jvmBuildNumber() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_build_number;
+    }
+
+    /**
+     * Returns the major version of the running JDK.
+     *
+     * @since 1.6
+     */
+    public static synchronized int jdkMajorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_major_version;
+    }
+
+    /**
+     * Returns the minor version of the running JDK.
+     * @since 1.6
+     */
+    public static synchronized int jdkMinorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_minor_version;
+    }
+
+    /**
+     * Returns the micro version of the running JDK.
+     * @since 1.6
+     */
+    public static synchronized int jdkMicroVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_micro_version;
+    }
+
+    /**
+     * Returns the update release version of the running JDK if it's
+     * a RE build. It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jdkUpdateVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_update_version;
+    }
+
+    public static synchronized String jdkSpecialVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        if (jdk_special_version == null) {
+            jdk_special_version = getJdkSpecialVersion();
+        }
+        return jdk_special_version;
+    }
+    public static native String getJdkSpecialVersion();
+
+    /**
+     * Returns the build number of the running JDK if it's a RE build
+     * It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jdkBuildNumber() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_build_number;
+    }
+
+    // true if JVM exports the version info including the capabilities
+    private static boolean jvmVersionInfoAvailable;
+    private static synchronized void initVersions() {
+        if (versionsInitialized) {
+            return;
+        }
+        jvmVersionInfoAvailable = getJvmVersionInfo();
+        if (!jvmVersionInfoAvailable) {
+            // parse java.vm.version for older JVM before the
+            // new JVM_GetVersionInfo is added.
+            // valid format of the version string is:
+            // n.n.n[_uu[c]][-<identifer>]-bxx
+            CharSequence cs = System.getProperty("java.vm.version");
+            if (cs.length() >= 5 &&
+                Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
+                Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
+                Character.isDigit(cs.charAt(4))) {
+                jvm_major_version = Character.digit(cs.charAt(0), 10);
+                jvm_minor_version = Character.digit(cs.charAt(2), 10);
+                jvm_micro_version = Character.digit(cs.charAt(4), 10);
+                cs = cs.subSequence(5, cs.length());
+                if (cs.charAt(0) == '_' && cs.length() >= 3 &&
+                    Character.isDigit(cs.charAt(1)) &&
+                    Character.isDigit(cs.charAt(2))) {
+                    int nextChar = 3;
+                    try {
+                        String uu = cs.subSequence(1, 3).toString();
+                        jvm_update_version = Integer.valueOf(uu).intValue();
+                        if (cs.length() >= 4) {
+                            char c = cs.charAt(3);
+                            if (c >= 'a' && c <= 'z') {
+                                jvm_special_version = Character.toString(c);
+                                nextChar++;
+                            }
+                        }
+                    } catch (NumberFormatException e) {
+                        // not conforming to the naming convention
+                        return;
+                    }
+                    cs = cs.subSequence(nextChar, cs.length());
+                }
+                if (cs.charAt(0) == '-') {
+                    // skip the first character
+                    // valid format: <identifier>-bxx or bxx
+                    // non-product VM will have -debug|-release appended
+                    cs = cs.subSequence(1, cs.length());
+                    String[] res = cs.toString().split("-");
+                    for (String s : res) {
+                        if (s.charAt(0) == 'b' && s.length() == 3 &&
+                            Character.isDigit(s.charAt(1)) &&
+                            Character.isDigit(s.charAt(2))) {
+                            jvm_build_number =
+                                Integer.valueOf(s.substring(1, 3)).intValue();
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        getJdkVersionInfo();
+        versionsInitialized = true;
+    }
+
+    // Gets the JVM version info if available and sets the jvm_*_version fields
+    // and its capabilities.
+    //
+    // Return false if not available which implies an old VM (Tiger or before).
+    private static native boolean getJvmVersionInfo();
+    private static native void getJdkVersionInfo();
+
+}
+
+// Help Emacs a little because this file doesn't end in .java.
+//
+// Local Variables: ***
+// mode: java ***
+// End: ***
--- a/jdk/src/share/classes/sun/tools/jconsole/Version-template.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2004-2006 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 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.
- */
-
-package sun.tools.jconsole;
-
-import java.io.PrintStream;
-
-public class Version {
-    private static final String jconsole_version =
-        "@@jconsole_version@@";
-
-    public static void print(PrintStream ps) {
-        printFullVersion(ps);
-
-        ps.println(Resources.getText("Name and Build",
-                                     System.getProperty("java.runtime.name"),
-                                     System.getProperty("java.runtime.version")));
-
-        ps.println(Resources.getText("Name Build and Mode",
-                                     System.getProperty("java.vm.name"),
-                                     System.getProperty("java.vm.version"),
-                                     System.getProperty("java.vm.info")));
-
-    }
-
-    public static void printFullVersion(PrintStream ps) {
-        ps.println(Resources.getText("JConsole version", jconsole_version));
-    }
-
-    static String getVersion() {
-        return jconsole_version;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/tools/jconsole/Version.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004-2006 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+
+package sun.tools.jconsole;
+
+import java.io.PrintStream;
+
+public class Version {
+    private static final String jconsole_version =
+        "@@jconsole_version@@";
+
+    public static void print(PrintStream ps) {
+        printFullVersion(ps);
+
+        ps.println(Resources.getText("Name and Build",
+                                     System.getProperty("java.runtime.name"),
+                                     System.getProperty("java.runtime.version")));
+
+        ps.println(Resources.getText("Name Build and Mode",
+                                     System.getProperty("java.vm.name"),
+                                     System.getProperty("java.vm.version"),
+                                     System.getProperty("java.vm.info")));
+
+    }
+
+    public static void printFullVersion(PrintStream ps) {
+        ps.println(Resources.getText("JConsole version", jconsole_version));
+    }
+
+    static String getVersion() {
+        return jconsole_version;
+    }
+}
--- a/jdk/src/share/native/com/sun/media/sound/SoundDefs.h	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/src/share/native/com/sun/media/sound/SoundDefs.h	Wed Jul 05 17:02:54 2017 +0200
@@ -38,6 +38,7 @@
 #define X_SPARCV9       3
 #define X_IA64          4
 #define X_AMD64         5
+#define X_ZERO          6
 
 // **********************************
 // Make sure you set X_PLATFORM and X_ARCH defines correctly.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/bin/ergo_zero.c	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1998-2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 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.
+ */
+#include "ergo.h"
+
+
+/* Methods for solaris-sparc and linux-sparc: these are easy. */
+
+/* Ask the OS how many processors there are. */
+static unsigned long
+physical_processors(void) {
+  const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+
+  JLI_TraceLauncher("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+  return sys_processors;
+}
+
+/* The sparc version of the "server-class" predicate. */
+jboolean
+ServerClassMachineImpl(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= server_memory) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  JLI_TraceLauncher("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/bin/zero/jvm.cfg	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,39 @@
+# Copyright 2003 Sun Microsystems, Inc.  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.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 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.
+#
+# 
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
+-hotspot ERROR
+-classic WARN
+-native ERROR
+-green ERROR
--- a/jdk/test/java/nio/Buffer/Basic-X.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,869 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  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.
- */
-
-/* Type-specific source code for unit test
- *
- * Regenerate the BasicX classes via genBasic.sh whenever this file changes.
- * We check in the generated source files so that the test tree can be used
- * independently of the rest of the source tree.
- */
-
-#warn This file is preprocessed before being compiled
-
-import java.nio.*;
-import java.lang.reflect.Method;
-
-
-public class Basic$Type$
-    extends Basic
-{
-
-    private static void relGet($Type$Buffer b) {
-        int n = b.capacity();
-        $type$ v;
-        for (int i = 0; i < n; i++)
-            ck(b, (long)b.get(), (long)(($type$)ic(i)));
-        b.rewind();
-    }
-
-    private static void relGet($Type$Buffer b, int start) {
-        int n = b.remaining();
-        $type$ v;
-        for (int i = start; i < n; i++)
-            ck(b, (long)b.get(), (long)(($type$)ic(i)));
-        b.rewind();
-    }
-
-    private static void absGet($Type$Buffer b) {
-        int n = b.capacity();
-        $type$ v;
-        for (int i = 0; i < n; i++)
-            ck(b, (long)b.get(), (long)(($type$)ic(i)));
-        b.rewind();
-    }
-
-    private static void bulkGet($Type$Buffer b) {
-        int n = b.capacity();
-        $type$[] a = new $type$[n + 7];
-        b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
-            ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
-    }
-
-    private static void relPut($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        for (int i = 0; i < n; i++)
-            b.put(($type$)ic(i));
-        b.flip();
-    }
-
-    private static void absPut($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        for (int i = 0; i < n; i++)
-            b.put(i, ($type$)ic(i));
-        b.limit(n);
-        b.position(0);
-    }
-
-    private static void bulkPutArray($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        $type$[] a = new $type$[n + 7];
-        for (int i = 0; i < n; i++)
-            a[i + 7] = ($type$)ic(i);
-        b.put(a, 7, n);
-        b.flip();
-    }
-
-    private static void bulkPutBuffer($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        $Type$Buffer c = $Type$Buffer.allocate(n + 7);
-        c.position(7);
-        for (int i = 0; i < n; i++)
-            c.put(($type$)ic(i));
-        c.flip();
-        c.position(7);
-        b.put(c);
-        b.flip();
-    }
-
-    //6231529
-    private static void callReset($Type$Buffer b) {
-        b.position(0);
-        b.mark();
-
-        b.duplicate().reset();
-        b.asReadOnlyBuffer().reset();
-    }
-
-#if[byte]
-#else[byte]
-    // 6221101-6234263
-
-    private static void putBuffer() {
-        final int cap = 10;
-
-        $Type$Buffer direct1 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        $Type$Buffer nondirect1 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        direct1.put(nondirect1);
-
-        $Type$Buffer direct2 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        $Type$Buffer nondirect2 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        nondirect2.put(direct2);
-
-        $Type$Buffer direct3 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        $Type$Buffer direct4 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        direct3.put(direct4);
-
-        $Type$Buffer nondirect3 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        $Type$Buffer nondirect4 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        nondirect3.put(nondirect4);
-    }
-#end[byte]
-
-#if[char]
-
-    private static void bulkPutString($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        StringBuffer sb = new StringBuffer(n + 7);
-        sb.append("1234567");
-        for (int i = 0; i < n; i++)
-            sb.append((char)ic(i));
-        b.put(sb.toString(), 7, 7 + n);
-        b.flip();
-    }
-
-#end[char]
-
-    private static void checkSlice($Type$Buffer b, $Type$Buffer slice) {
-        ck(slice, 0, slice.position());
-        ck(slice, b.remaining(), slice.limit());
-        ck(slice, b.remaining(), slice.capacity());
-        if (b.isDirect() != slice.isDirect())
-            fail("Lost direction", slice);
-        if (b.isReadOnly() != slice.isReadOnly())
-            fail("Lost read-only", slice);
-    }
-
-#if[byte]
-
-    private static void checkBytes(ByteBuffer b, byte[] bs) {
-        int n = bs.length;
-        int p = b.position();
-        byte v;
-        if (b.order() == ByteOrder.BIG_ENDIAN) {
-            for (int i = 0; i < n; i++)
-                ck(b, b.get(), bs[i]);
-        } else {
-            for (int i = n - 1; i >= 0; i--)
-                ck(b, b.get(), bs[i]);
-        }
-        b.position(p);
-    }
-
-    private static void compact(Buffer b) {
-        try {
-            Class<?> cl = b.getClass();
-            Method m = cl.getDeclaredMethod("compact");
-            m.setAccessible(true);
-            m.invoke(b);
-        } catch (Exception e) {
-            fail(e.getMessage(), b);
-        }
-    }
-
-    private static void checkInvalidMarkException(final Buffer b) {
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-            public void run() {
-                b.mark();
-                compact(b);
-                b.reset();
-            }});
-    }
-
-    private static void testViews(int level, ByteBuffer b, boolean direct) {
-
-        ShortBuffer sb = b.asShortBuffer();
-        BasicShort.test(level, sb, direct);
-        checkBytes(b, new byte[] { 0, (byte)ic(0) });
-        checkInvalidMarkException(sb);
-
-        CharBuffer cb = b.asCharBuffer();
-        BasicChar.test(level, cb, direct);
-        checkBytes(b, new byte[] { 0, (byte)ic(0) });
-        checkInvalidMarkException(cb);
-
-        IntBuffer ib = b.asIntBuffer();
-        BasicInt.test(level, ib, direct);
-        checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
-        checkInvalidMarkException(ib);
-
-        LongBuffer lb = b.asLongBuffer();
-        BasicLong.test(level, lb, direct);
-        checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
-        checkInvalidMarkException(lb);
-
-        FloatBuffer fb = b.asFloatBuffer();
-        BasicFloat.test(level, fb, direct);
-        checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
-        checkInvalidMarkException(fb);
-
-        DoubleBuffer db = b.asDoubleBuffer();
-        BasicDouble.test(level, db, direct);
-        checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
-        checkInvalidMarkException(db);
-    }
-
-    private static void testHet(int level, ByteBuffer b) {
-
-        int p = b.position();
-        b.limit(b.capacity());
-        show(level, b);
-        out.print("    put:");
-
-        b.putChar((char)1);
-        b.putChar((char)Character.MAX_VALUE);
-        out.print(" char");
-
-        b.putShort((short)1);
-        b.putShort((short)Short.MAX_VALUE);
-        out.print(" short");
-
-        b.putInt(1);
-        b.putInt(Integer.MAX_VALUE);
-        out.print(" int");
-
-        b.putLong((long)1);
-        b.putLong((long)Long.MAX_VALUE);
-        out.print(" long");
-
-        b.putFloat((float)1);
-        b.putFloat((float)Float.MIN_VALUE);
-        b.putFloat((float)Float.MAX_VALUE);
-        out.print(" float");
-
-        b.putDouble((double)1);
-        b.putDouble((double)Double.MIN_VALUE);
-        b.putDouble((double)Double.MAX_VALUE);
-        out.print(" double");
-
-        out.println();
-        b.limit(b.position());
-        b.position(p);
-        show(level, b);
-        out.print("    get:");
-
-        ck(b, b.getChar(), 1);
-        ck(b, b.getChar(), Character.MAX_VALUE);
-        out.print(" char");
-
-        ck(b, b.getShort(), 1);
-        ck(b, b.getShort(), Short.MAX_VALUE);
-        out.print(" short");
-
-        ck(b, b.getInt(), 1);
-        ck(b, b.getInt(), Integer.MAX_VALUE);
-        out.print(" int");
-
-        ck(b, b.getLong(), 1);
-        ck(b, b.getLong(), Long.MAX_VALUE);
-        out.print(" long");
-
-        ck(b, (long)b.getFloat(), 1);
-        ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE);
-        ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE);
-        out.print(" float");
-
-        ck(b, (long)b.getDouble(), 1);
-        ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE);
-        ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE);
-        out.print(" double");
-
-        out.println();
-
-    }
-
-#end[byte]
-
-    private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
-        boolean caught = false;
-        try {
-            thunk.run();
-        } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass())) {
-                caught = true;
-            } else {
-                fail(x.getMessage() + " not expected");
-            }
-        }
-        if (!caught)
-            fail(ex.getName() + " not thrown", b);
-    }
-
-    private static void tryCatch($type$ [] t, Class ex, Runnable thunk) {
-        tryCatch($Type$Buffer.wrap(t), ex, thunk);
-    }
-
-    public static void test(int level, final $Type$Buffer b, boolean direct) {
-
-        show(level, b);
-
-        if (direct != b.isDirect())
-            fail("Wrong direction", b);
-
-        // Gets and puts
-
-        relPut(b);
-        relGet(b);
-        absGet(b);
-        bulkGet(b);
-
-        absPut(b);
-        relGet(b);
-        absGet(b);
-        bulkGet(b);
-
-        bulkPutArray(b);
-        relGet(b);
-
-        bulkPutBuffer(b);
-        relGet(b);
-
-#if[char]
-
-        bulkPutString(b);
-        relGet(b);
-        b.position(1);
-        b.limit(7);
-        ck(b, b.toString().equals("bcdefg"));
-
-        // CharSequence ops
-
-        b.position(2);
-        ck(b, b.charAt(1), 'd');
-        CharBuffer c = b.subSequence(1, 4);
-        ck(c, c.capacity(), b.capacity());
-        ck(c, c.position(), b.position()+1);
-        ck(c, c.limit(), b.position()+4);
-        ck(c, b.subSequence(1, 4).toString().equals("def"));
-
-        // 4938424
-        b.position(4);
-        ck(b, b.charAt(1), 'f');
-        ck(b, b.subSequence(1, 3).toString().equals("fg"));
-
-#end[char]
-
-        // Compact
-
-        relPut(b);
-        b.position(13);
-        b.compact();
-        b.flip();
-        relGet(b, 13);
-
-        // Exceptions
-
-        relPut(b);
-        b.limit(b.capacity() / 2);
-        b.position(b.limit());
-
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put(($type$)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), ($type$)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
-
-        // Values
-
-        b.clear();
-        b.put(($type$)0);
-        b.put(($type$)-1);
-        b.put(($type$)1);
-        b.put($Fulltype$.MAX_VALUE);
-        b.put($Fulltype$.MIN_VALUE);
-#if[float]
-        b.put(-Float.MAX_VALUE);
-        b.put(-Float.MIN_VALUE);
-        b.put(Float.NEGATIVE_INFINITY);
-        b.put(Float.POSITIVE_INFINITY);
-        b.put(Float.NaN);
-        b.put(0.91697687f);             // Changes value if incorrectly swapped
-#end[float]
-#if[double]
-        b.put(-Double.MAX_VALUE);
-        b.put(-Double.MIN_VALUE);
-        b.put(Double.NEGATIVE_INFINITY);
-        b.put(Double.POSITIVE_INFINITY);
-        b.put(Double.NaN);
-        b.put(0.5121609353879392);      // Changes value if incorrectly swapped
-#end[double]
-
-        $type$ v;
-        b.flip();
-        ck(b, b.get(), 0);
-        ck(b, b.get(), ($type$)-1);
-        ck(b, b.get(), 1);
-        ck(b, b.get(), $Fulltype$.MAX_VALUE);
-        ck(b, b.get(), $Fulltype$.MIN_VALUE);
-
-#if[float]
-        ck(b, b.get(), -Float.MAX_VALUE);
-        ck(b, b.get(), -Float.MIN_VALUE);
-        ck(b, b.get(), Float.NEGATIVE_INFINITY);
-        ck(b, b.get(), Float.POSITIVE_INFINITY);
-        if (Float.floatToRawIntBits(v = b.get()) != Float.floatToRawIntBits(Float.NaN))
-            fail(b, (long)Float.NaN, (long)v);
-        ck(b, b.get(), 0.91697687f);
-#end[float]
-#if[double]
-        ck(b, b.get(), -Double.MAX_VALUE);
-        ck(b, b.get(), -Double.MIN_VALUE);
-        ck(b, b.get(), Double.NEGATIVE_INFINITY);
-        ck(b, b.get(), Double.POSITIVE_INFINITY);
-        if (Double.doubleToRawLongBits(v = b.get())
-            != Double.doubleToRawLongBits(Double.NaN))
-            fail(b, (long)Double.NaN, (long)v);
-        ck(b, b.get(), 0.5121609353879392);
-#end[double]
-
-
-        // Comparison
-        b.rewind();
-        $Type$Buffer b2 = $Type$Buffer.allocate(b.capacity());
-        b2.put(b);
-        b2.flip();
-        b.position(2);
-        b2.position(2);
-        if (!b.equals(b2)) {
-            for (int i = 2; i < b.limit(); i++) {
-                $type$ x = b.get(i);
-                $type$ y = b2.get(i);
-                if (x != y
-#if[double]
-                    || Double.compare(x, y) != 0
-#end[double]
-#if[float]
-                    || Float.compare(x, y) != 0
-#end[float]
-                    )
-                    out.println("[" + i + "] " + x + " != " + y);
-            }
-            fail("Identical buffers not equal", b, b2);
-        }
-        if (b.compareTo(b2) != 0)
-            fail("Comparison to identical buffer != 0", b, b2);
-
-        b.limit(b.limit() + 1);
-        b.position(b.limit() - 1);
-        b.put(($type$)99);
-        b.rewind();
-        b2.rewind();
-        if (b.equals(b2))
-            fail("Non-identical buffers equal", b, b2);
-        if (b.compareTo(b2) <= 0)
-            fail("Comparison to shorter buffer <= 0", b, b2);
-        b.limit(b.limit() - 1);
-
-        b.put(2, ($type$)42);
-        if (b.equals(b2))
-            fail("Non-identical buffers equal", b, b2);
-        if (b.compareTo(b2) <= 0)
-            fail("Comparison to lesser buffer <= 0", b, b2);
-
-        // Sub, dup
-
-        relPut(b);
-        relGet(b.duplicate());
-        b.position(13);
-        relGet(b.duplicate(), 13);
-        relGet(b.duplicate().slice(), 13);
-        relGet(b.slice(), 13);
-        relGet(b.slice().duplicate(), 13);
-
-        // Slice
-
-        b.position(5);
-        $Type$Buffer sb = b.slice();
-        checkSlice(b, sb);
-        b.position(0);
-        $Type$Buffer sb2 = sb.slice();
-        checkSlice(sb, sb2);
-
-        if (!sb.equals(sb2))
-            fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
-            fail("Array offsets do not match: "
-                 + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
-
-#if[byte]
-
-        // Views
-
-        b.clear();
-        b.order(ByteOrder.BIG_ENDIAN);
-        testViews(level + 1, b, direct);
-
-        for (int i = 1; i <= 9; i++) {
-            b.position(i);
-            show(level + 1, b);
-            testViews(level + 2, b, direct);
-        }
-
-        b.position(0);
-        b.order(ByteOrder.LITTLE_ENDIAN);
-        testViews(level + 1, b, direct);
-
-        // Heterogeneous accessors
-
-        b.order(ByteOrder.BIG_ENDIAN);
-        for (int i = 0; i <= 9; i++) {
-            b.position(i);
-            testHet(level + 1, b);
-        }
-        b.order(ByteOrder.LITTLE_ENDIAN);
-        b.position(3);
-        testHet(level + 1, b);
-
-#end[byte]
-
-        // Read-only views
-
-        b.rewind();
-        final $Type$Buffer rb = b.asReadOnlyBuffer();
-        if (!b.equals(rb))
-            fail("Buffer not equal to read-only view", b, rb);
-        show(level + 1, rb);
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-#if[byte]
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar((char)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar(0, (char)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort((short)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort(0, (short)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(0, 1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong((long)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong(0, (long)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat((float)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat(0, (float)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble((double)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble(0, (double)1);
-                }});
-
-#end[byte]
-
-        if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
-        }
-
-        // Bulk puts from read-only buffers
-
-        b.clear();
-        rb.rewind();
-        b.put(rb);
-
-#if[byte]
-        // For byte buffers, test both the direct and non-direct cases
-        $Type$Buffer ob
-            = (b.isDirect()
-               ? $Type$Buffer.allocate(rb.capacity())
-               : $Type$Buffer.allocateDirect(rb.capacity()));
-        rb.rewind();
-        ob.put(rb);
-#end[byte]
-
-        relPut(b);                       // Required by testViews
-
-    }
-
-#if[char]
-
-    private static void testStr() {
-        final String s = "abcdefghijklm";
-        int start = 3;
-        int end = 9;
-        final CharBuffer b = CharBuffer.wrap(s, start, end);
-        show(0, b);
-        ck(b, b.toString().equals(s.substring(start, end)));
-        ck(b, b.toString().equals("defghi"));
-        ck(b, b.isReadOnly());
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    b.put('x');
-                }});
-        ck(b, start, b.position());
-        ck(b, end, b.limit());
-        ck(b, s.length(), b.capacity());
-        b.position(6);
-        ck(b, b.subSequence(0,3).toString().equals("ghi"));
-
-        // The index, relative to the position, must be non-negative and
-        // smaller than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(-1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(b.remaining());
-                }});
-
-        // The index must be non-negative and less than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        // The start must be non-negative and no larger than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(-1, b.remaining());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(b.remaining() + 1, b.remaining());
-                }});
-
-        // The end must be no smaller than start and no larger than
-        // remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(2, 1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(0, b.remaining() + 1);
-                }});
-
-        // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, -1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, s.length() + 1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, 1, 0);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, 0, s.length() + 1);
-                }});
-    }
-
-#end[char]
-
-    public static void test(final $type$ [] ba) {
-        int offset = 47;
-        int length = 900;
-        final $Type$Buffer b = $Type$Buffer.wrap(ba, offset, length);
-        show(0, b);
-        ck(b, b.capacity(), ba.length);
-        ck(b, b.position(), offset);
-        ck(b, b.limit(), offset + length);
-
-        // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, 0, ba.length + 1);
-                }});
-
-        // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(($type$ []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(($type$ []) null);
-                }});
-    }
-
-    private static void testAllocate() {
-        // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.allocate(-1);
-                }});
-#if[byte]
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.allocateDirect(-1);
-                }});
-#end[byte]
-    }
-
-    public static void test() {
-        testAllocate();
-        test(0, $Type$Buffer.allocate(7 * 1024), false);
-        test(0, $Type$Buffer.wrap(new $type$[7 * 1024], 0, 7 * 1024), false);
-        test(new $type$[1024]);
-#if[byte]
-        $Type$Buffer b = $Type$Buffer.allocateDirect(7 * 1024);
-        for (b.position(0); b.position() < b.limit(); )
-            ck(b, b.get(), 0);
-        test(0, b, true);
-#end[byte]
-#if[char]
-        testStr();
-#end[char]
-
-        callReset($Type$Buffer.allocate(10));
-
-#if[byte]
-#else[byte]
-        putBuffer();
-#end[byte]
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/Buffer/Basic-X.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,869 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  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.
+ */
+
+/* Type-specific source code for unit test
+ *
+ * Regenerate the BasicX classes via genBasic.sh whenever this file changes.
+ * We check in the generated source files so that the test tree can be used
+ * independently of the rest of the source tree.
+ */
+
+#warn This file is preprocessed before being compiled
+
+import java.nio.*;
+import java.lang.reflect.Method;
+
+
+public class Basic$Type$
+    extends Basic
+{
+
+    private static void relGet($Type$Buffer b) {
+        int n = b.capacity();
+        $type$ v;
+        for (int i = 0; i < n; i++)
+            ck(b, (long)b.get(), (long)(($type$)ic(i)));
+        b.rewind();
+    }
+
+    private static void relGet($Type$Buffer b, int start) {
+        int n = b.remaining();
+        $type$ v;
+        for (int i = start; i < n; i++)
+            ck(b, (long)b.get(), (long)(($type$)ic(i)));
+        b.rewind();
+    }
+
+    private static void absGet($Type$Buffer b) {
+        int n = b.capacity();
+        $type$ v;
+        for (int i = 0; i < n; i++)
+            ck(b, (long)b.get(), (long)(($type$)ic(i)));
+        b.rewind();
+    }
+
+    private static void bulkGet($Type$Buffer b) {
+        int n = b.capacity();
+        $type$[] a = new $type$[n + 7];
+        b.get(a, 7, n);
+        for (int i = 0; i < n; i++)
+            ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
+    }
+
+    private static void relPut($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        for (int i = 0; i < n; i++)
+            b.put(($type$)ic(i));
+        b.flip();
+    }
+
+    private static void absPut($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        for (int i = 0; i < n; i++)
+            b.put(i, ($type$)ic(i));
+        b.limit(n);
+        b.position(0);
+    }
+
+    private static void bulkPutArray($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        $type$[] a = new $type$[n + 7];
+        for (int i = 0; i < n; i++)
+            a[i + 7] = ($type$)ic(i);
+        b.put(a, 7, n);
+        b.flip();
+    }
+
+    private static void bulkPutBuffer($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        $Type$Buffer c = $Type$Buffer.allocate(n + 7);
+        c.position(7);
+        for (int i = 0; i < n; i++)
+            c.put(($type$)ic(i));
+        c.flip();
+        c.position(7);
+        b.put(c);
+        b.flip();
+    }
+
+    //6231529
+    private static void callReset($Type$Buffer b) {
+        b.position(0);
+        b.mark();
+
+        b.duplicate().reset();
+        b.asReadOnlyBuffer().reset();
+    }
+
+#if[byte]
+#else[byte]
+    // 6221101-6234263
+
+    private static void putBuffer() {
+        final int cap = 10;
+
+        $Type$Buffer direct1 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        $Type$Buffer nondirect1 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        direct1.put(nondirect1);
+
+        $Type$Buffer direct2 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        $Type$Buffer nondirect2 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        nondirect2.put(direct2);
+
+        $Type$Buffer direct3 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        $Type$Buffer direct4 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        direct3.put(direct4);
+
+        $Type$Buffer nondirect3 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        $Type$Buffer nondirect4 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        nondirect3.put(nondirect4);
+    }
+#end[byte]
+
+#if[char]
+
+    private static void bulkPutString($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        StringBuffer sb = new StringBuffer(n + 7);
+        sb.append("1234567");
+        for (int i = 0; i < n; i++)
+            sb.append((char)ic(i));
+        b.put(sb.toString(), 7, 7 + n);
+        b.flip();
+    }
+
+#end[char]
+
+    private static void checkSlice($Type$Buffer b, $Type$Buffer slice) {
+        ck(slice, 0, slice.position());
+        ck(slice, b.remaining(), slice.limit());
+        ck(slice, b.remaining(), slice.capacity());
+        if (b.isDirect() != slice.isDirect())
+            fail("Lost direction", slice);
+        if (b.isReadOnly() != slice.isReadOnly())
+            fail("Lost read-only", slice);
+    }
+
+#if[byte]
+
+    private static void checkBytes(ByteBuffer b, byte[] bs) {
+        int n = bs.length;
+        int p = b.position();
+        byte v;
+        if (b.order() == ByteOrder.BIG_ENDIAN) {
+            for (int i = 0; i < n; i++)
+                ck(b, b.get(), bs[i]);
+        } else {
+            for (int i = n - 1; i >= 0; i--)
+                ck(b, b.get(), bs[i]);
+        }
+        b.position(p);
+    }
+
+    private static void compact(Buffer b) {
+        try {
+            Class<?> cl = b.getClass();
+            Method m = cl.getDeclaredMethod("compact");
+            m.setAccessible(true);
+            m.invoke(b);
+        } catch (Exception e) {
+            fail(e.getMessage(), b);
+        }
+    }
+
+    private static void checkInvalidMarkException(final Buffer b) {
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+            public void run() {
+                b.mark();
+                compact(b);
+                b.reset();
+            }});
+    }
+
+    private static void testViews(int level, ByteBuffer b, boolean direct) {
+
+        ShortBuffer sb = b.asShortBuffer();
+        BasicShort.test(level, sb, direct);
+        checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(sb);
+
+        CharBuffer cb = b.asCharBuffer();
+        BasicChar.test(level, cb, direct);
+        checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(cb);
+
+        IntBuffer ib = b.asIntBuffer();
+        BasicInt.test(level, ib, direct);
+        checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(ib);
+
+        LongBuffer lb = b.asLongBuffer();
+        BasicLong.test(level, lb, direct);
+        checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(lb);
+
+        FloatBuffer fb = b.asFloatBuffer();
+        BasicFloat.test(level, fb, direct);
+        checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
+        checkInvalidMarkException(fb);
+
+        DoubleBuffer db = b.asDoubleBuffer();
+        BasicDouble.test(level, db, direct);
+        checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
+        checkInvalidMarkException(db);
+    }
+
+    private static void testHet(int level, ByteBuffer b) {
+
+        int p = b.position();
+        b.limit(b.capacity());
+        show(level, b);
+        out.print("    put:");
+
+        b.putChar((char)1);
+        b.putChar((char)Character.MAX_VALUE);
+        out.print(" char");
+
+        b.putShort((short)1);
+        b.putShort((short)Short.MAX_VALUE);
+        out.print(" short");
+
+        b.putInt(1);
+        b.putInt(Integer.MAX_VALUE);
+        out.print(" int");
+
+        b.putLong((long)1);
+        b.putLong((long)Long.MAX_VALUE);
+        out.print(" long");
+
+        b.putFloat((float)1);
+        b.putFloat((float)Float.MIN_VALUE);
+        b.putFloat((float)Float.MAX_VALUE);
+        out.print(" float");
+
+        b.putDouble((double)1);
+        b.putDouble((double)Double.MIN_VALUE);
+        b.putDouble((double)Double.MAX_VALUE);
+        out.print(" double");
+
+        out.println();
+        b.limit(b.position());
+        b.position(p);
+        show(level, b);
+        out.print("    get:");
+
+        ck(b, b.getChar(), 1);
+        ck(b, b.getChar(), Character.MAX_VALUE);
+        out.print(" char");
+
+        ck(b, b.getShort(), 1);
+        ck(b, b.getShort(), Short.MAX_VALUE);
+        out.print(" short");
+
+        ck(b, b.getInt(), 1);
+        ck(b, b.getInt(), Integer.MAX_VALUE);
+        out.print(" int");
+
+        ck(b, b.getLong(), 1);
+        ck(b, b.getLong(), Long.MAX_VALUE);
+        out.print(" long");
+
+        ck(b, (long)b.getFloat(), 1);
+        ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE);
+        ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE);
+        out.print(" float");
+
+        ck(b, (long)b.getDouble(), 1);
+        ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE);
+        ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE);
+        out.print(" double");
+
+        out.println();
+
+    }
+
+#end[byte]
+
+    private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
+        boolean caught = false;
+        try {
+            thunk.run();
+        } catch (Throwable x) {
+            if (ex.isAssignableFrom(x.getClass())) {
+                caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
+        }
+        if (!caught)
+            fail(ex.getName() + " not thrown", b);
+    }
+
+    private static void tryCatch($type$ [] t, Class ex, Runnable thunk) {
+        tryCatch($Type$Buffer.wrap(t), ex, thunk);
+    }
+
+    public static void test(int level, final $Type$Buffer b, boolean direct) {
+
+        show(level, b);
+
+        if (direct != b.isDirect())
+            fail("Wrong direction", b);
+
+        // Gets and puts
+
+        relPut(b);
+        relGet(b);
+        absGet(b);
+        bulkGet(b);
+
+        absPut(b);
+        relGet(b);
+        absGet(b);
+        bulkGet(b);
+
+        bulkPutArray(b);
+        relGet(b);
+
+        bulkPutBuffer(b);
+        relGet(b);
+
+#if[char]
+
+        bulkPutString(b);
+        relGet(b);
+        b.position(1);
+        b.limit(7);
+        ck(b, b.toString().equals("bcdefg"));
+
+        // CharSequence ops
+
+        b.position(2);
+        ck(b, b.charAt(1), 'd');
+        CharBuffer c = b.subSequence(1, 4);
+        ck(c, c.capacity(), b.capacity());
+        ck(c, c.position(), b.position()+1);
+        ck(c, c.limit(), b.position()+4);
+        ck(c, b.subSequence(1, 4).toString().equals("def"));
+
+        // 4938424
+        b.position(4);
+        ck(b, b.charAt(1), 'f');
+        ck(b, b.subSequence(1, 3).toString().equals("fg"));
+
+#end[char]
+
+        // Compact
+
+        relPut(b);
+        b.position(13);
+        b.compact();
+        b.flip();
+        relGet(b, 13);
+
+        // Exceptions
+
+        relPut(b);
+        b.limit(b.capacity() / 2);
+        b.position(b.limit());
+
+        tryCatch(b, BufferUnderflowException.class, new Runnable() {
+                public void run() {
+                    b.get();
+                }});
+
+        tryCatch(b, BufferOverflowException.class, new Runnable() {
+                public void run() {
+                    b.put(($type$)42);
+                }});
+
+        // The index must be non-negative and lesss than the buffer's limit.
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(b.limit());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(-1);
+                }});
+
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.put(b.limit(), ($type$)42);
+                }});
+
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
+        // Values
+
+        b.clear();
+        b.put(($type$)0);
+        b.put(($type$)-1);
+        b.put(($type$)1);
+        b.put($Fulltype$.MAX_VALUE);
+        b.put($Fulltype$.MIN_VALUE);
+#if[float]
+        b.put(-Float.MAX_VALUE);
+        b.put(-Float.MIN_VALUE);
+        b.put(Float.NEGATIVE_INFINITY);
+        b.put(Float.POSITIVE_INFINITY);
+        b.put(Float.NaN);
+        b.put(0.91697687f);             // Changes value if incorrectly swapped
+#end[float]
+#if[double]
+        b.put(-Double.MAX_VALUE);
+        b.put(-Double.MIN_VALUE);
+        b.put(Double.NEGATIVE_INFINITY);
+        b.put(Double.POSITIVE_INFINITY);
+        b.put(Double.NaN);
+        b.put(0.5121609353879392);      // Changes value if incorrectly swapped
+#end[double]
+
+        $type$ v;
+        b.flip();
+        ck(b, b.get(), 0);
+        ck(b, b.get(), ($type$)-1);
+        ck(b, b.get(), 1);
+        ck(b, b.get(), $Fulltype$.MAX_VALUE);
+        ck(b, b.get(), $Fulltype$.MIN_VALUE);
+
+#if[float]
+        ck(b, b.get(), -Float.MAX_VALUE);
+        ck(b, b.get(), -Float.MIN_VALUE);
+        ck(b, b.get(), Float.NEGATIVE_INFINITY);
+        ck(b, b.get(), Float.POSITIVE_INFINITY);
+        if (Float.floatToRawIntBits(v = b.get()) != Float.floatToRawIntBits(Float.NaN))
+            fail(b, (long)Float.NaN, (long)v);
+        ck(b, b.get(), 0.91697687f);
+#end[float]
+#if[double]
+        ck(b, b.get(), -Double.MAX_VALUE);
+        ck(b, b.get(), -Double.MIN_VALUE);
+        ck(b, b.get(), Double.NEGATIVE_INFINITY);
+        ck(b, b.get(), Double.POSITIVE_INFINITY);
+        if (Double.doubleToRawLongBits(v = b.get())
+            != Double.doubleToRawLongBits(Double.NaN))
+            fail(b, (long)Double.NaN, (long)v);
+        ck(b, b.get(), 0.5121609353879392);
+#end[double]
+
+
+        // Comparison
+        b.rewind();
+        $Type$Buffer b2 = $Type$Buffer.allocate(b.capacity());
+        b2.put(b);
+        b2.flip();
+        b.position(2);
+        b2.position(2);
+        if (!b.equals(b2)) {
+            for (int i = 2; i < b.limit(); i++) {
+                $type$ x = b.get(i);
+                $type$ y = b2.get(i);
+                if (x != y
+#if[double]
+                    || Double.compare(x, y) != 0
+#end[double]
+#if[float]
+                    || Float.compare(x, y) != 0
+#end[float]
+                    )
+                    out.println("[" + i + "] " + x + " != " + y);
+            }
+            fail("Identical buffers not equal", b, b2);
+        }
+        if (b.compareTo(b2) != 0)
+            fail("Comparison to identical buffer != 0", b, b2);
+
+        b.limit(b.limit() + 1);
+        b.position(b.limit() - 1);
+        b.put(($type$)99);
+        b.rewind();
+        b2.rewind();
+        if (b.equals(b2))
+            fail("Non-identical buffers equal", b, b2);
+        if (b.compareTo(b2) <= 0)
+            fail("Comparison to shorter buffer <= 0", b, b2);
+        b.limit(b.limit() - 1);
+
+        b.put(2, ($type$)42);
+        if (b.equals(b2))
+            fail("Non-identical buffers equal", b, b2);
+        if (b.compareTo(b2) <= 0)
+            fail("Comparison to lesser buffer <= 0", b, b2);
+
+        // Sub, dup
+
+        relPut(b);
+        relGet(b.duplicate());
+        b.position(13);
+        relGet(b.duplicate(), 13);
+        relGet(b.duplicate().slice(), 13);
+        relGet(b.slice(), 13);
+        relGet(b.slice().duplicate(), 13);
+
+        // Slice
+
+        b.position(5);
+        $Type$Buffer sb = b.slice();
+        checkSlice(b, sb);
+        b.position(0);
+        $Type$Buffer sb2 = sb.slice();
+        checkSlice(sb, sb2);
+
+        if (!sb.equals(sb2))
+            fail("Sliced slices do not match", sb, sb2);
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+            fail("Array offsets do not match: "
+                 + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+
+#if[byte]
+
+        // Views
+
+        b.clear();
+        b.order(ByteOrder.BIG_ENDIAN);
+        testViews(level + 1, b, direct);
+
+        for (int i = 1; i <= 9; i++) {
+            b.position(i);
+            show(level + 1, b);
+            testViews(level + 2, b, direct);
+        }
+
+        b.position(0);
+        b.order(ByteOrder.LITTLE_ENDIAN);
+        testViews(level + 1, b, direct);
+
+        // Heterogeneous accessors
+
+        b.order(ByteOrder.BIG_ENDIAN);
+        for (int i = 0; i <= 9; i++) {
+            b.position(i);
+            testHet(level + 1, b);
+        }
+        b.order(ByteOrder.LITTLE_ENDIAN);
+        b.position(3);
+        testHet(level + 1, b);
+
+#end[byte]
+
+        // Read-only views
+
+        b.rewind();
+        final $Type$Buffer rb = b.asReadOnlyBuffer();
+        if (!b.equals(rb))
+            fail("Buffer not equal to read-only view", b, rb);
+        show(level + 1, rb);
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    relPut(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    absPut(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    bulkPutArray(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    bulkPutBuffer(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.compact();
+                }});
+
+#if[byte]
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putChar((char)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putChar(0, (char)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putShort((short)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putShort(0, (short)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putInt(1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putInt(0, 1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putLong((long)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putLong(0, (long)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putFloat((float)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putFloat(0, (float)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putDouble((double)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putDouble(0, (double)1);
+                }});
+
+#end[byte]
+
+        if (rb.getClass().getName().startsWith("java.nio.Heap")) {
+
+            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                    public void run() {
+                        rb.array();
+                    }});
+
+            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                    public void run() {
+                        rb.arrayOffset();
+                    }});
+
+            if (rb.hasArray())
+                fail("Read-only heap buffer's backing array is accessible",
+                     rb);
+
+        }
+
+        // Bulk puts from read-only buffers
+
+        b.clear();
+        rb.rewind();
+        b.put(rb);
+
+#if[byte]
+        // For byte buffers, test both the direct and non-direct cases
+        $Type$Buffer ob
+            = (b.isDirect()
+               ? $Type$Buffer.allocate(rb.capacity())
+               : $Type$Buffer.allocateDirect(rb.capacity()));
+        rb.rewind();
+        ob.put(rb);
+#end[byte]
+
+        relPut(b);                       // Required by testViews
+
+    }
+
+#if[char]
+
+    private static void testStr() {
+        final String s = "abcdefghijklm";
+        int start = 3;
+        int end = 9;
+        final CharBuffer b = CharBuffer.wrap(s, start, end);
+        show(0, b);
+        ck(b, b.toString().equals(s.substring(start, end)));
+        ck(b, b.toString().equals("defghi"));
+        ck(b, b.isReadOnly());
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    b.put('x');
+                }});
+        ck(b, start, b.position());
+        ck(b, end, b.limit());
+        ck(b, s.length(), b.capacity());
+        b.position(6);
+        ck(b, b.subSequence(0,3).toString().equals("ghi"));
+
+        // The index, relative to the position, must be non-negative and
+        // smaller than remaining().
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.charAt(-1);
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.charAt(b.remaining());
+                }});
+
+        // The index must be non-negative and less than the buffer's limit.
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(b.limit());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(-1);
+                }});
+
+        // The start must be non-negative and no larger than remaining().
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(-1, b.remaining());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(b.remaining() + 1, b.remaining());
+                }});
+
+        // The end must be no smaller than start and no larger than
+        // remaining().
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(2, 1);
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(0, b.remaining() + 1);
+                }});
+
+        // The offset must be non-negative and no larger than <array.length>.
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, -1, s.length());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, s.length() + 1, s.length());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, 1, 0);
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, 0, s.length() + 1);
+                }});
+    }
+
+#end[char]
+
+    public static void test(final $type$ [] ba) {
+        int offset = 47;
+        int length = 900;
+        final $Type$Buffer b = $Type$Buffer.wrap(ba, offset, length);
+        show(0, b);
+        ck(b, b.capacity(), ba.length);
+        ck(b, b.position(), offset);
+        ck(b, b.limit(), offset + length);
+
+        // The offset must be non-negative and no larger than <array.length>.
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, -1, ba.length);
+                }});
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, ba.length + 1, ba.length);
+                }});
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, 0, -1);
+                }});
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, 0, ba.length + 1);
+                }});
+
+        // A NullPointerException will be thrown if the array is null.
+        tryCatch(ba, NullPointerException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(($type$ []) null, 0, 5);
+                }});
+        tryCatch(ba, NullPointerException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(($type$ []) null);
+                }});
+    }
+
+    private static void testAllocate() {
+        // An IllegalArgumentException will be thrown for negative capacities.
+        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.allocate(-1);
+                }});
+#if[byte]
+        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.allocateDirect(-1);
+                }});
+#end[byte]
+    }
+
+    public static void test() {
+        testAllocate();
+        test(0, $Type$Buffer.allocate(7 * 1024), false);
+        test(0, $Type$Buffer.wrap(new $type$[7 * 1024], 0, 7 * 1024), false);
+        test(new $type$[1024]);
+#if[byte]
+        $Type$Buffer b = $Type$Buffer.allocateDirect(7 * 1024);
+        for (b.position(0); b.position() < b.limit(); )
+            ck(b, b.get(), 0);
+        test(0, b, true);
+#end[byte]
+#if[char]
+        testStr();
+#end[char]
+
+        callReset($Type$Buffer.allocate(10));
+
+#if[byte]
+#else[byte]
+        putBuffer();
+#end[byte]
+    }
+
+}
--- a/jdk/test/java/nio/Buffer/CopyDirect-X-Memory.java	Fri Nov 06 17:26:01 2009 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright 2002-2007 Sun Microsystems, Inc.  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.
- */
-
-#warn This file is preprocessed before being compiled
-
-import java.nio.*;
-
-public class CopyDirect$Type$Memory
-    extends CopyDirectMemory
-{
-    private static void init($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        for (int i = 0; i < n; i++)
-            b.put(i, ($type$)ic(i));
-        b.limit(n);
-        b.position(0);
-    }
-
-    private static void init($type$ [] a) {
-        for (int i = 0; i < a.length; i++)
-            a[i] = ($type$)ic(i + 1);
-    }
-
-    public static void test() {
-#if[byte]
-        ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
-#else[byte]
-        ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
-        $Type$Buffer b = bb.as$Type$Buffer();
-#end[byte]
-        init(b);
-        $type$ [] a = new $type$[b.capacity()];
-        init(a);
-
-        // copyFrom$Type$Array (a -> b)
-        b.put(a);
-        for (int i = 0; i < a.length; i++)
-            ck(b, b.get(i), ($type$)ic(i + 1));
-
-        // copyTo$Type$Array (b -> a)
-        init(b);
-        init(a);
-        b.get(a);
-        for (int i = 0; i < a.length; i++)
-            if (a[i] != b.get(i))
-                fail("Copy failed at " + i + ": '"
-                     + a[i] + "' != '" + b.get(i) + "'");
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/Buffer/CopyDirect-X-Memory.java.template	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2007 Sun Microsystems, Inc.  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.
+ */
+
+#warn This file is preprocessed before being compiled
+
+import java.nio.*;
+
+public class CopyDirect$Type$Memory
+    extends CopyDirectMemory
+{
+    private static void init($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        for (int i = 0; i < n; i++)
+            b.put(i, ($type$)ic(i));
+        b.limit(n);
+        b.position(0);
+    }
+
+    private static void init($type$ [] a) {
+        for (int i = 0; i < a.length; i++)
+            a[i] = ($type$)ic(i + 1);
+    }
+
+    public static void test() {
+#if[byte]
+        ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
+#else[byte]
+        ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
+        $Type$Buffer b = bb.as$Type$Buffer();
+#end[byte]
+        init(b);
+        $type$ [] a = new $type$[b.capacity()];
+        init(a);
+
+        // copyFrom$Type$Array (a -> b)
+        b.put(a);
+        for (int i = 0; i < a.length; i++)
+            ck(b, b.get(i), ($type$)ic(i + 1));
+
+        // copyTo$Type$Array (b -> a)
+        init(b);
+        init(a);
+        b.get(a);
+        for (int i = 0; i < a.length; i++)
+            if (a[i] != b.get(i))
+                fail("Copy failed at " + i + ": '"
+                     + a[i] + "' != '" + b.get(i) + "'");
+    }
+}
--- a/jdk/test/java/nio/Buffer/genBasic.sh	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/nio/Buffer/genBasic.sh	Wed Jul 05 17:02:54 2017 +0200
@@ -26,7 +26,7 @@
 javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java
 
 gen() {
-    java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java >Basic$2.java
+    java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java.template >Basic$2.java
 }
 
 gen byte Byte Byte
--- a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh	Wed Jul 05 17:02:54 2017 +0200
@@ -26,7 +26,7 @@
 javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java
 
 gen() {
-    java  build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java >CopyDirect$2Memory.java
+    java  build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java.template >CopyDirect$2Memory.java
 }
 
 gen byte Byte Byte
--- a/jdk/test/java/util/Collection/BiggernYours.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/Collection/BiggernYours.java	Wed Jul 05 17:02:54 2017 +0200
@@ -178,10 +178,10 @@
             new ConcurrentLinkedQueue() {
                 public int size() {return randomize(super.size());}});
 
-//         testCollections(
-//             new LinkedTransferQueue(),
-//             new LinkedTransferQueue() {
-//                 public int size() {return randomize(super.size());}});
+        testCollections(
+            new LinkedTransferQueue(),
+            new LinkedTransferQueue() {
+                public int size() {return randomize(super.size());}});
 
         testCollections(
             new LinkedBlockingQueue(),
--- a/jdk/test/java/util/Collection/IteratorAtEnd.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/Collection/IteratorAtEnd.java	Wed Jul 05 17:02:54 2017 +0200
@@ -49,7 +49,7 @@
         testCollection(new LinkedBlockingQueue());
         testCollection(new ArrayBlockingQueue(100));
         testCollection(new ConcurrentLinkedQueue());
-//         testCollection(new LinkedTransferQueue());
+        testCollection(new LinkedTransferQueue());
 
         testMap(new HashMap());
         testMap(new Hashtable());
--- a/jdk/test/java/util/Collection/MOAT.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/Collection/MOAT.java	Wed Jul 05 17:02:54 2017 +0200
@@ -76,7 +76,7 @@
         testCollection(new LinkedBlockingQueue<Integer>(20));
         testCollection(new LinkedBlockingDeque<Integer>(20));
         testCollection(new ConcurrentLinkedQueue<Integer>());
-//         testCollection(new LinkedTransferQueue<Integer>());
+        testCollection(new LinkedTransferQueue<Integer>());
         testCollection(new ConcurrentSkipListSet<Integer>());
         testCollection(Arrays.asList(new Integer(42)));
         testCollection(Arrays.asList(1,2,3));
--- a/jdk/test/java/util/Collections/CheckedNull.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/Collections/CheckedNull.java	Wed Jul 05 17:02:54 2017 +0200
@@ -52,7 +52,7 @@
 
         testMap(Collections.checkedMap(
                     new HashMap<String, String>(),
-                    String.class, String.class));;
+                    String.class, String.class));
     }
 
     ClassCastException cce(F f) {
--- a/jdk/test/java/util/Collections/RacingCollections.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/Collections/RacingCollections.java	Wed Jul 05 17:02:54 2017 +0200
@@ -234,7 +234,7 @@
         List<Queue<Integer>> list =
             new ArrayList<Queue<Integer>>(newConcurrentDeques());
         list.add(new LinkedBlockingQueue<Integer>(10));
-//         list.add(new LinkedTransferQueue<Integer>());
+        list.add(new LinkedTransferQueue<Integer>());
         return list;
     }
 
--- a/jdk/test/java/util/PriorityQueue/RemoveContains.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/PriorityQueue/RemoveContains.java	Wed Jul 05 17:02:54 2017 +0200
@@ -69,7 +69,7 @@
         test(new ArrayBlockingQueue<String>(10));
         test(new LinkedBlockingQueue<String>(10));
         test(new LinkedBlockingDeque<String>(10));
-//         test(new LinkedTransferQueue<String>());
+        test(new LinkedTransferQueue<String>());
         test(new ArrayDeque<String>(10));
 
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -119,12 +119,36 @@
         }
     }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int pairs, int iters) throws Exception {
 
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LTQasSQ<Integer>(), pairs, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
         oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
 
         /* PriorityBlockingQueue is unbounded
--- a/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java	Wed Jul 05 17:02:54 2017 +0200
@@ -37,7 +37,7 @@
         testQueue(new LinkedBlockingDeque<Integer>());
         testQueue(new ArrayBlockingQueue<Integer>(10, true));
         testQueue(new ArrayBlockingQueue<Integer>(10, false));
-//         testQueue(new LinkedTransferQueue<Integer>());
+        testQueue(new LinkedTransferQueue<Integer>());
 
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
         if (failed > 0) throw new Exception("Some tests failed");
--- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -87,11 +87,35 @@
             throw new Error();
    }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int producers, int iters) throws Exception {
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), producers, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), producers, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), producers, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), producers, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), producers, iters);
+        oneRun(new LTQasSQ<Integer>(), producers, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), producers, iters);
 
         // Don't run PBQ since can legitimately run out of memory
         //        if (print)
--- a/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -63,12 +63,11 @@
         test(new LinkedBlockingDeque());
         test(new LinkedBlockingDeque(2000));
         test(new ArrayBlockingQueue(2000));
-//         test(new LinkedTransferQueue());
+        test(new LinkedTransferQueue());
     }
 
     Random getRandom() {
-        return new Random();
-        // return ThreadLocalRandom.current();
+        return ThreadLocalRandom.current();
     }
 
     void test(final BlockingQueue q) throws Throwable {
--- a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Wed Jul 05 17:02:54 2017 +0200
@@ -46,7 +46,7 @@
     public static void main(String[] args) throws InterruptedException {
         final BlockingQueue[] qs = {
             new LinkedBlockingQueue(10),
-//             new LinkedTransferQueue(),
+            new LinkedTransferQueue(),
             new ArrayBlockingQueue(10),
             new SynchronousQueue(),
             new SynchronousQueue(true),
--- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -87,11 +87,35 @@
             throw new Error();
    }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int pairs, int iters) throws Exception {
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LTQasSQ<Integer>(), pairs, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
         oneRun(new PriorityBlockingQueue<Integer>(), pairs, iters);
         oneRun(new SynchronousQueue<Integer>(), pairs, iters);
 
--- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -73,11 +73,35 @@
             throw new Error();
    }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int consumers, int iters) throws Exception {
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), consumers, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), consumers, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), consumers, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), consumers, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), consumers, iters);
+        oneRun(new LTQasSQ<Integer>(), consumers, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), consumers, iters);
         oneRun(new PriorityBlockingQueue<Integer>(), consumers, iters);
         oneRun(new SynchronousQueue<Integer>(), consumers, iters);
         if (print)
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -60,7 +60,7 @@
         //queues.add(new ArrayBlockingQueue<Integer>(count, true));
         queues.add(new LinkedBlockingQueue<Integer>());
         queues.add(new LinkedBlockingDeque<Integer>());
-//         queues.add(new LinkedTransferQueue<Integer>());
+        queues.add(new LinkedTransferQueue<Integer>());
 
         // Following additional implementations are available from:
         // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Wed Jul 05 17:02:54 2017 +0200
@@ -43,7 +43,7 @@
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
-// import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.LinkedTransferQueue;
 import java.util.concurrent.PriorityBlockingQueue;
 import java.util.LinkedList;
 import java.util.PriorityQueue;
@@ -70,7 +70,7 @@
         queues.add(new PriorityBlockingQueue<Boolean>());
         queues.add(new PriorityQueue<Boolean>());
         queues.add(new LinkedList<Boolean>());
-//         queues.add(new LinkedTransferQueue<Boolean>());
+        queues.add(new LinkedTransferQueue<Boolean>());
 
         // Following additional implementations are available from:
         // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Wed Jul 05 17:02:54 2017 +0200
@@ -49,7 +49,7 @@
         test(new LinkedBlockingDeque());
         test(new LinkedBlockingDeque(20));
         test(new ConcurrentLinkedQueue());
-//         test(new LinkedTransferQueue());
+        test(new LinkedTransferQueue());
         // Other concurrent queues (e.g. ArrayBlockingQueue) do not
         // currently have weakly consistent iterators.
         // test(new ArrayBlockingQueue(20));
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -56,12 +56,11 @@
         testQueue(new ArrayBlockingQueue(10));
         testQueue(new PriorityBlockingQueue(10));
         testQueue(new ConcurrentLinkedQueue());
-//         testQueue(new LinkedTransferQueue());
+        testQueue(new LinkedTransferQueue());
     }
 
     Random getRandom() {
-        return new Random();
-        // return ThreadLocalRandom.current();
+        return ThreadLocalRandom.current();
     }
 
     void testQueue(final Queue q) throws Throwable {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Wed Jul 05 17:02:54 2017 +0200
@@ -45,7 +45,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
-// import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.LinkedTransferQueue;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -67,7 +67,7 @@
         queues.add(new ArrayBlockingQueue<Boolean>(count, true));
         queues.add(new LinkedBlockingQueue<Boolean>());
         queues.add(new LinkedBlockingDeque<Boolean>());
-//         queues.add(new LinkedTransferQueue<Boolean>());
+        queues.add(new LinkedTransferQueue<Boolean>());
 
         // Following additional implementations are available from:
         // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/Phaser/Arrive.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6445158
+ * @summary tests for Phaser.arrive()
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Arrive {
+    void test(String[] args) throws Throwable {
+        final int n = ThreadLocalRandom.current().nextInt(1, 10);
+        final int nthreads = n*3/2;
+        final Phaser startingGate = new Phaser(nthreads);
+        final Phaser phaser = new Phaser(n);
+        final List<Thread> threads = new ArrayList<Thread>();
+        final AtomicInteger count0 = new AtomicInteger(0);
+        final AtomicInteger count1 = new AtomicInteger(0);
+        final Runnable task = new Runnable() { public void run() {
+            equal(startingGate.getPhase(), 0);
+            startingGate.arriveAndAwaitAdvance();
+            equal(startingGate.getPhase(), 1);
+            int phase = phaser.arrive();
+            if (phase == 0)
+                count0.getAndIncrement();
+            else if (phase == 1)
+                count1.getAndIncrement();
+            else
+                fail();
+        }};
+        for (int i = 0; i < nthreads; i++)
+            threads.add(new Thread(task));
+        for (Thread thread : threads)
+            thread.start();
+        for (Thread thread : threads)
+            thread.join();
+        equal(count0.get(), n);
+        equal(count1.get(), nthreads-n);
+        equal(phaser.getPhase(), 1);
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new Arrive().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/Phaser/Basic.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,407 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6445158
+ * @summary Basic tests for Phaser
+ * @author Chris Hegarty
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import static java.util.concurrent.TimeUnit.*;
+
+public class Basic {
+
+    private static void checkTerminated(final Phaser phaser) {
+        check(phaser.isTerminated());
+        int unarriverParties = phaser.getUnarrivedParties();
+        int registeredParties = phaser.getRegisteredParties();
+        equal(phaser.arrive(), -1);
+        equal(phaser.arriveAndDeregister(), -1);
+        equal(phaser.arriveAndAwaitAdvance(), -1);
+        equal(phaser.bulkRegister(10), -1);
+        equal(phaser.getPhase(), -1);
+        equal(phaser.register(), -1);
+        try {
+            equal(phaser.awaitAdvanceInterruptibly(0), -1);
+            equal(phaser.awaitAdvanceInterruptibly(0, 10, SECONDS), -1);
+        } catch (Exception ie) {
+            unexpected(ie);
+        }
+        equal(phaser.getUnarrivedParties(), unarriverParties);
+        equal(phaser.getRegisteredParties(), registeredParties);
+    }
+
+    private static void checkResult(Arriver a, Class<? extends Throwable> c) {
+        Throwable t = a.result();
+        if (! ((t == null && c == null) || (c != null && c.isInstance(t)))) {
+            //      t.printStackTrace();
+            fail("Mismatch in thread " +
+                 a.getName() + ": " +
+                 t + ", " +
+                 (c == null ? "<null>" : c.getName()));
+        } else {
+            pass();
+        }
+    }
+
+    //----------------------------------------------------------------
+    // Mechanism to get all test threads into "running" mode.
+    //----------------------------------------------------------------
+    private static Phaser atTheStartingGate = new Phaser(3);
+
+    private static void toTheStartingGate() {
+        try {
+            boolean expectNextPhase = false;
+            if (atTheStartingGate.getUnarrivedParties() == 1) {
+                expectNextPhase = true;
+            }
+            int phase = atTheStartingGate.getPhase();
+            equal(phase, atTheStartingGate.arrive());
+            int AwaitPhase = atTheStartingGate.awaitAdvanceInterruptibly(phase,
+                                                        10,
+                                                        SECONDS);
+            if (expectNextPhase) check(AwaitPhase == (phase + 1));
+
+            pass();
+        } catch (Throwable t) {
+            unexpected(t);
+           // reset(atTheStartingGate);
+            throw new Error(t);
+        }
+    }
+
+    //----------------------------------------------------------------
+    // Convenience methods for creating threads that call arrive,
+    // awaitAdvance, arriveAndAwaitAdvance, awaitAdvanceInterruptibly
+    //----------------------------------------------------------------
+    private static abstract class Arriver extends Thread {
+        static AtomicInteger count = new AtomicInteger(1);
+
+        Arriver() {
+            this("Arriver");
+        }
+
+        Arriver(String name) {
+            this.setName(name + ":" + count.getAndIncrement());
+            this.setDaemon(true);
+        }
+
+        private volatile Throwable result;
+        private volatile int phase;
+        protected void result(Throwable result) { this.result = result; }
+        public Throwable result() { return this.result; }
+        protected void phase(int phase) { this.phase = phase; }
+        public int phase() { return this.phase; }
+    }
+
+    private static abstract class Awaiter extends Arriver {
+        Awaiter() { super("Awaiter"); }
+        Awaiter(String name) { super(name); }
+    }
+
+    private static Arriver arriver(final Phaser phaser) {
+        return new Arriver() { public void run() {
+            toTheStartingGate();
+
+            try { phase(phaser.arrive()); }
+            catch (Throwable result) { result(result); }}};
+    }
+
+    private static AtomicInteger cycleArriveAwaitAdvance = new AtomicInteger(1);
+
+    private static Awaiter awaiter(final Phaser phaser) {
+        return new Awaiter() { public void run() {
+            toTheStartingGate();
+
+            try {
+                if (cycleArriveAwaitAdvance.getAndIncrement() % 2 == 0)
+                    phase(phaser.awaitAdvance(phaser.arrive()));
+                else
+                    phase(phaser.arriveAndAwaitAdvance());
+            } catch (Throwable result) { result(result); }}};
+    }
+
+    private static Awaiter awaiter(final Phaser phaser,
+                                   final long timeout,
+                                   final TimeUnit unit) {
+        return new Awaiter("InterruptibleWaiter") { public void run() {
+            toTheStartingGate();
+
+            try {
+                if (timeout < 0)
+                    phase(phaser.awaitAdvanceInterruptibly(phaser.arrive()));
+                else
+                    phase(phaser.awaitAdvanceInterruptibly(phaser.arrive(),
+                                                     timeout,
+                                                     unit));
+            } catch (Throwable result) { result(result); }}};
+    }
+
+    // Returns an infinite lazy list of all possible arriver/awaiter combinations.
+    private static Iterator<Arriver> arriverIterator(final Phaser phaser) {
+        return new Iterator<Arriver>() {
+            int i = 0;
+            public boolean hasNext() { return true; }
+            public Arriver next() {
+                switch ((i++)&7) {
+                    case 0: case 4:
+                        return arriver(phaser);
+                    case 1: case 5:
+                        return awaiter(phaser);
+                    case 2: case 6: case 7:
+                        return awaiter(phaser, -1, SECONDS);
+                    default:
+                        return awaiter(phaser, 10, SECONDS); }}
+            public void remove() {throw new UnsupportedOperationException();}};
+    }
+
+    // Returns an infinite lazy list of all possible awaiter only combinations.
+    private static Iterator<Awaiter> awaiterIterator(final Phaser phaser) {
+        return new Iterator<Awaiter>() {
+            int i = 0;
+            public boolean hasNext() { return true; }
+            public Awaiter next() {
+                switch ((i++)&7) {
+                    case 1: case 4: case 7:
+                        return awaiter(phaser);
+                    case 2: case 5:
+                        return awaiter(phaser, -1, SECONDS);
+                    default:
+                        return awaiter(phaser, 10, SECONDS); }}
+            public void remove() {throw new UnsupportedOperationException();}};
+    }
+
+    private static void realMain(String[] args) throws Throwable {
+
+        Thread.currentThread().setName("mainThread");
+
+        //----------------------------------------------------------------
+        // Normal use
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            equal(phaser.getRegisteredParties(), 3);
+            equal(phaser.getArrivedParties(), 0);
+            equal(phaser.getPhase(), 0);
+            check(phaser.getRoot().equals(phaser));
+            equal(phaser.getParent(), null);
+            check(!phaser.isTerminated());
+
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            int phase = 0;
+            for (int i = 0; i < 10; i++) {
+                equal(phaser.getPhase(), phase++);
+                Arriver a1 = arrivers.next(); a1.start();
+                Arriver a2 = arrivers.next(); a2.start();
+                toTheStartingGate();
+                phaser.arriveAndAwaitAdvance();
+                a1.join();
+                a2.join();
+                checkResult(a1, null);
+                checkResult(a2, null);
+                check(!phaser.isTerminated());
+                equal(phaser.getRegisteredParties(), 3);
+                equal(phaser.getArrivedParties(), 0);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // One thread interrupted
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            int phase = phaser.getPhase();
+            for (int i = 0; i < 4; i++) {
+                check(phaser.getPhase() == phase);
+                Awaiter a1 = awaiter(phaser, 10, SECONDS); a1.start();
+                Arriver a2 = arrivers.next(); a2.start();
+                toTheStartingGate();
+                a1.interrupt();
+                a1.join();
+                phaser.arriveAndAwaitAdvance();
+                a2.join();
+                checkResult(a1, InterruptedException.class);
+                checkResult(a2, null);
+                check(!phaser.isTerminated());
+                equal(phaser.getRegisteredParties(), 3);
+                equal(phaser.getArrivedParties(), 0);
+                phase++;
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Phaser is terminated while threads are waiting
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            Iterator<Awaiter> awaiters = awaiterIterator(phaser);
+            for (int i = 0; i < 4; i++) {
+                Arriver a1 = awaiters.next(); a1.start();
+                Arriver a2 = awaiters.next(); a2.start();
+                toTheStartingGate();
+                while (phaser.getArrivedParties() < 2) Thread.yield();
+                phaser.forceTermination();
+                a1.join();
+                a2.join();
+                check(a1.phase == -1);
+                check(a2.phase == -1);
+                int arrivedParties = phaser.getArrivedParties();
+                checkTerminated(phaser);
+                equal(phaser.getArrivedParties(), arrivedParties);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Adds new unarrived parties to this phaser
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(1);
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            LinkedList<Arriver> arriverList = new LinkedList<Arriver>();
+            int phase = phaser.getPhase();
+            for (int i = 1; i < 5; i++) {
+                atTheStartingGate = new Phaser(1+(3*i));
+                check(phaser.getPhase() == phase);
+                // register 3 more
+                phaser.register(); phaser.register(); phaser.register();
+                for (int z=0; z<(3*i); z++) {
+                   arriverList.add(arrivers.next());
+                }
+                for (Arriver arriver : arriverList)
+                    arriver.start();
+
+                toTheStartingGate();
+                phaser.arriveAndAwaitAdvance();
+
+                for (Arriver arriver : arriverList) {
+                    arriver.join();
+                    checkResult(arriver, null);
+                }
+                equal(phaser.getRegisteredParties(), 1 + (3*i));
+                equal(phaser.getArrivedParties(), 0);
+                arriverList.clear();
+                phase++;
+            }
+            atTheStartingGate = new Phaser(3);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // One thread timed out
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            for (long timeout : new long[] { 0L, 5L }) {
+                for (int i = 0; i < 2; i++) {
+                    Awaiter a1 = awaiter(phaser, timeout, SECONDS); a1.start();
+                    Arriver a2 = arrivers.next();                   a2.start();
+                    toTheStartingGate();
+                    a1.join();
+                    checkResult(a1, TimeoutException.class);
+                    phaser.arrive();
+                    a2.join();
+                    checkResult(a2, null);
+                    check(!phaser.isTerminated());
+                }
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Barrier action completed normally
+        //----------------------------------------------------------------
+        try {
+            final AtomicInteger count = new AtomicInteger(0);
+            final Phaser[] kludge = new Phaser[1];
+            Phaser phaser = new Phaser(3) {
+                @Override
+                protected boolean onAdvance(int phase, int registeredParties) {
+                    int countPhase = count.getAndIncrement();
+                    equal(countPhase, phase);
+                    equal(kludge[0].getPhase(), phase);
+                    equal(kludge[0].getRegisteredParties(), registeredParties);
+                    if (phase >= 3)
+                        return true; // terminate
+
+                    return false;
+                }
+            };
+            kludge[0] = phaser;
+            equal(phaser.getRegisteredParties(), 3);
+            Iterator<Awaiter> awaiters = awaiterIterator(phaser);
+            for (int i = 0; i < 4; i++) {
+                Awaiter a1 = awaiters.next(); a1.start();
+                Awaiter a2 = awaiters.next(); a2.start();
+                toTheStartingGate();
+                while (phaser.getArrivedParties() < 2) Thread.yield();
+                phaser.arrive();
+                a1.join();
+                a2.join();
+                checkResult(a1, null);
+                checkResult(a2, null);
+                equal(count.get(), i+1);
+                if (i < 3) {
+                    check(!phaser.isTerminated());
+                    equal(phaser.getRegisteredParties(), 3);
+                    equal(phaser.getArrivedParties(), 0);
+                    equal(phaser.getUnarrivedParties(), 3);
+                    equal(phaser.getPhase(), count.get());
+                } else
+                    checkTerminated(phaser);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    static volatile int passed = 0, failed = 0;
+    static void pass() {passed++;}
+    static void fail() {failed++; Thread.dumpStack();}
+    static void fail(String msg) {System.out.println(msg); fail();}
+    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    static void check(boolean cond) {if (cond) pass(); else fail();}
+    static void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(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);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java	Wed Jul 05 17:02:54 2017 +0200
@@ -21,6 +21,17 @@
  */
 
 /*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
  * @test
  * @bug 6725789
  * @summary Check for long overflow in task time comparison.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/forkjoin/Integrate.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,265 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6865571
+ * @summary Numerical Integration using fork/join
+ * @run main Integrate reps=1 forkPolicy=dynamic
+ * @run main Integrate reps=1 forkPolicy=serial
+ * @run main Integrate reps=1 forkPolicy=fork
+ */
+
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveAction;
+
+/**
+ * Sample program using Gaussian Quadrature for numerical integration.
+ * This version uses a simplified hardwired function.  Inspired by a
+ * <A href="http://www.cs.uga.edu/~dkl/filaments/dist.html">
+ * Filaments</A> demo program.
+ */
+public final class Integrate {
+
+    static final double errorTolerance = 1.0e-11;
+    /** for time conversion */
+    static final long NPS = (1000L * 1000 * 1000);
+
+    static final int SERIAL = -1;
+    static final int DYNAMIC = 0;
+    static final int FORK = 1;
+
+    // the function to integrate
+    static double computeFunction(double x)  {
+        return (x * x + 1.0) * x;
+    }
+
+    static final double start = 0.0;
+    static final double end = 1536.0;
+    /*
+     * The number of recursive calls for
+     * integrate from start to end.
+     * (Empirically determined)
+     */
+    static final int calls = 263479047;
+
+    static String keywordValue(String[] args, String keyword) {
+        for (String arg : args)
+            if (arg.startsWith(keyword))
+                return arg.substring(keyword.length() + 1);
+        return null;
+    }
+
+    static int intArg(String[] args, String keyword, int defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    static int policyArg(String[] args, String keyword, int defaultPolicy) {
+        String val = keywordValue(args, keyword);
+        if (val == null) return defaultPolicy;
+        if (val.equals("dynamic")) return DYNAMIC;
+        if (val.equals("serial")) return SERIAL;
+        if (val.equals("fork")) return FORK;
+        throw new Error();
+    }
+
+    /**
+     * Usage: Integrate [procs=N] [reps=N] forkPolicy=serial|dynamic|fork
+     */
+    public static void main(String[] args) throws Exception {
+        final int procs = intArg(args, "procs",
+                                 Runtime.getRuntime().availableProcessors());
+        final int forkPolicy = policyArg(args, "forkPolicy", DYNAMIC);
+
+        ForkJoinPool g = new ForkJoinPool(procs);
+        System.out.println("Integrating from " + start + " to " + end +
+                           " forkPolicy = " + forkPolicy);
+        long lastTime = System.nanoTime();
+
+        for (int reps = intArg(args, "reps", 10); reps > 0; reps--) {
+            double a;
+            if (forkPolicy == SERIAL)
+                a = SQuad.computeArea(g, start, end);
+            else if (forkPolicy == FORK)
+                a = FQuad.computeArea(g, start, end);
+            else
+                a = DQuad.computeArea(g, start, end);
+            long now = System.nanoTime();
+            double s = (double) (now - lastTime) / NPS;
+            lastTime = now;
+            System.out.printf("Calls/sec: %12d", (long) (calls / s));
+            System.out.printf(" Time: %7.3f", s);
+            System.out.printf(" Area: %12.1f", a);
+            System.out.println();
+        }
+        System.out.println(g);
+        g.shutdown();
+    }
+
+
+    // Sequential version
+    static final class SQuad extends RecursiveAction {
+        static double computeArea(ForkJoinPool pool, double l, double r) {
+            SQuad q = new SQuad(l, r, 0);
+            pool.invoke(q);
+            return q.area;
+        }
+
+        final double left;       // lower bound
+        final double right;      // upper bound
+        double area;
+
+        SQuad(double l, double r, double a) {
+            this.left = l; this.right = r; this.area = a;
+        }
+
+        public final void compute() {
+            double l = left;
+            double r = right;
+            area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area);
+        }
+
+        static final double recEval(double l, double r, double fl,
+                                    double fr, double a) {
+            double h = (r - l) * 0.5;
+            double c = l + h;
+            double fc = (c * c + 1.0) * c;
+            double hh = h * 0.5;
+            double al = (fl + fc) * hh;
+            double ar = (fr + fc) * hh;
+            double alr = al + ar;
+            if (Math.abs(alr - a) <= errorTolerance)
+                return alr;
+            else
+                return recEval(c, r, fc, fr, ar) + recEval(l, c, fl, fc, al);
+        }
+
+    }
+
+    //....................................
+
+    // ForkJoin version
+    static final class FQuad extends RecursiveAction {
+        static double computeArea(ForkJoinPool pool, double l, double r) {
+            FQuad q = new FQuad(l, r, 0);
+            pool.invoke(q);
+            return q.area;
+        }
+
+        final double left;       // lower bound
+        final double right;      // upper bound
+        double area;
+
+        FQuad(double l, double r, double a) {
+            this.left = l; this.right = r; this.area = a;
+        }
+
+        public final void compute() {
+            double l = left;
+            double r = right;
+            area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area);
+        }
+
+        static final double recEval(double l, double r, double fl,
+                                    double fr, double a) {
+            double h = (r - l) * 0.5;
+            double c = l + h;
+            double fc = (c * c + 1.0) * c;
+            double hh = h * 0.5;
+            double al = (fl + fc) * hh;
+            double ar = (fr + fc) * hh;
+            double alr = al + ar;
+            if (Math.abs(alr - a) <= errorTolerance)
+                return alr;
+            FQuad q = new FQuad(l, c, al);
+            q.fork();
+            ar = recEval(c, r, fc, fr, ar);
+            if (!q.tryUnfork()) {
+                q.quietlyHelpJoin();
+                return ar + q.area;
+            }
+            return ar + recEval(l, c, fl, fc, al);
+        }
+
+    }
+
+    // ...........................
+
+    // Version using on-demand Fork
+    static final class DQuad extends RecursiveAction {
+        static double computeArea(ForkJoinPool pool, double l, double r) {
+            DQuad q = new DQuad(l, r, 0);
+            pool.invoke(q);
+            return q.area;
+        }
+
+        final double left;       // lower bound
+        final double right;      // upper bound
+        double area;
+
+        DQuad(double l, double r, double a) {
+            this.left = l; this.right = r; this.area = a;
+        }
+
+        public final void compute() {
+            double l = left;
+            double r = right;
+            area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area);
+        }
+
+        static final double recEval(double l, double r, double fl,
+                                    double fr, double a) {
+            double h = (r - l) * 0.5;
+            double c = l + h;
+            double fc = (c * c + 1.0) * c;
+            double hh = h * 0.5;
+            double al = (fl + fc) * hh;
+            double ar = (fr + fc) * hh;
+            double alr = al + ar;
+            if (Math.abs(alr - a) <= errorTolerance)
+                return alr;
+            DQuad q = null;
+            if (getSurplusQueuedTaskCount() <= 3)
+                (q = new DQuad(l, c, al)).fork();
+            ar = recEval(c, r, fc, fr, ar);
+            if (q != null && !q.tryUnfork()) {
+                q.quietlyHelpJoin();
+                return ar + q.area;
+            }
+            return ar + recEval(l, c, fl, fc, al);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/forkjoin/NQueensCS.java	Wed Jul 05 17:02:54 2017 +0200
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6865571
+ * @summary Solve NQueens using fork/join
+ * @run main NQueensCS maxBoardSize=11 reps=1
+ * @run main NQueensCS maxBoardSize=11 reps=1 procs=8
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveAction;
+
+public class NQueensCS extends RecursiveAction {
+
+    static long lastStealCount;
+    static int boardSize;
+
+    static final int[] expectedSolutions = new int[] {
+        0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200,
+        73712, 365596, 2279184, 14772512, 95815104, 666090624
+    }; // see http://www.durangobill.com/N_Queens.html
+
+    static String keywordValue(String[] args, String keyword) {
+        for (String arg : args)
+            if (arg.startsWith(keyword))
+                return arg.substring(keyword.length() + 1);
+        return null;
+    }
+
+    static int intArg(String[] args, String keyword, int defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    /** for time conversion */
+    static final long NPS = (1000L * 1000L * 1000L);
+
+    /**
+     * Usage: NQueensCS [minBoardSize=N] [maxBoardSize=N] [procs=N] [reps=N]
+     */
+    public static void main(String[] args) throws Exception {
+        // Board sizes too small: hard to measure well.
+        // Board sizes too large: take too long to run.
+        final int minBoardSize = intArg(args, "minBoardSize",  8);
+        final int maxBoardSize = intArg(args, "maxBoardSize", 15);
+
+        final int procs = intArg(args, "procs", 0);
+
+        for (int reps = intArg(args, "reps", 10); reps > 0; reps--) {
+            ForkJoinPool g = (procs == 0) ?
+                new ForkJoinPool() :
+                new ForkJoinPool(procs);
+            lastStealCount = g.getStealCount();
+            for (int i = minBoardSize; i <= maxBoardSize; i++)
+                test(g, i);
+            System.out.println(g);
+            g.shutdown();
+        }
+    }
+
+    static void test(ForkJoinPool g, int i) throws Exception {
+        boardSize = i;
+        int ps = g.getParallelism();
+        long start = System.nanoTime();
+        NQueensCS task = new NQueensCS(new int[0]);
+        g.invoke(task);
+        int solutions = task.solutions;
+        long time = System.nanoTime() - start;
+        double secs = (double) time / NPS;
+        if (solutions != expectedSolutions[i])
+            throw new Error();
+        System.out.printf("NQueensCS %3d", i);
+        System.out.printf(" Time: %7.3f", secs);
+        long sc = g.getStealCount();
+        long ns = sc - lastStealCount;
+        lastStealCount = sc;
+        System.out.printf(" Steals/t: %5d", ns/ps);
+        System.out.println();
+    }
+
+    // Boards are represented as arrays where each cell
+    // holds the column number of the queen in that row
+
+    final int[] sofar;
+    NQueensCS nextSubtask; // to link subtasks
+    int solutions;
+    NQueensCS(int[] a) {
+        this.sofar = a;
+    }
+
+    public final void compute() {
+        NQueensCS subtasks;
+        int bs = boardSize;
+        if (sofar.length >= bs)
+            solutions = 1;
+        else if ((subtasks = explore(sofar, bs)) != null)
+            solutions = processSubtasks(subtasks);
+    }
+
+    private static NQueensCS explore(int[] array, int bs) {
+        int row = array.length;
+        NQueensCS s = null; // subtask list
+        outer:
+        for (int q = 0; q < bs; ++q) {
+            for (int i = 0; i < row; i++) {
+                int p = array[i];
+                if (q == p || q == p - (row - i) || q == p + (row - i))
+                    continue outer; // attacked
+            }
+            NQueensCS first = s; // lag forks to ensure 1 kept
+            if (first != null)
+                first.fork();
+            int[] next = Arrays.copyOf(array, row+1);
+            next[row] = q;
+            NQueensCS subtask = new NQueensCS(next);
+            subtask.nextSubtask = first;
+            s = subtask;
+        }
+        return s;
+    }
+
+    private static int processSubtasks(NQueensCS s) {
+        // Always run first the task held instead of forked
+        s.compute();
+        int ns = s.solutions;
+        s = s.nextSubtask;
+        // Then the unstolen ones
+        while (s != null && s.tryUnfork()) {
+            s.compute();
+            ns += s.solutions;
+            s = s.nextSubtask;
+        }
+        // Then wait for the stolen ones
+        while (s != null) {
+            s.join();
+            ns += s.solutions;
+            s = s.nextSubtask;
+        }
+        return ns;
+    }
+}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java	Wed Jul 05 17:02:54 2017 +0200
@@ -115,7 +115,7 @@
             finally {
                 lock.unlock();
             }
-            if (completed != 2)
+            if (c != 2)
                 throw new Error("Completed != 2");
             int r = result;
             if (r == 0) // avoid overoptimization
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java	Fri Nov 06 17:26:01 2009 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java	Wed Jul 05 17:02:54 2017 +0200
@@ -30,6 +30,7 @@
  * Expert Group and released to the public domain, as explained at
  * http://creativecommons.org/licenses/publicdomain
  */
+
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
--- a/make/hotspot-rules.gmk	Fri Nov 06 17:26:01 2009 -0800
+++ b/make/hotspot-rules.gmk	Wed Jul 05 17:02:54 2017 +0200
@@ -72,6 +72,10 @@
   HOTSPOT_TARGET = all_fastdebug
 endif
 
+ifeq ($(ZERO_BUILD), true)
+  HOTSPOT_TARGET := $(HOTSPOT_TARGET)zero
+endif
+
 HOTSPOT_BUILD_ARGUMENTS += $(COMMON_BUILD_ARGUMENTS)
 HOTSPOT_BUILD_ARGUMENTS += ALT_OUTPUTDIR=$(HOTSPOT_OUTPUTDIR)
 HOTSPOT_BUILD_ARGUMENTS += ALT_EXPORT_PATH=$(HOTSPOT_EXPORT_PATH)