Merge
authorprr
Thu, 21 Jun 2018 09:53:50 -0700
changeset 50825 aa0a35b071fb
parent 50824 871e0ee4bad4 (current diff)
parent 50698 c1f7ece09b84 (diff)
child 50826 f5b95be8b6e2
Merge
src/java.net.http/share/classes/jdk/internal/net/http/ImmutableHeaders.java
src/java.net.http/share/classes/jdk/internal/net/http/common/HttpHeadersImpl.java
test/jdk/java/net/httpclient/ThrowingPublishers.java
test/jdk/java/net/httpclient/ThrowingPushPromises.java
test/jdk/java/net/httpclient/ThrowingSubscribers.java
test/jdk/java/net/httpclient/offline/FixedHttpHeaders.java
--- a/.hgtags	Wed Jun 20 11:12:48 2018 -0700
+++ b/.hgtags	Thu Jun 21 09:53:50 2018 -0700
@@ -490,3 +490,4 @@
 02934b0d661b82b7fe1052a04998d2091352e08d jdk-11+16
 64e4b1686141e57a681936a8283983341484676e jdk-11+17
 e1b3def126240d5433902f3cb0e91a4c27f6db50 jdk-11+18
+fb8b3f4672774e15654958295558a1af1b576919 jdk-11+19
--- a/make/autoconf/flags-cflags.m4	Wed Jun 20 11:12:48 2018 -0700
+++ b/make/autoconf/flags-cflags.m4	Thu Jun 21 09:53:50 2018 -0700
@@ -549,6 +549,7 @@
   elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     WARNING_CFLAGS="-W3"
     WARNING_CFLAGS_JDK="-wd4800"
+    WARNING_CFLAGS_JVM="-wd4800"
   fi
 
   # Set some additional per-OS defines.
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -166,7 +166,6 @@
     tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
   } else {
     eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
-    incr_allocated_bytes(noreg, var_size_in_bytes, con_size_in_bytes, t1);
   }
 }
 
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -722,7 +722,6 @@
           __ ldrw(obj_size, Address(klass, Klass::layout_helper_offset()));
 
           __ eden_allocate(obj, obj_size, 0, t1, slow_path);
-          __ incr_allocated_bytes(rthread, obj_size, 0, rscratch1);
 
           __ initialize_object(obj, klass, obj_size, 0, t1, t2, /* is_tlab_allocated */ false);
           __ verify_oop(obj);
@@ -823,7 +822,6 @@
           __ andr(arr_size, arr_size, ~MinObjAlignmentInBytesMask);
 
           __ eden_allocate(obj, arr_size, 0, t1, slow_path);  // preserves arr_size
-          __ incr_allocated_bytes(rthread, arr_size, 0, rscratch1);
 
           __ initialize_header(obj, klass, length, t1, t2);
           __ ldrb(t1, Address(klass, in_bytes(Klass::layout_helper_offset()) + (Klass::_lh_header_size_shift / BitsPerByte)));
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -24,7 +24,9 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
 #include "runtime/jniHandles.hpp"
+#include "runtime/thread.hpp"
 
 #define __ masm->
 
@@ -121,3 +123,109 @@
   __ andr(obj, obj, ~JNIHandles::weak_tag_mask);
   __ ldr(obj, Address(obj, 0));             // *obj
 }
+
+// Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes.
+void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj,
+                                        Register var_size_in_bytes,
+                                        int con_size_in_bytes,
+                                        Register t1,
+                                        Register t2,
+                                        Label& slow_case) {
+  assert_different_registers(obj, t2);
+  assert_different_registers(obj, var_size_in_bytes);
+  Register end = t2;
+
+  // verify_tlab();
+
+  __ ldr(obj, Address(rthread, JavaThread::tlab_top_offset()));
+  if (var_size_in_bytes == noreg) {
+    __ lea(end, Address(obj, con_size_in_bytes));
+  } else {
+    __ lea(end, Address(obj, var_size_in_bytes));
+  }
+  __ ldr(rscratch1, Address(rthread, JavaThread::tlab_end_offset()));
+  __ cmp(end, rscratch1);
+  __ br(Assembler::HI, slow_case);
+
+  // update the tlab top pointer
+  __ str(end, Address(rthread, JavaThread::tlab_top_offset()));
+
+  // recover var_size_in_bytes if necessary
+  if (var_size_in_bytes == end) {
+    __ sub(var_size_in_bytes, var_size_in_bytes, obj);
+  }
+  // verify_tlab();
+}
+
+// Defines obj, preserves var_size_in_bytes
+void BarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj,
+                                        Register var_size_in_bytes,
+                                        int con_size_in_bytes,
+                                        Register t1,
+                                        Label& slow_case) {
+  assert_different_registers(obj, var_size_in_bytes, t1);
+  if (!Universe::heap()->supports_inline_contig_alloc()) {
+    __ b(slow_case);
+  } else {
+    Register end = t1;
+    Register heap_end = rscratch2;
+    Label retry;
+    __ bind(retry);
+    {
+      unsigned long offset;
+      __ adrp(rscratch1, ExternalAddress((address) Universe::heap()->end_addr()), offset);
+      __ ldr(heap_end, Address(rscratch1, offset));
+    }
+
+    ExternalAddress heap_top((address) Universe::heap()->top_addr());
+
+    // Get the current top of the heap
+    {
+      unsigned long offset;
+      __ adrp(rscratch1, heap_top, offset);
+      // Use add() here after ARDP, rather than lea().
+      // lea() does not generate anything if its offset is zero.
+      // However, relocs expect to find either an ADD or a load/store
+      // insn after an ADRP.  add() always generates an ADD insn, even
+      // for add(Rn, Rn, 0).
+      __ add(rscratch1, rscratch1, offset);
+      __ ldaxr(obj, rscratch1);
+    }
+
+    // Adjust it my the size of our new object
+    if (var_size_in_bytes == noreg) {
+      __ lea(end, Address(obj, con_size_in_bytes));
+    } else {
+      __ lea(end, Address(obj, var_size_in_bytes));
+    }
+
+    // if end < obj then we wrapped around high memory
+    __ cmp(end, obj);
+    __ br(Assembler::LO, slow_case);
+
+    __ cmp(end, heap_end);
+    __ br(Assembler::HI, slow_case);
+
+    // If heap_top hasn't been changed by some other thread, update it.
+    __ stlxr(rscratch2, end, rscratch1);
+    __ cbnzw(rscratch2, retry);
+
+    incr_allocated_bytes(masm, var_size_in_bytes, con_size_in_bytes, t1);
+  }
+}
+
+void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm,
+                                               Register var_size_in_bytes,
+                                               int con_size_in_bytes,
+                                               Register t1) {
+  assert(t1->is_valid(), "need temp reg");
+
+  __ ldr(t1, Address(rthread, in_bytes(JavaThread::allocated_bytes_offset())));
+  if (var_size_in_bytes->is_valid()) {
+    __ add(t1, t1, var_size_in_bytes);
+  } else {
+    __ add(t1, t1, con_size_in_bytes);
+  }
+  __ str(t1, Address(rthread, in_bytes(JavaThread::allocated_bytes_offset())));
+}
+
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -30,6 +30,11 @@
 #include "oops/access.hpp"
 
 class BarrierSetAssembler: public CHeapObj<mtGC> {
+private:
+  void incr_allocated_bytes(MacroAssembler* masm,
+                            Register var_size_in_bytes, int con_size_in_bytes,
+                            Register t1 = noreg);
+
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register addr, Register count, RegSet saved_regs) {}
@@ -46,6 +51,22 @@
   virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
                                              Register obj, Register tmp, Label& slowpath);
 
+  virtual void tlab_allocate(MacroAssembler* masm,
+    Register obj,                      // result: pointer to object after successful allocation
+    Register var_size_in_bytes,        // object size in bytes if unknown at compile time; invalid otherwise
+    int      con_size_in_bytes,        // object size in bytes if   known at compile time
+    Register t1,                       // temp register
+    Register t2,                       // temp register
+    Label&   slow_case                 // continuation point if fast allocation fails
+  );
+
+  void eden_allocate(MacroAssembler* masm,
+    Register obj,                      // result: pointer to object after successful allocation
+    Register var_size_in_bytes,        // object size in bytes if unknown at compile time; invalid otherwise
+    int      con_size_in_bytes,        // object size in bytes if   known at compile time
+    Register t1,                       // temp register
+    Label&   slow_case                 // continuation point if fast allocation fails
+  );
   virtual void barrier_stubs_init() {}
 };
 
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -2440,24 +2440,6 @@
 
 #undef ATOMIC_XCHG
 
-void MacroAssembler::incr_allocated_bytes(Register thread,
-                                          Register var_size_in_bytes,
-                                          int con_size_in_bytes,
-                                          Register t1) {
-  if (!thread->is_valid()) {
-    thread = rthread;
-  }
-  assert(t1->is_valid(), "need temp reg");
-
-  ldr(t1, Address(thread, in_bytes(JavaThread::allocated_bytes_offset())));
-  if (var_size_in_bytes->is_valid()) {
-    add(t1, t1, var_size_in_bytes);
-  } else {
-    add(t1, t1, con_size_in_bytes);
-  }
-  str(t1, Address(thread, in_bytes(JavaThread::allocated_bytes_offset())));
-}
-
 #ifndef PRODUCT
 extern "C" void findpc(intptr_t x);
 #endif
@@ -4085,30 +4067,18 @@
                                    Register t1,
                                    Register t2,
                                    Label& slow_case) {
-  assert_different_registers(obj, t2);
-  assert_different_registers(obj, var_size_in_bytes);
-  Register end = t2;
-
-  // verify_tlab();
-
-  ldr(obj, Address(rthread, JavaThread::tlab_top_offset()));
-  if (var_size_in_bytes == noreg) {
-    lea(end, Address(obj, con_size_in_bytes));
-  } else {
-    lea(end, Address(obj, var_size_in_bytes));
-  }
-  ldr(rscratch1, Address(rthread, JavaThread::tlab_end_offset()));
-  cmp(end, rscratch1);
-  br(Assembler::HI, slow_case);
-
-  // update the tlab top pointer
-  str(end, Address(rthread, JavaThread::tlab_top_offset()));
-
-  // recover var_size_in_bytes if necessary
-  if (var_size_in_bytes == end) {
-    sub(var_size_in_bytes, var_size_in_bytes, obj);
-  }
-  // verify_tlab();
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
+}
+
+// Defines obj, preserves var_size_in_bytes
+void MacroAssembler::eden_allocate(Register obj,
+                                   Register var_size_in_bytes,
+                                   int con_size_in_bytes,
+                                   Register t1,
+                                   Label& slow_case) {
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->eden_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
 }
 
 // Zero words; len is in bytes
@@ -4173,61 +4143,6 @@
   cbnz(len, loop);
 }
 
-// Defines obj, preserves var_size_in_bytes
-void MacroAssembler::eden_allocate(Register obj,
-                                   Register var_size_in_bytes,
-                                   int con_size_in_bytes,
-                                   Register t1,
-                                   Label& slow_case) {
-  assert_different_registers(obj, var_size_in_bytes, t1);
-  if (!Universe::heap()->supports_inline_contig_alloc()) {
-    b(slow_case);
-  } else {
-    Register end = t1;
-    Register heap_end = rscratch2;
-    Label retry;
-    bind(retry);
-    {
-      unsigned long offset;
-      adrp(rscratch1, ExternalAddress((address) Universe::heap()->end_addr()), offset);
-      ldr(heap_end, Address(rscratch1, offset));
-    }
-
-    ExternalAddress heap_top((address) Universe::heap()->top_addr());
-
-    // Get the current top of the heap
-    {
-      unsigned long offset;
-      adrp(rscratch1, heap_top, offset);
-      // Use add() here after ARDP, rather than lea().
-      // lea() does not generate anything if its offset is zero.
-      // However, relocs expect to find either an ADD or a load/store
-      // insn after an ADRP.  add() always generates an ADD insn, even
-      // for add(Rn, Rn, 0).
-      add(rscratch1, rscratch1, offset);
-      ldaxr(obj, rscratch1);
-    }
-
-    // Adjust it my the size of our new object
-    if (var_size_in_bytes == noreg) {
-      lea(end, Address(obj, con_size_in_bytes));
-    } else {
-      lea(end, Address(obj, var_size_in_bytes));
-    }
-
-    // if end < obj then we wrapped around high memory
-    cmp(end, obj);
-    br(Assembler::LO, slow_case);
-
-    cmp(end, heap_end);
-    br(Assembler::HI, slow_case);
-
-    // If heap_top hasn't been changed by some other thread, update it.
-    stlxr(rscratch2, end, rscratch1);
-    cbnzw(rscratch2, retry);
-  }
-}
-
 void MacroAssembler::verify_tlab() {
 #ifdef ASSERT
   if (UseTLAB && VerifyOops) {
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -866,10 +866,6 @@
   void zero_memory(Register addr, Register len, Register t1);
   void verify_tlab();
 
-  void incr_allocated_bytes(Register thread,
-                            Register var_size_in_bytes, int con_size_in_bytes,
-                            Register t1 = noreg);
-
   // interface method calling
   void lookup_interface_method(Register recv_klass,
                                Register intf_klass,
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -3562,7 +3562,6 @@
     // r3: instance size in bytes
     if (allow_shared_alloc) {
       __ eden_allocate(r0, r3, 0, r10, slow_case);
-      __ incr_allocated_bytes(rthread, r3, 0, rscratch1);
     }
   }
 
--- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -3023,8 +3023,8 @@
   mov(Rscratch, SP);
   sub(Rscratch, Rmark, Rscratch);
   ands(Rscratch, Rscratch, imm);
-  b(done, ne); // exit with failure
-  str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes())); // set to zero
+  // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
+  str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
   b(done);
 
 #else
@@ -3034,7 +3034,8 @@
   sub(Rscratch, Rmark, SP, eq);
   movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
   // If still 'eq' then recursive locking OK
-  str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()), eq); // set to zero
+  // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
+  str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
   b(done);
 #endif
 
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -139,10 +139,9 @@
 // Defines obj, preserves var_size_in_bytes
 void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {
   if (UseTLAB) {
-    tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
+    tlab_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
   } else {
-    eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
-    incr_allocated_bytes(noreg, var_size_in_bytes, con_size_in_bytes, t1);
+    eden_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
   }
 }
 
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1056,8 +1056,7 @@
           // get the instance size (size is postive so movl is fine for 64bit)
           __ movl(obj_size, Address(klass, Klass::layout_helper_offset()));
 
-          __ eden_allocate(obj, obj_size, 0, t1, slow_path);
-          __ incr_allocated_bytes(thread, obj_size, 0);
+          __ eden_allocate(thread, obj, obj_size, 0, t1, slow_path);
 
           __ initialize_object(obj, klass, obj_size, 0, t1, t2, /* is_tlab_allocated */ false);
           __ verify_oop(obj);
@@ -1155,12 +1154,10 @@
           __ addptr(arr_size, MinObjAlignmentInBytesMask); // align up
           __ andptr(arr_size, ~MinObjAlignmentInBytesMask);
 
-          __ eden_allocate(obj, arr_size, 0, t1, slow_path);  // preserves arr_size
-
           // Using t2 for non 64-bit.
           const Register thread = NOT_LP64(t2) LP64_ONLY(r15_thread);
           NOT_LP64(__ get_thread(thread));
-          __ incr_allocated_bytes(thread, arr_size, 0);
+          __ eden_allocate(thread, obj, arr_size, 0, t1, slow_path);  // preserves arr_size
 
           __ initialize_header(obj, klass, length, t1, t2);
           __ movb(t1, Address(klass, in_bytes(Klass::layout_helper_offset()) + (Klass::_lh_header_size_shift / BitsPerByte)));
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -24,8 +24,10 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "runtime/jniHandles.hpp"
+#include "runtime/thread.hpp"
 
 #define __ masm->
 
@@ -213,3 +215,110 @@
   __ clear_jweak_tag(obj);
   __ movptr(obj, Address(obj, 0));
 }
+
+void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm,
+                                        Register thread, Register obj,
+                                        Register var_size_in_bytes,
+                                        int con_size_in_bytes,
+                                        Register t1,
+                                        Register t2,
+                                        Label& slow_case) {
+  assert_different_registers(obj, t1, t2);
+  assert_different_registers(obj, var_size_in_bytes, t1);
+  Register end = t2;
+  if (!thread->is_valid()) {
+#ifdef _LP64
+    thread = r15_thread;
+#else
+    assert(t1->is_valid(), "need temp reg");
+    thread = t1;
+    __ get_thread(thread);
+#endif
+  }
+
+  __ verify_tlab();
+
+  __ movptr(obj, Address(thread, JavaThread::tlab_top_offset()));
+  if (var_size_in_bytes == noreg) {
+    __ lea(end, Address(obj, con_size_in_bytes));
+  } else {
+    __ lea(end, Address(obj, var_size_in_bytes, Address::times_1));
+  }
+  __ cmpptr(end, Address(thread, JavaThread::tlab_end_offset()));
+  __ jcc(Assembler::above, slow_case);
+
+  // update the tlab top pointer
+  __ movptr(Address(thread, JavaThread::tlab_top_offset()), end);
+
+  // recover var_size_in_bytes if necessary
+  if (var_size_in_bytes == end) {
+    __ subptr(var_size_in_bytes, obj);
+  }
+  __ verify_tlab();
+}
+
+// Defines obj, preserves var_size_in_bytes
+void BarrierSetAssembler::eden_allocate(MacroAssembler* masm,
+                                        Register thread, Register obj,
+                                        Register var_size_in_bytes,
+                                        int con_size_in_bytes,
+                                        Register t1,
+                                        Label& slow_case) {
+  assert(obj == rax, "obj must be in rax, for cmpxchg");
+  assert_different_registers(obj, var_size_in_bytes, t1);
+  if (!Universe::heap()->supports_inline_contig_alloc()) {
+    __ jmp(slow_case);
+  } else {
+    Register end = t1;
+    Label retry;
+    __ bind(retry);
+    ExternalAddress heap_top((address) Universe::heap()->top_addr());
+    __ movptr(obj, heap_top);
+    if (var_size_in_bytes == noreg) {
+      __ lea(end, Address(obj, con_size_in_bytes));
+    } else {
+      __ lea(end, Address(obj, var_size_in_bytes, Address::times_1));
+    }
+    // if end < obj then we wrapped around => object too long => slow case
+    __ cmpptr(end, obj);
+    __ jcc(Assembler::below, slow_case);
+    __ cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr()));
+    __ jcc(Assembler::above, slow_case);
+    // Compare obj with the top addr, and if still equal, store the new top addr in
+    // end at the address of the top addr pointer. Sets ZF if was equal, and clears
+    // it otherwise. Use lock prefix for atomicity on MPs.
+    __ locked_cmpxchgptr(end, heap_top);
+    __ jcc(Assembler::notEqual, retry);
+    incr_allocated_bytes(masm, thread, var_size_in_bytes, con_size_in_bytes, thread->is_valid() ? noreg : t1);
+  }
+}
+
+void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, Register thread,
+                                               Register var_size_in_bytes,
+                                               int con_size_in_bytes,
+                                               Register t1) {
+  if (!thread->is_valid()) {
+#ifdef _LP64
+    thread = r15_thread;
+#else
+    assert(t1->is_valid(), "need temp reg");
+    thread = t1;
+    __ get_thread(thread);
+#endif
+  }
+
+#ifdef _LP64
+  if (var_size_in_bytes->is_valid()) {
+    __ addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes);
+  } else {
+    __ addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes);
+  }
+#else
+  if (var_size_in_bytes->is_valid()) {
+    __ addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes);
+  } else {
+    __ addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes);
+  }
+  __ adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0);
+#endif
+}
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -32,7 +32,12 @@
 class InterpreterMacroAssembler;
 
 class BarrierSetAssembler: public CHeapObj<mtGC> {
-protected:
+private:
+  void incr_allocated_bytes(MacroAssembler* masm, Register thread,
+                            Register var_size_in_bytes,
+                            int con_size_in_bytes,
+                            Register t1);
+
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count) {}
@@ -60,6 +65,19 @@
   virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
                                              Register obj, Register tmp, Label& slowpath);
 
+  virtual void tlab_allocate(MacroAssembler* masm,
+                             Register thread, Register obj,
+                             Register var_size_in_bytes,
+                             int con_size_in_bytes,
+                             Register t1, Register t2,
+                             Label& slow_case);
+  virtual void eden_allocate(MacroAssembler* masm,
+                             Register thread, Register obj,
+                             Register var_size_in_bytes,
+                             int con_size_in_bytes,
+                             Register t1,
+                             Label& slow_case);
+
   virtual void barrier_stubs_init() {}
 };
 
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -2959,40 +2959,6 @@
 #endif // !LP64 || C1 || !C2 || INCLUDE_JVMCI
 
 
-// Defines obj, preserves var_size_in_bytes
-void MacroAssembler::eden_allocate(Register obj,
-                                   Register var_size_in_bytes,
-                                   int con_size_in_bytes,
-                                   Register t1,
-                                   Label& slow_case) {
-  assert(obj == rax, "obj must be in rax, for cmpxchg");
-  assert_different_registers(obj, var_size_in_bytes, t1);
-  if (!Universe::heap()->supports_inline_contig_alloc()) {
-    jmp(slow_case);
-  } else {
-    Register end = t1;
-    Label retry;
-    bind(retry);
-    ExternalAddress heap_top((address) Universe::heap()->top_addr());
-    movptr(obj, heap_top);
-    if (var_size_in_bytes == noreg) {
-      lea(end, Address(obj, con_size_in_bytes));
-    } else {
-      lea(end, Address(obj, var_size_in_bytes, Address::times_1));
-    }
-    // if end < obj then we wrapped around => object too long => slow case
-    cmpptr(end, obj);
-    jcc(Assembler::below, slow_case);
-    cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr()));
-    jcc(Assembler::above, slow_case);
-    // Compare obj with the top addr, and if still equal, store the new top addr in
-    // end at the address of the top addr pointer. Sets ZF if was equal, and clears
-    // it otherwise. Use lock prefix for atomicity on MPs.
-    locked_cmpxchgptr(end, heap_top);
-    jcc(Assembler::notEqual, retry);
-  }
-}
-
 void MacroAssembler::enter() {
   push(rbp);
   mov(rbp, rsp);
@@ -5310,38 +5276,24 @@
 }
 
 // Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes.
-void MacroAssembler::tlab_allocate(Register obj,
+void MacroAssembler::tlab_allocate(Register thread, Register obj,
                                    Register var_size_in_bytes,
                                    int con_size_in_bytes,
                                    Register t1,
                                    Register t2,
                                    Label& slow_case) {
-  assert_different_registers(obj, t1, t2);
-  assert_different_registers(obj, var_size_in_bytes, t1);
-  Register end = t2;
-  Register thread = NOT_LP64(t1) LP64_ONLY(r15_thread);
-
-  verify_tlab();
-
-  NOT_LP64(get_thread(thread));
-
-  movptr(obj, Address(thread, JavaThread::tlab_top_offset()));
-  if (var_size_in_bytes == noreg) {
-    lea(end, Address(obj, con_size_in_bytes));
-  } else {
-    lea(end, Address(obj, var_size_in_bytes, Address::times_1));
-  }
-  cmpptr(end, Address(thread, JavaThread::tlab_end_offset()));
-  jcc(Assembler::above, slow_case);
-
-  // update the tlab top pointer
-  movptr(Address(thread, JavaThread::tlab_top_offset()), end);
-
-  // recover var_size_in_bytes if necessary
-  if (var_size_in_bytes == end) {
-    subptr(var_size_in_bytes, obj);
-  }
-  verify_tlab();
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->tlab_allocate(this, thread, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
+}
+
+// Defines obj, preserves var_size_in_bytes
+void MacroAssembler::eden_allocate(Register thread, Register obj,
+                                   Register var_size_in_bytes,
+                                   int con_size_in_bytes,
+                                   Register t1,
+                                   Label& slow_case) {
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->eden_allocate(this, thread, obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
 }
 
 // Preserves the contents of address, destroys the contents length_in_bytes and temp.
@@ -5400,36 +5352,6 @@
   bind(done);
 }
 
-void MacroAssembler::incr_allocated_bytes(Register thread,
-                                          Register var_size_in_bytes,
-                                          int con_size_in_bytes,
-                                          Register t1) {
-  if (!thread->is_valid()) {
-#ifdef _LP64
-    thread = r15_thread;
-#else
-    assert(t1->is_valid(), "need temp reg");
-    thread = t1;
-    get_thread(thread);
-#endif
-  }
-
-#ifdef _LP64
-  if (var_size_in_bytes->is_valid()) {
-    addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes);
-  } else {
-    addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes);
-  }
-#else
-  if (var_size_in_bytes->is_valid()) {
-    addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes);
-  } else {
-    addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes);
-  }
-  adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0);
-#endif
-}
-
 // Look up the method for a megamorphic invokeinterface call.
 // The target method is determined by <intf_klass, itable_index>.
 // The receiver klass is in recv_klass.
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -504,6 +504,7 @@
 
   // allocation
   void eden_allocate(
+    Register thread,                   // Current thread
     Register obj,                      // result: pointer to object after successful allocation
     Register var_size_in_bytes,        // object size in bytes if unknown at compile time; invalid otherwise
     int      con_size_in_bytes,        // object size in bytes if   known at compile time
@@ -511,6 +512,7 @@
     Label&   slow_case                 // continuation point if fast allocation fails
   );
   void tlab_allocate(
+    Register thread,                   // Current thread
     Register obj,                      // result: pointer to object after successful allocation
     Register var_size_in_bytes,        // object size in bytes if unknown at compile time; invalid otherwise
     int      con_size_in_bytes,        // object size in bytes if   known at compile time
@@ -520,10 +522,6 @@
   );
   void zero_memory(Register address, Register length_in_bytes, int offset_in_bytes, Register temp);
 
-  void incr_allocated_bytes(Register thread,
-                            Register var_size_in_bytes, int con_size_in_bytes,
-                            Register t1 = noreg);
-
   // interface method calling
   void lookup_interface_method(Register recv_klass,
                                Register intf_klass,
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -4013,7 +4013,7 @@
 #endif // _LP64
 
   if (UseTLAB) {
-    __ tlab_allocate(rax, rdx, 0, rcx, rbx, slow_case);
+    __ tlab_allocate(thread, rax, rdx, 0, rcx, rbx, slow_case);
     if (ZeroTLAB) {
       // the fields have been already cleared
       __ jmp(initialize_header);
@@ -4025,10 +4025,7 @@
     // Allocation in the shared Eden, if allowed.
     //
     // rdx: instance size in bytes
-    if (allow_shared_alloc) {
-      __ eden_allocate(rax, rdx, 0, rbx, slow_case);
-      __ incr_allocated_bytes(thread, rdx, 0);
-    }
+    __ eden_allocate(thread, rax, rdx, 0, rbx, slow_case);
   }
 
   // If UseTLAB or allow_shared_alloc are true, the object is created above and
--- a/src/hotspot/os/aix/os_aix.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/aix/os_aix.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -3737,16 +3737,6 @@
   return buf[0] == 'y' || buf[0] == 'Y';
 }
 
-int os::stat(const char *path, struct stat *sbuf) {
-  char pathbuf[MAX_PATH];
-  if (strlen(path) > MAX_PATH - 1) {
-    errno = ENAMETOOLONG;
-    return -1;
-  }
-  os::native_path(strcpy(pathbuf, path));
-  return ::stat(pathbuf, sbuf);
-}
-
 // Is a (classpath) directory empty?
 bool os::dir_is_empty(const char* path) {
   DIR *dir = NULL;
--- a/src/hotspot/os/aix/os_aix.inline.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/aix/os_aix.inline.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -93,10 +93,6 @@
   return ::fsync(fd);
 }
 
-inline char* os::native_path(char *path) {
-  return path;
-}
-
 inline int os::ftruncate(int fd, jlong length) {
   return ::ftruncate64(fd, length);
 }
--- a/src/hotspot/os/bsd/os_bsd.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/bsd/os_bsd.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -3489,16 +3489,6 @@
   return buf[0] == 'y' || buf[0] == 'Y';
 }
 
-int os::stat(const char *path, struct stat *sbuf) {
-  char pathbuf[MAX_PATH];
-  if (strlen(path) > MAX_PATH - 1) {
-    errno = ENAMETOOLONG;
-    return -1;
-  }
-  os::native_path(strcpy(pathbuf, path));
-  return ::stat(pathbuf, sbuf);
-}
-
 static inline struct timespec get_mtime(const char* filename) {
   struct stat st;
   int ret = os::stat(filename, &st);
--- a/src/hotspot/os/bsd/os_bsd.inline.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/bsd/os_bsd.inline.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -96,10 +96,6 @@
   return ::fsync(fd);
 }
 
-inline char* os::native_path(char *path) {
-  return path;
-}
-
 inline int os::ftruncate(int fd, jlong length) {
   return ::ftruncate(fd, length);
 }
--- a/src/hotspot/os/linux/os_linux.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/linux/os_linux.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -5378,16 +5378,6 @@
   return buf[0] == 'y' || buf[0] == 'Y';
 }
 
-int os::stat(const char *path, struct stat *sbuf) {
-  char pathbuf[MAX_PATH];
-  if (strlen(path) > MAX_PATH - 1) {
-    errno = ENAMETOOLONG;
-    return -1;
-  }
-  os::native_path(strcpy(pathbuf, path));
-  return ::stat(pathbuf, sbuf);
-}
-
 // Is a (classpath) directory empty?
 bool os::dir_is_empty(const char* path) {
   DIR *dir = NULL;
--- a/src/hotspot/os/linux/os_linux.inline.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/linux/os_linux.inline.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -88,10 +88,6 @@
   return ::fsync(fd);
 }
 
-inline char* os::native_path(char *path) {
-  return path;
-}
-
 inline int os::ftruncate(int fd, jlong length) {
   return ::ftruncate64(fd, length);
 }
--- a/src/hotspot/os/posix/os_posix.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/posix/os_posix.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1334,6 +1334,13 @@
 
 }
 
+int os::stat(const char *path, struct stat *sbuf) {
+  return ::stat(path, sbuf);
+}
+
+char * os::native_path(char *path) {
+  return path;
+}
 
 // Check minimum allowable stack sizes for thread creation and to initialize
 // the java system classes, including StackOverflowError - depends on page
--- a/src/hotspot/os/solaris/os_solaris.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1667,16 +1667,6 @@
   return (void*)::dlopen(NULL, RTLD_LAZY);
 }
 
-int os::stat(const char *path, struct stat *sbuf) {
-  char pathbuf[MAX_PATH];
-  if (strlen(path) > MAX_PATH - 1) {
-    errno = ENAMETOOLONG;
-    return -1;
-  }
-  os::native_path(strcpy(pathbuf, path));
-  return ::stat(pathbuf, sbuf);
-}
-
 static inline time_t get_mtime(const char* filename) {
   struct stat st;
   int ret = os::stat(filename, &st);
@@ -4474,10 +4464,6 @@
   return (jlong) ::lseek64(fd, offset, whence);
 }
 
-char * os::native_path(char *path) {
-  return path;
-}
-
 int os::ftruncate(int fd, jlong length) {
   return ::ftruncate64(fd, length);
 }
--- a/src/hotspot/share/classfile/stringTable.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/classfile/stringTable.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -81,7 +81,7 @@
   void check_concurrent_work();
   void trigger_concurrent_work();
 
-  static uintx item_added();
+  static size_t item_added();
   static void item_removed();
   size_t add_items_to_clean(size_t ndead);
 
--- a/src/hotspot/share/code/codeCache.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/code/codeCache.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -409,7 +409,7 @@
   add_heap(heap);
 
   // Reserve Space
-  size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
+  size_t size_initial = MIN2((size_t)InitialCodeCacheSize, rs.size());
   size_initial = align_up(size_initial, os::vm_page_size());
   if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) {
     vm_exit_during_initialization(err_msg("Could not reserve enough space in %s (" SIZE_FORMAT "K)",
--- a/src/hotspot/share/compiler/compilerDefinitions.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/compiler/compilerDefinitions.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -198,7 +198,7 @@
   // Increase the code cache size - tiered compiles a lot more.
   if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
     FLAG_SET_ERGO(uintx, ReservedCodeCacheSize,
-                  MIN2(CODE_CACHE_DEFAULT_LIMIT, ReservedCodeCacheSize * 5));
+                  MIN2(CODE_CACHE_DEFAULT_LIMIT, (size_t)ReservedCodeCacheSize * 5));
   }
   // Enable SegmentedCodeCache if TieredCompilation is enabled and ReservedCodeCacheSize >= 240M
   if (FLAG_IS_DEFAULT(SegmentedCodeCache) && ReservedCodeCacheSize >= 240*M) {
--- a/src/hotspot/share/gc/cms/parNewGeneration.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -203,7 +203,7 @@
   const size_t num_overflow_elems = of_stack->size();
   const size_t space_available = queue->max_elems() - queue->size();
   const size_t num_take_elems = MIN3(space_available / 4,
-                                     ParGCDesiredObjsFromOverflowList,
+                                     (size_t)ParGCDesiredObjsFromOverflowList,
                                      num_overflow_elems);
   // Transfer the most recent num_take_elems from the overflow
   // stack to our work queue.
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -2350,7 +2350,7 @@
   // of things to do) or totally (at the very end).
   size_t target_size;
   if (partially) {
-    target_size = MIN2((size_t)_task_queue->max_elems()/3, GCDrainStackTargetSize);
+    target_size = MIN2((size_t)_task_queue->max_elems()/3, (size_t)GCDrainStackTargetSize);
   } else {
     target_size = 0;
   }
--- a/src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkObjArrayProcessor.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
 }
 
 size_t G1CMObjArrayProcessor::process_array_slice(objArrayOop obj, HeapWord* start_from, size_t remaining) {
-  size_t words_to_scan = MIN2(remaining, ObjArrayMarkingStride);
+  size_t words_to_scan = MIN2(remaining, (size_t)ObjArrayMarkingStride);
 
   if (remaining > ObjArrayMarkingStride) {
     push_array_slice(start_from + ObjArrayMarkingStride);
--- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -91,7 +91,7 @@
   void pretouch_internal(size_t start_page, size_t end_page);
 
   // Returns the index of the page which contains the given address.
-  uintptr_t  addr_to_page_index(char* addr) const;
+  size_t  addr_to_page_index(char* addr) const;
   // Returns the address of the given page index.
   char*  page_start(size_t index) const;
 
--- a/src/hotspot/share/gc/parallel/parallel_globals.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -52,12 +52,12 @@
           "Use maximum compaction in the Parallel Old garbage collector "   \
           "for a system GC")                                                \
                                                                             \
-  product(uintx, ParallelOldDeadWoodLimiterMean, 50,                        \
+  product(size_t, ParallelOldDeadWoodLimiterMean, 50,                        \
           "The mean used by the parallel compact dead wood "                \
           "limiter (a number between 0-100)")                               \
           range(0, 100)                                                     \
                                                                             \
-  product(uintx, ParallelOldDeadWoodLimiterStdDev, 80,                      \
+  product(size_t, ParallelOldDeadWoodLimiterStdDev, 80,                      \
           "The standard deviation used by the parallel compact dead wood "  \
           "limiter (a number between 0-100)")                               \
           range(0, 100)                                                     \
--- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,7 +118,7 @@
   const size_t beg_index = size_t(index);
   assert(beg_index < len || len == 0, "index too large");
 
-  const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride);
+  const size_t stride = MIN2(len - beg_index, (size_t)ObjArrayMarkingStride);
   const size_t end_index = beg_index + stride;
   T* const base = (T*)obj->base_raw();
   T* const beg = base + beg_index;
--- a/src/hotspot/share/gc/shared/plab.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/shared/plab.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 
 size_t PLAB::min_size() {
   // Make sure that we return something that is larger than AlignmentReserve
-  return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
+  return align_object_size(MAX2(MinTLABSize / HeapWordSize, (size_t)oopDesc::header_size())) + AlignmentReserve;
 }
 
 size_t PLAB::max_size() {
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -654,7 +654,7 @@
             STRDEDUP_BYTES_PARAM(_table->_size * sizeof(StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(StringDedupEntry)));
   log.debug("    Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT, _table->_size, _min_size, _max_size);
   log.debug("    Entries: " UINTX_FORMAT ", Load: " STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT,
-            _table->_entries, percent_of(_table->_entries, _table->_size), _entry_cache->size(), _entries_added, _entries_removed);
+            _table->_entries, percent_of((size_t)_table->_entries, _table->_size), _entry_cache->size(), _entries_added, _entries_removed);
   log.debug("    Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" STRDEDUP_PERCENT_FORMAT_NS ")",
             _resize_count, _table->_shrink_threshold, _shrink_load_factor * 100.0, _table->_grow_threshold, _grow_load_factor * 100.0);
   log.debug("    Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x", _rehash_count, _rehash_threshold, _table->_hash_seed);
--- a/src/hotspot/share/gc/z/zArguments.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/z/zArguments.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -91,6 +91,10 @@
   FLAG_SET_DEFAULT(VerifyDuringStartup, false);
   FLAG_SET_DEFAULT(VerifyBeforeExit, false);
 
+  // Verification before heap iteration not (yet) supported, for the
+  // same reason we need fixup_partial_loads
+  FLAG_SET_DEFAULT(VerifyBeforeIteration, false);
+
   // Verification of stacks not (yet) supported, for the same reason
   // we need fixup_partial_loads
   DEBUG_ONLY(FLAG_SET_DEFAULT(VerifyStack, false));
--- a/src/hotspot/share/gc/z/zServiceability.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/gc/z/zServiceability.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -138,6 +138,7 @@
 ZServiceabilityManagerStatsTracer::ZServiceabilityManagerStatsTracer(bool is_gc_begin, bool is_gc_end) :
     _stats(ZHeap::heap()->serviceability_memory_manager(),
            ZCollectedHeap::heap()->gc_cause() /* cause */,
+           true        /* allMemoryPoolsAffected */,
            is_gc_begin /* recordGCBeginTime */,
            is_gc_begin /* recordPreGCUsage */,
            true        /* recordPeakUsage */,
--- a/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -42,6 +42,11 @@
 
 static volatile jbyte suspended = 0;
 bool LeakProfiler::start(jint sample_count) {
+  if (UseZGC) {
+    log_warning(jfr)("LeakProfiler is currently not supported in combination with ZGC");
+    return false;
+  }
+
   if (_object_sampler != NULL) {
     // already started
     return true;
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -87,10 +87,28 @@
 
 static JfrStartFlightRecordingDCmd* _startup_recording = NULL;
 
+static void release_startup_recording() {
+  if (_startup_recording != NULL) {
+    delete _startup_recording;
+    _startup_recording = NULL;
+  }
+}
+
+static void teardown_startup_support() {
+  release_startup_recording();
+  JfrOptionSet::release_startup_recordings();
+}
+
+
 // Parsing options here to detect errors as soon as possible
-static bool parse_startup_recording(TRAPS) {
-  assert(StartFlightRecording != NULL, "invariant");
-  CmdLine cmdline(StartFlightRecording, strlen(StartFlightRecording), true);
+static bool parse_recording_options(const char* options, TRAPS) {
+  assert(options != NULL, "invariant");
+  if (_startup_recording != NULL) {
+    delete _startup_recording;
+  }
+  CmdLine cmdline(options, strlen(options), true);
+  _startup_recording = new (ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
+  assert(_startup_recording != NULL, "invariant");
   _startup_recording->parse(&cmdline, ',', THREAD);
   if (HAS_PENDING_EXCEPTION) {
     java_lang_Throwable::print(PENDING_EXCEPTION, tty);
@@ -100,31 +118,61 @@
   return true;
 }
 
-static bool initialize_startup_recording(TRAPS) {
-  if (StartFlightRecording != NULL) {
-    _startup_recording = new (ResourceObj::C_HEAP, mtTracing) JfrStartFlightRecordingDCmd(tty, true);
-    return _startup_recording != NULL && parse_startup_recording(THREAD);
+static bool validate_recording_options(TRAPS) {
+  const GrowableArray<const char*>* startup_options = JfrOptionSet::startup_recordings();
+  if (startup_options == NULL) {
+    return true;
+  }
+  const int length = startup_options->length();
+  assert(length >= 1, "invariant");
+  for (int i = 0; i < length; ++i) {
+    if (!parse_recording_options(startup_options->at(i), THREAD)) {
+      return false;
+    }
   }
   return true;
 }
 
-static bool startup_recording(TRAPS) {
-  if (_startup_recording == NULL) {
-    return true;
-  }
-  log_trace(jfr, system)("Starting up Jfr startup recording");
+static bool launch_recording(TRAPS) {
+  assert(_startup_recording != NULL, "invariant");
+  log_trace(jfr, system)("Starting a recording");
   _startup_recording->execute(DCmd_Source_Internal, Thread::current());
-  delete _startup_recording;
-  _startup_recording = NULL;
   if (HAS_PENDING_EXCEPTION) {
-    log_debug(jfr, system)("Exception while starting Jfr startup recording");
+    log_debug(jfr, system)("Exception while starting a recording");
     CLEAR_PENDING_EXCEPTION;
     return false;
   }
-  log_trace(jfr, system)("Finished starting Jfr startup recording");
+  log_trace(jfr, system)("Finished starting a recording");
   return true;
 }
 
+static bool launch_recordings(const GrowableArray<const char*>* startup_options, TRAPS) {
+  assert(startup_options != NULL, "invariant");
+  const int length = startup_options->length();
+  assert(length >= 1, "invariant");
+  if (length == 1) {
+    // already parsed and ready, launch it
+    return launch_recording(THREAD);
+  }
+  for (int i = 0; i < length; ++i) {
+    parse_recording_options(startup_options->at(i), THREAD);
+    if (!launch_recording(THREAD)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static bool startup_recordings(TRAPS) {
+  const GrowableArray<const char*>* startup_options = JfrOptionSet::startup_recordings();
+  if (startup_options == NULL) {
+    return true;
+  }
+  const bool ret = launch_recordings(startup_options, THREAD);
+  teardown_startup_support();
+  return ret;
+}
+
 static void log_jdk_jfr_module_resolution_error(TRAPS) {
   LogTarget(Error, jfr, system) lt_error;
   LogTargetHandle handle(lt_error);
@@ -141,7 +189,7 @@
   if (!register_jfr_dcmds()) {
     return false;
   }
-  if (!initialize_startup_recording(thread)) {
+  if (!validate_recording_options(thread)) {
     return false;
   }
   if (in_graph) {
@@ -159,7 +207,7 @@
     log_jdk_jfr_module_resolution_error(thread);
     return false;
   }
-  return startup_recording(thread);
+  return startup_recordings(thread);
 }
 
 static bool _created = false;
--- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -34,6 +34,7 @@
 #include "runtime/thread.inline.hpp"
 #include "services/diagnosticArgument.hpp"
 #include "services/diagnosticFramework.hpp"
+#include "utilities/growableArray.hpp"
 #include "utilities/ostream.hpp"
 
 struct ObsoleteOption {
@@ -664,42 +665,51 @@
   return true;
 }
 
-/*
-
-to support starting multiple startup recordings
-
-static const char* start_flight_recording_option_original = NULL;
-static const char* flight_recorder_option_original = NULL;
-
-static void copy_option_string(const JavaVMOption* option, const char** addr) {
-  assert(option != NULL, "invariant");
-  assert(option->optionString != NULL, "invariant");
-  const size_t length = strlen(option->optionString);
-  *addr = JfrCHeapObj::new_array<char>(length + 1);
-  assert(*addr != NULL, "invarinat");
-  strncpy((char*)*addr, option->optionString, length + 1);
-  assert(strncmp(*addr, option->optionString, length + 1) == 0, "invariant");
-}
-
-copy_option_string(*option, &start_flight_recording_option_original);
-copy_option_string(*option, &flight_recorder_option_original);
-*/
+static GrowableArray<const char*>* startup_recording_array = NULL;
 
 bool JfrOptionSet::parse_start_flight_recording_option(const JavaVMOption** option, char* tail) {
   assert(option != NULL, "invariant");
   assert(tail != NULL, "invariant");
   assert((*option)->optionString != NULL, "invariant");
   assert(strncmp((*option)->optionString, "-XX:StartFlightRecording", 24) == 0, "invariant");
+  const char* param_string = NULL;
   if (*tail == '\0') {
     // Add dummy dumponexit=false so -XX:StartFlightRecording can be used without a parameter.
     // The existing option->optionString points to stack memory so no need to deallocate.
     const_cast<JavaVMOption*>(*option)->optionString = (char*)"-XX:StartFlightRecording=dumponexit=false";
+    param_string = (*option)->optionString + 25;
   } else {
     *tail = '='; // ":" -> "="
+    param_string = tail + 1;
   }
+  assert(param_string != NULL, "invariant");
+  const size_t param_length = strlen(param_string);
+
+  if (startup_recording_array == NULL) {
+    startup_recording_array = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<const char*>(8, true, mtTracing);
+  }
+  assert(startup_recording_array != NULL, "invariant");
+  char* startup_options = NEW_C_HEAP_ARRAY(char, param_length + 1, mtTracing);
+  strncpy(startup_options, param_string, strlen(param_string) + 1);
+  assert(strncmp(param_string, startup_options, param_length) == 0, "invariant");
+  startup_recording_array->append(startup_options);
   return false;
 }
 
+const GrowableArray<const char*>* JfrOptionSet::startup_recordings() {
+  return startup_recording_array;
+}
+
+void JfrOptionSet::release_startup_recordings() {
+  if (startup_recording_array != NULL) {
+    for (int i = 0; i < startup_recording_array->length(); ++i) {
+      FREE_C_HEAP_ARRAY(char, startup_recording_array->at(i));
+    }
+  }
+  delete startup_recording_array;
+  DEBUG_ONLY(startup_recording_array = NULL;)
+}
+
 bool JfrOptionSet::parse_flight_recorder_option(const JavaVMOption** option, char* tail) {
   assert(option != NULL, "invariant");
   assert(tail != NULL, "invariant");
--- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -29,6 +29,9 @@
 #include "memory/allocation.hpp"
 #include "utilities/exceptions.hpp"
 
+template <typename>
+class GrowableArray;
+
 //
 // Command-line options and defaults
 //
@@ -78,6 +81,8 @@
   static bool parse_start_flight_recording_option(const JavaVMOption** option, char* tail);
   static bool parse_flight_recorder_option(const JavaVMOption** option, char* tail);
 
+  static const GrowableArray<const char*>* startup_recordings();
+  static void release_startup_recordings();
 };
 
 #endif // SHARE_VM_JFR_RECORDER_SERVICE_JFROPTIONSET_HPP
--- a/src/hotspot/share/prims/whitebox.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/prims/whitebox.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1116,7 +1116,7 @@
 WB_END
 
 WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
-  uintx result;
+  size_t result;
   if (GetVMFlag <size_t> (thread, env, name, &result, &JVMFlag::size_tAt)) {
     ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
     return longBox(thread, env, result);
--- a/src/hotspot/share/runtime/arguments.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/runtime/arguments.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -540,6 +540,7 @@
   { "PrintSafepointStatisticsCount",JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) },
   { "AggressiveOpts",               JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) },
   { "AllowNonVirtualCalls",         JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) },
+  { "UnlinkSymbolsALot",            JDK_Version::jdk(11), JDK_Version::jdk(12), JDK_Version::jdk(13) },
 
   // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
   { "DefaultMaxRAMFraction",        JDK_Version::jdk(8),  JDK_Version::undefined(), JDK_Version::undefined() },
--- a/src/hotspot/share/runtime/arguments.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/runtime/arguments.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -333,7 +333,7 @@
   // Value of the conservative maximum heap alignment needed
   static size_t  _conservative_max_heap_alignment;
 
-  static uintx  _min_heap_size;
+  static size_t  _min_heap_size;
 
   // -Xrun arguments
   static AgentLibraryList _libraryList;
--- a/src/hotspot/share/runtime/os.hpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/runtime/os.hpp	Thu Jun 21 09:53:50 2018 -0700
@@ -558,6 +558,9 @@
   static FILE* fopen(const char* path, const char* mode);
   static int close(int fd);
   static jlong lseek(int fd, jlong offset, int whence);
+  // This function, on Windows, canonicalizes a given path (see os_windows.cpp for details).
+  // On Posix, this function is a noop: it does not change anything and just returns
+  // the input pointer.
   static char* native_path(char *path);
   static int ftruncate(int fd, jlong length);
   static int fsync(int fd);
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -1989,11 +1989,7 @@
 
 // Handles the uncommon case in locking, i.e., contention or an inflated lock.
 JRT_BLOCK_ENTRY(void, SharedRuntime::complete_monitor_locking_C(oopDesc* _obj, BasicLock* lock, JavaThread* thread))
-  // Disable ObjectSynchronizer::quick_enter() in default config
-  // on AARCH64 and ARM until JDK-8153107 is resolved.
-  if (ARM_ONLY((SyncFlags & 256) != 0 &&)
-      AARCH64_ONLY((SyncFlags & 256) != 0 &&)
-      !SafepointSynchronize::is_synchronizing()) {
+  if (!SafepointSynchronize::is_synchronizing()) {
     // Only try quick_enter() if we're not trying to reach a safepoint
     // so that the calling thread reaches the safepoint more quickly.
     if (ObjectSynchronizer::quick_enter(_obj, thread, lock)) return;
--- a/src/hotspot/share/runtime/vm_version.cpp	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/hotspot/share/runtime/vm_version.cpp	Thu Jun 21 09:53:50 2018 -0700
@@ -115,7 +115,7 @@
 
 const char* Abstract_VM_Version::vm_vendor() {
 #ifdef VENDOR
-  return XSTR(VENDOR);
+  return VENDOR;
 #else
   return "Oracle Corporation";
 #endif
--- a/src/java.base/share/classes/java/util/Collection.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.base/share/classes/java/util/Collection.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,6 +25,7 @@
 
 package java.util;
 
+import java.util.function.IntFunction;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
@@ -276,8 +277,12 @@
      * allocate a new array even if this collection is backed by an array).
      * The caller is thus free to modify the returned array.
      *
-     * <p>This method acts as bridge between array-based and collection-based
-     * APIs.
+     * @apiNote
+     * This method acts as a bridge between array-based and collection-based APIs.
+     * It returns an array whose runtime type is {@code Object[]}.
+     * Use {@link #toArray(Object[]) toArray(T[])} to reuse an existing
+     * array, or use {@link #toArray(IntFunction)} to control the runtime type
+     * of the array.
      *
      * @return an array, whose {@linkplain Class#getComponentType runtime component
      * type} is {@code Object}, containing all of the elements in this collection
@@ -302,19 +307,27 @@
      * are returned by its iterator, this method must return the elements in
      * the same order.
      *
-     * <p>Like the {@link #toArray()} method, this method acts as bridge between
-     * array-based and collection-based APIs.  Further, this method allows
-     * precise control over the runtime type of the output array, and may,
-     * under certain circumstances, be used to save allocation costs.
+     * @apiNote
+     * This method acts as a bridge between array-based and collection-based APIs.
+     * It allows an existing array to be reused under certain circumstances.
+     * Use {@link #toArray()} to create an array whose runtime type is {@code Object[]},
+     * or use {@link #toArray(IntFunction)} to control the runtime type of
+     * the array.
      *
      * <p>Suppose {@code x} is a collection known to contain only strings.
-     * The following code can be used to dump the collection into a newly
-     * allocated array of {@code String}:
+     * The following code can be used to dump the collection into a previously
+     * allocated {@code String} array:
      *
      * <pre>
-     *     String[] y = x.toArray(new String[0]);</pre>
+     *     String[] y = new String[SIZE];
+     *     ...
+     *     y = x.toArray(y);</pre>
      *
-     * Note that {@code toArray(new Object[0])} is identical in function to
+     * <p>The return value is reassigned to the variable {@code y}, because a
+     * new array will be allocated and returned if the collection {@code x} has
+     * too many elements to fit into the existing array {@code y}.
+     *
+     * <p>Note that {@code toArray(new Object[0])} is identical in function to
      * {@code toArray()}.
      *
      * @param <T> the component type of the array to contain the collection
@@ -329,6 +342,45 @@
      */
     <T> T[] toArray(T[] a);
 
+    /**
+     * Returns an array containing all of the elements in this collection,
+     * using the provided {@code generator} function to allocate the returned array.
+     *
+     * <p>If this collection makes any guarantees as to what order its elements
+     * are returned by its iterator, this method must return the elements in
+     * the same order.
+     *
+     * @apiNote
+     * This method acts as a bridge between array-based and collection-based APIs.
+     * It allows creation of an array of a particular runtime type. Use
+     * {@link #toArray()} to create an array whose runtime type is {@code Object[]},
+     * or use {@link #toArray(Object[]) toArray(T[])} to reuse an existing array.
+     *
+     * <p>Suppose {@code x} is a collection known to contain only strings.
+     * The following code can be used to dump the collection into a newly
+     * allocated array of {@code String}:
+     *
+     * <pre>
+     *     String[] y = x.toArray(String[]::new);</pre>
+     *
+     * @implSpec
+     * The default implementation calls the generator function with zero
+     * and then passes the resulting array to {@link #toArray(Object[]) toArray(T[])}.
+     *
+     * @param <T> the component type of the array to contain the collection
+     * @param generator a function which produces a new array of the desired
+     *                  type and the provided length
+     * @return an array containing all of the elements in this collection
+     * @throws ArrayStoreException if the runtime type of any element in this
+     *         collection is not assignable to the {@linkplain Class#getComponentType
+     *         runtime component type} of the generated array
+     * @throws NullPointerException if the generator function is null
+     * @since 11
+     */
+    default <T> T[] toArray(IntFunction<T[]> generator) {
+        return toArray(generator.apply(0));
+    }
+
     // Modification Operations
 
     /**
--- a/src/java.base/share/classes/java/util/Collections.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.base/share/classes/java/util/Collections.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,6 +33,7 @@
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import java.util.function.IntFunction;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
 import java.util.stream.IntStream;
@@ -1028,12 +1029,13 @@
             this.c = c;
         }
 
-        public int size()                   {return c.size();}
-        public boolean isEmpty()            {return c.isEmpty();}
-        public boolean contains(Object o)   {return c.contains(o);}
-        public Object[] toArray()           {return c.toArray();}
-        public <T> T[] toArray(T[] a)       {return c.toArray(a);}
-        public String toString()            {return c.toString();}
+        public int size()                          {return c.size();}
+        public boolean isEmpty()                   {return c.isEmpty();}
+        public boolean contains(Object o)          {return c.contains(o);}
+        public Object[] toArray()                  {return c.toArray();}
+        public <T> T[] toArray(T[] a)              {return c.toArray(a);}
+        public <T> T[] toArray(IntFunction<T[]> f) {return c.toArray(f);}
+        public String toString()                   {return c.toString();}
 
         public Iterator<E> iterator() {
             return new Iterator<E>() {
@@ -2020,6 +2022,9 @@
         public <T> T[] toArray(T[] a) {
             synchronized (mutex) {return c.toArray(a);}
         }
+        public <T> T[] toArray(IntFunction<T[]> f) {
+            synchronized (mutex) {return c.toArray(f);}
+        }
 
         public Iterator<E> iterator() {
             return c.iterator(); // Must be manually synched by user!
@@ -3049,14 +3054,15 @@
             this.type = Objects.requireNonNull(type, "type");
         }
 
-        public int size()                 { return c.size(); }
-        public boolean isEmpty()          { return c.isEmpty(); }
-        public boolean contains(Object o) { return c.contains(o); }
-        public Object[] toArray()         { return c.toArray(); }
-        public <T> T[] toArray(T[] a)     { return c.toArray(a); }
-        public String toString()          { return c.toString(); }
-        public boolean remove(Object o)   { return c.remove(o); }
-        public void clear()               {        c.clear(); }
+        public int size()                          { return c.size(); }
+        public boolean isEmpty()                   { return c.isEmpty(); }
+        public boolean contains(Object o)          { return c.contains(o); }
+        public Object[] toArray()                  { return c.toArray(); }
+        public <T> T[] toArray(T[] a)              { return c.toArray(a); }
+        public <T> T[] toArray(IntFunction<T[]> f) { return c.toArray(f); }
+        public String toString()                   { return c.toString(); }
+        public boolean remove(Object o)            { return c.remove(o); }
+        public void clear()                        {        c.clear(); }
 
         public boolean containsAll(Collection<?> coll) {
             return c.containsAll(coll);
@@ -5559,25 +5565,26 @@
         implements Queue<E>, Serializable {
         private static final long serialVersionUID = 1802017725587941708L;
         private final Deque<E> q;
-        AsLIFOQueue(Deque<E> q)           { this.q = q; }
-        public boolean add(E e)           { q.addFirst(e); return true; }
-        public boolean offer(E e)         { return q.offerFirst(e); }
-        public E poll()                   { return q.pollFirst(); }
-        public E remove()                 { return q.removeFirst(); }
-        public E peek()                   { return q.peekFirst(); }
-        public E element()                { return q.getFirst(); }
-        public void clear()               {        q.clear(); }
-        public int size()                 { return q.size(); }
-        public boolean isEmpty()          { return q.isEmpty(); }
-        public boolean contains(Object o) { return q.contains(o); }
-        public boolean remove(Object o)   { return q.remove(o); }
-        public Iterator<E> iterator()     { return q.iterator(); }
-        public Object[] toArray()         { return q.toArray(); }
-        public <T> T[] toArray(T[] a)     { return q.toArray(a); }
-        public String toString()          { return q.toString(); }
-        public boolean containsAll(Collection<?> c) {return q.containsAll(c);}
-        public boolean removeAll(Collection<?> c)   {return q.removeAll(c);}
-        public boolean retainAll(Collection<?> c)   {return q.retainAll(c);}
+        AsLIFOQueue(Deque<E> q)                     { this.q = q; }
+        public boolean add(E e)                     { q.addFirst(e); return true; }
+        public boolean offer(E e)                   { return q.offerFirst(e); }
+        public E poll()                             { return q.pollFirst(); }
+        public E remove()                           { return q.removeFirst(); }
+        public E peek()                             { return q.peekFirst(); }
+        public E element()                          { return q.getFirst(); }
+        public void clear()                         {        q.clear(); }
+        public int size()                           { return q.size(); }
+        public boolean isEmpty()                    { return q.isEmpty(); }
+        public boolean contains(Object o)           { return q.contains(o); }
+        public boolean remove(Object o)             { return q.remove(o); }
+        public Iterator<E> iterator()               { return q.iterator(); }
+        public Object[] toArray()                   { return q.toArray(); }
+        public <T> T[] toArray(T[] a)               { return q.toArray(a); }
+        public <T> T[] toArray(IntFunction<T[]> f)  { return q.toArray(f); }
+        public String toString()                    { return q.toString(); }
+        public boolean containsAll(Collection<?> c) { return q.containsAll(c); }
+        public boolean removeAll(Collection<?> c)   { return q.removeAll(c); }
+        public boolean retainAll(Collection<?> c)   { return q.retainAll(c); }
         // We use inherited addAll; forwarding addAll would be wrong
 
         // Override default methods in Collection
--- a/src/java.base/share/classes/java/util/ImmutableCollections.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.base/share/classes/java/util/ImmutableCollections.java	Thu Jun 21 09:53:50 2018 -0700
@@ -83,6 +83,16 @@
 
     // ---------- List Implementations ----------
 
+    // make a copy, short-circuiting based on implementation class
+    @SuppressWarnings("unchecked")
+    static <E> List<E> listCopy(Collection<? extends E> coll) {
+        if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
+            return (List<E>)coll;
+        } else {
+            return (List<E>)List.of(coll.toArray());
+        }
+    }
+
     @SuppressWarnings("unchecked")
     static <E> List<E> emptyList() {
         return (List<E>) ListN.EMPTY_LIST;
--- a/src/java.base/share/classes/java/util/List.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.base/share/classes/java/util/List.java	Thu Jun 21 09:53:50 2018 -0700
@@ -1057,12 +1057,7 @@
      * @throws NullPointerException if coll is null, or if it contains any nulls
      * @since 10
      */
-    @SuppressWarnings("unchecked")
     static <E> List<E> copyOf(Collection<? extends E> coll) {
-        if (coll instanceof ImmutableCollections.AbstractImmutableList) {
-            return (List<E>)coll;
-        } else {
-            return (List<E>)List.of(coll.toArray());
-        }
+        return ImmutableCollections.listCopy(coll);
     }
 }
--- a/src/java.base/share/classes/java/util/Properties.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.base/share/classes/java/util/Properties.java	Thu Jun 21 09:53:50 2018 -0700
@@ -47,6 +47,7 @@
 import java.util.function.Function;
 
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.util.xml.PropertiesDefaultHandler;
 
 /**
@@ -140,7 +141,9 @@
     /**
      * use serialVersionUID from JDK 1.1.X for interoperability
      */
-     private static final long serialVersionUID = 4112578634029874840L;
+    private static final long serialVersionUID = 4112578634029874840L;
+
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 
     /**
      * A property list that contains default values for any keys not
@@ -148,7 +151,7 @@
      *
      * @serial
      */
-    protected Properties defaults;
+    protected volatile Properties defaults;
 
     /**
      * Properties does not store values in its inherited Hashtable, but instead
@@ -156,7 +159,7 @@
      * simple read operations.  Writes and bulk operations remain synchronized,
      * as in Hashtable.
      */
-    private transient ConcurrentHashMap<Object, Object> map;
+    private transient volatile ConcurrentHashMap<Object, Object> map;
 
     /**
      * Creates an empty property list with no default values.
@@ -200,6 +203,9 @@
         super((Void) null);
         map = new ConcurrentHashMap<>(initialCapacity);
         this.defaults = defaults;
+
+        // Ensure writes can't be reordered
+        UNSAFE.storeFence();
     }
 
     /**
@@ -1097,7 +1103,8 @@
     public String getProperty(String key) {
         Object oval = map.get(key);
         String sval = (oval instanceof String) ? (String)oval : null;
-        return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
+        Properties defaults;
+        return ((sval == null) && ((defaults = this.defaults) != null)) ? defaults.getProperty(key) : sval;
     }
 
     /**
@@ -1483,6 +1490,7 @@
 
     @Override
     void writeHashtable(ObjectOutputStream s) throws IOException {
+        var map = this.map;
         List<Object> entryStack = new ArrayList<>(map.size() * 2); // an estimate
 
         for (Map.Entry<Object, Object> entry : map.entrySet()) {
@@ -1537,7 +1545,7 @@
                      .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor((int)(elements / 0.75)));
 
         // create CHM of appropriate capacity
-        map = new ConcurrentHashMap<>(elements);
+        var map = new ConcurrentHashMap<>(elements);
 
         // Read all the key/value objects
         for (; elements > 0; elements--) {
@@ -1545,5 +1553,6 @@
             Object value = s.readObject();
             map.put(key, value);
         }
+        this.map = map;
     }
 }
--- a/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java	Thu Jun 21 09:53:50 2018 -0700
@@ -114,6 +114,9 @@
      * Used by RSASignature and RSACipher.
      */
     public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
+        if (key == null) {
+            throw new InvalidKeyException("Key must not be null");
+        }
         if ((key instanceof RSAPrivateKeyImpl) ||
             (key instanceof RSAPrivateCrtKeyImpl) ||
             (key instanceof RSAPublicKeyImpl)) {
--- a/src/java.net.http/share/classes/java/net/http/HttpClient.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/HttpClient.java	Thu Jun 21 09:53:50 2018 -0700
@@ -57,7 +57,7 @@
  * and can be used to send multiple requests.
  *
  * <p> An {@code HttpClient} provides configuration information, and resource
- * sharing, for all requests send through it.
+ * sharing, for all requests sent through it.
  *
  * <p> A {@link BodyHandler BodyHandler} must be supplied for each {@link
  * HttpRequest} sent. The {@code BodyHandler} determines how to handle the
@@ -232,11 +232,10 @@
          *
          * <p> If this method is not invoked prior to {@linkplain #build()
          * building}, a default executor is created for each newly built {@code
-         * HttpClient}. The default executor uses a {@linkplain
-         * Executors#newCachedThreadPool(ThreadFactory) cached thread pool},
-         * with a custom thread factory.
+         * HttpClient}.
          *
-         * @implNote If a security manager has been installed, the thread
+         * @implNote The default executor uses a thread pool, with a custom
+         * thread factory. If a security manager has been installed, the thread
          * factory creates threads that run with an access control context that
          * has no permissions.
          *
@@ -451,7 +450,7 @@
      * then the response, containing the  {@code 3XX} response code, is returned,
      * where it can be handled manually.
      *
-     * <p> {@code Redirect} policy is set via the {@linkplain
+     * <p> {@code Redirect} policy is set through the {@linkplain
      * HttpClient.Builder#followRedirects(Redirect) Builder.followRedirects}
      * method.
      *
--- a/src/java.net.http/share/classes/java/net/http/HttpHeaders.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/HttpHeaders.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,62 +25,68 @@
 
 package java.net.http;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.OptionalLong;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.unmodifiableList;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.function.BiPredicate;
+import static java.lang.String.CASE_INSENSITIVE_ORDER;
+import static java.util.Collections.unmodifiableMap;
 import static java.util.Objects.requireNonNull;
 
 /**
  * A read-only view of a set of HTTP headers.
  *
- * <p> An {@code HttpHeaders} is not created directly, but rather returned from
- * an {@link HttpResponse HttpResponse}. Specific HTTP headers can be set for
- * {@linkplain HttpRequest requests} through the one of the request builder's
- * {@link HttpRequest.Builder#header(String, String) headers} methods.
+ * <p> An {@code HttpHeaders} is not typically created directly, but rather
+ * returned from an {@link HttpRequest#headers() HttpRequest} or an
+ * {@link HttpResponse#headers() HttpResponse}. Specific HTTP headers can be
+ * set for a {@linkplain HttpRequest request} through one of the request
+ * builder's {@link HttpRequest.Builder#header(String, String) headers} methods.
  *
  * <p> The methods of this class ( that accept a String header name ), and the
- * Map returned by the {@link #map() map} method, operate without regard to
- * case when retrieving the header value.
+ * {@code Map} returned by the {@link #map() map} method, operate without regard
+ * to case when retrieving the header value(s).
+ *
+ * <p> An HTTP header name may appear more than once in the HTTP protocol. As
+ * such, headers are represented as a name and a list of values. Each occurrence
+ * of a header value is added verbatim, to the appropriate header name list,
+ * without interpreting its value. In particular, {@code HttpHeaders} does not
+ * perform any splitting or joining of comma separated header value strings. The
+ * order of elements in a header value list is preserved when {@link
+ * HttpRequest.Builder#header(String, String) building} a request. For
+ * responses, the order of elements in a header value list is the order in which
+ * they were received. The {@code Map} returned by the {@code map} method,
+ * however, does not provide any guarantee with regard to the ordering of its
+ * entries.
  *
  * <p> {@code HttpHeaders} instances are immutable.
  *
  * @since 11
  */
-public abstract class HttpHeaders {
-
-    /**
-     * Creates an HttpHeaders.
-     */
-    protected HttpHeaders() {}
+public final class HttpHeaders {
 
     /**
-     * Returns an {@link Optional} containing the first value of the given named
-     * (and possibly multi-valued) header. If the header is not present, then
-     * the returned {@code Optional} is empty.
-     *
-     * @implSpec
-     * The default implementation invokes
-     * {@code allValues(name).stream().findFirst()}
+     * Returns an {@link Optional} containing the first header string value of
+     * the given named (and possibly multi-valued) header. If the header is not
+     * present, then the returned {@code Optional} is empty.
      *
      * @param name the header name
-     * @return an {@code Optional<String>} for the first named value
+     * @return an {@code Optional<String>} containing the first named header
+     *         string value, if present
      */
     public Optional<String> firstValue(String name) {
         return allValues(name).stream().findFirst();
     }
 
     /**
-     * Returns an {@link OptionalLong} containing the first value of the
-     * named header field. If the header is not present, then the Optional is
-     * empty. If the header is present but contains a value that does not parse
-     * as a {@code Long} value, then an exception is thrown.
-     *
-     * @implSpec
-     * The default implementation invokes
-     * {@code allValues(name).stream().mapToLong(Long::valueOf).findFirst()}
+     * Returns an {@link OptionalLong} containing the first header string value
+     * of the named header field. If the header is not present, then the
+     * Optional is empty. If the header is present but contains a value that
+     * does not parse as a {@code Long} value, then an exception is thrown.
      *
      * @param name the header name
      * @return  an {@code OptionalLong}
@@ -92,23 +98,19 @@
     }
 
     /**
-     * Returns an unmodifiable List of all of the values of the given named
-     * header. Always returns a List, which may be empty if the header is not
-     * present.
-     *
-     * @implSpec
-     * The default implementation invokes, among other things, the
-     * {@code map().get(name)} to retrieve the list of header values.
+     * Returns an unmodifiable List of all of the header string values of the
+     * given named header. Always returns a List, which may be empty if the
+     * header is not present.
      *
      * @param name the header name
-     * @return a List of String values
+     * @return a List of headers string values
      */
     public List<String> allValues(String name) {
         requireNonNull(name);
         List<String> values = map().get(name);
         // Making unmodifiable list out of empty in order to make a list which
         // throws UOE unconditionally
-        return values != null ? values : unmodifiableList(emptyList());
+        return values != null ? values : List.of();
     }
 
     /**
@@ -116,7 +118,9 @@
      *
      * @return the Map
      */
-    public abstract Map<String, List<String>> map();
+    public Map<String,List<String>> map() {
+        return headers;
+    }
 
     /**
      * Tests this HTTP headers instance for equality with the given object.
@@ -149,7 +153,11 @@
      * @return the hash-code value for this HTTP headers
      */
     public final int hashCode() {
-        return map().hashCode();
+        int h = 0;
+        for (Map.Entry<String, List<String>> e : map().entrySet()) {
+            h += entryHash(e);
+        }
+        return h;
     }
 
     /**
@@ -165,4 +173,93 @@
         sb.append(" }");
         return sb.toString();
     }
+
+    /**
+     * Returns an HTTP headers from the given map. The given map's key
+     * represents the header name, and its value the list of string header
+     * values for that header name.
+     *
+     * <p> An HTTP header name may appear more than once in the HTTP protocol.
+     * Such, <i>multi-valued</i>, headers must be represented by a single entry
+     * in the given map, whose entry value is a list that represents the
+     * multiple header string values. Leading and trailing whitespaces are
+     * removed from all string values retrieved from the given map and its lists
+     * before processing. Only headers that, after filtering, contain at least
+     * one, possibly empty string, value will be added to the HTTP headers.
+     *
+     * @apiNote The primary purpose of this method is for testing frameworks.
+     * Per-request headers can be set through one of the {@code HttpRequest}
+     * {@link HttpRequest.Builder#header(String, String) headers} methods.
+     *
+     * @param headerMap the map containing the header names and values
+     * @param filter a filter that can be used to inspect each
+     *               header-name-and-value pair in the given map to determine if
+     *               it should, or should not, be added to the to the HTTP
+     *               headers
+     * @return an HTTP headers instance containing the given headers
+     * @throws NullPointerException if any of: {@code headerMap}, a key or value
+     *        in the given map, or an entry in the map's value list, or
+     *        {@code filter}, is {@code null}
+     * @throws IllegalArgumentException if the given {@code headerMap} contains
+     *         any two keys that are equal ( without regard to case ); or if the
+     *         given map contains any key whose length, after trimming
+     *         whitespaces, is {@code 0}
+     */
+    public static HttpHeaders of(Map<String,List<String>> headerMap,
+                                 BiPredicate<String,String> filter) {
+        requireNonNull(headerMap);
+        requireNonNull(filter);
+        return headersOf(headerMap, filter);
+    }
+
+    // --
+
+    private static final HttpHeaders NO_HEADERS = new HttpHeaders(Map.of());
+
+    private final Map<String,List<String>> headers;
+
+    private HttpHeaders(Map<String,List<String>> headers) {
+        this.headers = headers;
+    }
+
+    private static final int entryHash(Map.Entry<String, List<String>> e) {
+        String key = e.getKey();
+        List<String> value = e.getValue();
+        // we know that by construction key and values can't be null
+        int keyHash = key.toLowerCase(Locale.ROOT).hashCode();
+        int valueHash = value.hashCode();
+        return keyHash ^ valueHash;
+    }
+
+    // Returns a new HTTP headers after performing a structural copy and filtering.
+    private static HttpHeaders headersOf(Map<String,List<String>> map,
+                                         BiPredicate<String,String> filter) {
+        TreeMap<String,List<String>> other = new TreeMap<>(CASE_INSENSITIVE_ORDER);
+        TreeSet<String> notAdded = new TreeSet<>(CASE_INSENSITIVE_ORDER);
+        ArrayList<String> tempList = new ArrayList<>();
+        map.forEach((key, value) -> {
+            String headerName = requireNonNull(key).trim();
+            if (headerName.isEmpty()) {
+                throw new IllegalArgumentException("empty key");
+            }
+            List<String> headerValues = requireNonNull(value);
+            headerValues.forEach(headerValue -> {
+                headerValue = requireNonNull(headerValue).trim();
+                if (filter.test(headerName, headerValue)) {
+                    tempList.add(headerValue);
+                }
+            });
+
+            if (tempList.isEmpty()) {
+                if (other.containsKey(headerName)
+                        || notAdded.contains(headerName.toLowerCase(Locale.ROOT)))
+                    throw new IllegalArgumentException("duplicate key: " + headerName);
+                notAdded.add(headerName.toLowerCase(Locale.ROOT));
+            } else if (other.put(headerName, List.copyOf(tempList)) != null) {
+                throw new IllegalArgumentException("duplicate key: " + headerName);
+            }
+            tempList.clear();
+        });
+        return other.isEmpty() ? NO_HEADERS : new HttpHeaders(unmodifiableMap(other));
+    }
 }
--- a/src/java.net.http/share/classes/java/net/http/HttpRequest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/HttpRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -89,10 +89,12 @@
      * <p> Instances of {@code HttpRequest.Builder} are created by calling {@link
      * HttpRequest#newBuilder(URI)} or {@link HttpRequest#newBuilder()}.
      *
-     * <p> Each of the setter methods modifies the state of the builder
-     * and returns the same instance. The methods are not synchronized and
-     * should not be called from multiple threads without external
-     * synchronization. The {@link #build() build} method returns a new
+     * <p> The builder can be used to configure per-request state, such as: the
+     * request URI, the request method (default is GET unless explicitly set),
+     * specific request headers, etc. Each of the setter methods modifies the
+     * state of the builder and returns the same instance. The methods are not
+     * synchronized and should not be called from multiple threads without
+     * external synchronization. The {@link #build() build} method returns a new
      * {@code HttpRequest} each time it is invoked. Once built an {@code
      * HttpRequest} is immutable, and can be sent multiple times.
      *
--- a/src/java.net.http/share/classes/java/net/http/HttpResponse.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/HttpResponse.java	Thu Jun 21 09:53:50 2018 -0700
@@ -830,13 +830,13 @@
      * BodySubscriber} provides implementations of many common body subscribers.
      *
      * <p> The object acts as a {@link Flow.Subscriber}&lt;{@link List}&lt;{@link
-     * ByteBuffer}&gt;&gt; to the HTTP client implementation, which publishes
-     * unmodifiable lists of read-only ByteBuffers containing the response body.
-     * The Flow of data, as well as the order of ByteBuffers in the Flow lists,
-     * is a strictly ordered representation of the response body. Both the Lists
-     * and the ByteBuffers, once passed to the subscriber, are no longer used by
-     * the HTTP client. The subscriber converts the incoming buffers of data to
-     * some higher-level Java type {@code T}.
+     * ByteBuffer}&gt;&gt; to the HTTP Client implementation, which publishes
+     * lists of ByteBuffers containing the response body. The Flow of data, as
+     * well as the order of ByteBuffers in the Flow lists, is a strictly ordered
+     * representation of the response body. Both the Lists and the ByteBuffers,
+     * once passed to the subscriber, are no longer used by the HTTP Client. The
+     * subscriber converts the incoming buffers of data to some higher-level
+     * Java type {@code T}.
      *
      * <p> The {@link #getBody()} method returns a
      * {@link CompletionStage}&lt;{@code T}&gt; that provides the response body
@@ -859,6 +859,9 @@
      * may cause the underlying HTTP connection to be closed and prevent it
      * from being reused for subsequent operations.
      *
+     * @implNote The flow of data containing the response body is immutable.
+     * Specifically, it is a flow of unmodifiable lists of read-only ByteBuffers.
+     *
      * @param <T> the response body type
      * @see BodySubscribers
      * @since 11
@@ -888,20 +891,20 @@
      *
      * <pre>{@code    // Streams the response body to a File
      *   HttpResponse<byte[]> response = client
-     *     .send(request, (statusCode, responseHeaders) -> BodySubscribers.ofByteArray());
+     *     .send(request, responseInfo -> BodySubscribers.ofByteArray());
      *
      *   // Accumulates the response body and returns it as a byte[]
      *   HttpResponse<byte[]> response = client
-     *     .send(request, (statusCode, responseHeaders) -> BodySubscribers.ofByteArray());
+     *     .send(request, responseInfo -> BodySubscribers.ofByteArray());
      *
      *   // Discards the response body
      *   HttpResponse<Void> response = client
-     *     .send(request, (statusCode, responseHeaders) -> BodySubscribers.discarding());
+     *     .send(request, responseInfo -> BodySubscribers.discarding());
      *
      *   // Accumulates the response body as a String then maps it to its bytes
      *   HttpResponse<byte[]> response = client
-     *     .send(request, (sc, hdrs) ->
-     *        BodySubscribers.mapping(BodySubscribers.ofString(), String::getBytes));
+     *     .send(request, responseInfo ->
+     *        BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes));
      * }</pre>
      *
      * @since 11
--- a/src/java.net.http/share/classes/java/net/http/WebSocket.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/WebSocket.java	Thu Jun 21 09:53:50 2018 -0700
@@ -35,9 +35,9 @@
 /**
  * A WebSocket Client.
  *
- * <p> {@code WebSocket} instances can be created via {@link WebSocket.Builder}.
+ * <p> {@code WebSocket} instances are created through {@link WebSocket.Builder}.
  *
- * <p> WebSocket has an input and an output sides. These sides are independent
+ * <p> WebSocket has an input and an output side. These sides are independent
  * from each other. A side can either be open or closed. Once closed, the side
  * remains closed. WebSocket messages are sent through a {@code WebSocket} and
  * received through a {@code WebSocket.Listener} associated with it. Messages
@@ -55,21 +55,22 @@
  *
  * <p> A receive method is any of the {@code onText}, {@code onBinary},
  * {@code onPing}, {@code onPong} and {@code onClose} methods of
- * {@code Listener}. A receive method initiates a receive operation and returns
- * a {@code CompletionStage} which completes once the operation has completed.
+ * {@code Listener}. WebSocket initiates a receive operation by invoking a
+ * receive method on the listener. The listener then must return a
+ * {@code CompletionStage} which completes once the operation has completed.
  *
- * <p> A WebSocket maintains an <a id="counter">internal counter</a>.
- * This counter's value is a number of times the WebSocket has yet to invoke a
- * receive method. While this counter is zero the WebSocket does not invoke
- * receive methods. The counter is incremented by {@code n} when {@code
- * request(n)} is called. The counter is decremented by one when the WebSocket
- * invokes a receive method. {@code onOpen} and {@code onError} are not receive
- * methods. WebSocket invokes {@code onOpen} prior to any other methods on the
- * listener. WebSocket invokes {@code onOpen} at most once. WebSocket may invoke
- * {@code onError} at any given time. If the WebSocket invokes {@code onError}
- * or {@code onClose}, then no further listener's methods will be invoked, no
- * matter the value of the counter. For a newly built WebSocket the counter is
- * zero. A WebSocket invokes methods on the listener in a thread-safe manner.
+ * <p> To control receiving of messages, a WebSocket maintains an
+ * <a id="counter">internal counter</a>. This counter's value is a number of
+ * times the WebSocket has yet to invoke a receive method. While this counter is
+ * zero the WebSocket does not invoke receive methods. The counter is
+ * incremented by {@code n} when {@code request(n)} is called. The counter is
+ * decremented by one when the WebSocket invokes a receive method.
+ * {@code onOpen} and {@code onError} are not receive methods. WebSocket invokes
+ * {@code onOpen} prior to any other methods on the listener. WebSocket invokes
+ * {@code onOpen} at most once. WebSocket may invoke {@code onError} at any
+ * given time. If the WebSocket invokes {@code onError} or {@code onClose}, then
+ * no further listener's methods will be invoked, no matter the value of the
+ * counter. For a newly built WebSocket the counter is zero.
  *
  * <p> Unless otherwise stated, {@code null} arguments will cause methods
  * of {@code WebSocket} to throw {@code NullPointerException}, similarly,
@@ -105,13 +106,13 @@
     /**
      * A builder of {@linkplain WebSocket WebSocket Clients}.
      *
-     * <p> A builder can be created by invoking the
-     * {@link HttpClient#newWebSocketBuilder HttpClient.newWebSocketBuilder}
-     * method. The intermediate (setter-like) methods change the state of the
-     * builder and return the same builder they have been invoked on. If an
-     * intermediate method is not invoked, an appropriate default value (or
-     * behavior) will be assumed. A {@code Builder} is not safe for use by
-     * multiple threads without external synchronization.
+     * <p> Builders are created by invoking
+     * {@link HttpClient#newWebSocketBuilder HttpClient.newWebSocketBuilder}.
+     * The intermediate (setter-like) methods change the state of the builder
+     * and return the same builder they have been invoked on. If an intermediate
+     * method is not invoked, an appropriate default value (or behavior) will be
+     * assumed. A {@code Builder} is not safe for use by multiple threads
+     * without external synchronization.
      *
      * @since 11
      */
@@ -155,7 +156,7 @@
          * Sets a request for the given subprotocols.
          *
          * <p> After the {@code WebSocket} has been built, the actual
-         * subprotocol can be queried via
+         * subprotocol can be queried through
          * {@link WebSocket#getSubprotocol WebSocket.getSubprotocol()}.
          *
          * <p> Subprotocols are specified in the order of preference. The most
@@ -218,11 +219,17 @@
      * The receiving interface of {@code WebSocket}.
      *
      * <p> A {@code WebSocket} invokes methods of the associated listener
-     * passing itself as an argument. When data has been received, the
-     * {@code WebSocket} invokes a receive method. Methods {@code onText},
-     * {@code onBinary}, {@code onPing} and {@code onPong} must return a
-     * {@code CompletionStage} that completes once the message has been received
-     * by the listener.
+     * passing itself as an argument. These methods are invoked in a thread-safe
+     * manner, such that the next invocation may start only after the previous
+     * one has finished.
+     *
+     * <p> When data has been received, the {@code WebSocket} invokes a receive
+     * method. Methods {@code onText}, {@code onBinary}, {@code onPing} and
+     * {@code onPong} must return a {@code CompletionStage} that completes once
+     * the message has been received by the listener. If a listener's method
+     * returns {@code null} rather than a {@code CompletionStage},
+     * {@code WebSocket} will behave as if the listener returned a
+     * {@code CompletionStage} that is already completed normally.
      *
      * <p> An {@code IOException} raised in {@code WebSocket} will result in an
      * invocation of {@code onError} with that exception (if the input is not
@@ -231,11 +238,14 @@
      * exceptionally, the WebSocket will invoke {@code onError} with this
      * exception.
      *
-     * <p> If a listener's method returns {@code null} rather than a
-     * {@code CompletionStage}, {@code WebSocket} will behave as if the listener
-     * returned a {@code CompletionStage} that is already completed normally.
+     * @apiNote The strict sequential order of invocations from
+     * {@code WebSocket} to {@code Listener} means, in particular, that the
+     * {@code Listener}'s methods are treated as non-reentrant. This means that
+     * {@code Listener} implementations do not need to be concerned with
+     * possible recursion or the order in which they invoke
+     * {@code WebSocket.request} in relation to their processing logic.
      *
-     * @apiNote Careful attention may be required if a listener is associated
+     * <p> Careful attention may be required if a listener is associated
      * with more than a single {@code WebSocket}. In this case invocations
      * related to different instances of {@code WebSocket} may not be ordered
      * and may even happen concurrently.
--- a/src/java.net.http/share/classes/java/net/http/WebSocketHandshakeException.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/WebSocketHandshakeException.java	Thu Jun 21 09:53:50 2018 -0700
@@ -28,7 +28,7 @@
 import java.io.IOException;
 
 /**
- * An exception used to signal the opening handshake failed.
+ * Thrown when the opening handshake has failed.
  *
  * @since 11
  */
@@ -55,6 +55,10 @@
      * <p> The value may be unavailable ({@code null}) if this exception has
      * been serialized and then deserialized.
      *
+     * @apiNote The primary purpose of this method is to allow programmatic
+     * examination of the reasons behind the failure of the opening handshake.
+     * Some of these reasons might allow recovery.
+     *
      * @return server response
      */
     public HttpResponse<?> getResponse() {
--- a/src/java.net.http/share/classes/java/net/http/package-info.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/java/net/http/package-info.java	Thu Jun 21 09:53:50 2018 -0700
@@ -42,20 +42,24 @@
  * Hypertext Transfer Protocol (HTTP/1.1)</a>, and
  * <a href="https://tools.ietf.org/html/rfc6455">The WebSocket Protocol</a>.
  *
- * <p> Asynchronous tasks and dependent actions of returned {@link
- * java.util.concurrent.CompletableFuture} instances are executed on the threads
- * supplied by the client's {@link java.util.concurrent.Executor}, where
- * practical.
+ * <p> In general, asynchronous tasks execute in either the thread invoking
+ * the operation, e.g. {@linkplain HttpClient#send(HttpRequest, BodyHandler)
+ * sending} an HTTP request, or by the threads supplied by the client's {@link
+ * HttpClient#executor() executor}. Dependent tasks, those that are triggered by
+ * returned CompletionStages or CompletableFutures, that do not explicitly
+ * specify an executor, execute in the same {@link
+ * CompletableFuture#defaultExecutor() default executor} as that of {@code
+ * CompletableFuture}, or the invoking thread if the operation completes before
+ * the dependent task is registered.
  *
  * <p> {@code CompletableFuture}s returned by this API will throw {@link
- * java.lang.UnsupportedOperationException} for their {@link
- * java.util.concurrent.CompletableFuture#obtrudeValue(Object) obtrudeValue}
- * and {@link java.util.concurrent.CompletableFuture#obtrudeException(Throwable)
- * obtrudeException} methods. Invoking the {@link
- * java.util.concurrent.CompletableFuture#cancel cancel} method on a {@code
- * CompletableFuture} returned by this API will not interrupt the underlying
- * operation, but may be useful to complete, exceptionally, dependent stages
- * that have not already completed.
+ * UnsupportedOperationException} for their {@link
+ * CompletableFuture#obtrudeValue(Object) obtrudeValue}
+ * and {@link CompletableFuture#obtrudeException(Throwable)
+ * obtrudeException} methods. Invoking the {@link CompletableFuture#cancel
+ * cancel} method on a {@code CompletableFuture} returned by this API may not
+ * interrupt the underlying operation, but may be useful to complete,
+ * exceptionally, dependent stages that have not already completed.
  *
  * <p> Unless otherwise stated, {@code null} parameter values will cause methods
  * of all classes in this package to throw {@code NullPointerException}.
@@ -63,3 +67,9 @@
  * @since 11
  */
 package java.net.http;
+
+import java.lang.UnsupportedOperationException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse.BodyHandler;
+import java.util.concurrent.CompletableFuture;
--- a/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/AuthenticationFilter.java	Thu Jun 21 09:53:50 2018 -0700
@@ -34,7 +34,6 @@
 import java.net.URL;
 import java.util.Base64;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.Objects;
 import java.util.WeakHashMap;
 import java.net.http.HttpHeaders;
@@ -59,9 +58,9 @@
     static final int UNAUTHORIZED = 401;
     static final int PROXY_UNAUTHORIZED = 407;
 
-    private static final List<String> BASIC_DUMMY =
-            List.of("Basic " + Base64.getEncoder()
-                    .encodeToString("o:o".getBytes(ISO_8859_1)));
+    private static final String BASIC_DUMMY =
+            "Basic " + Base64.getEncoder()
+                    .encodeToString("o:o".getBytes(ISO_8859_1));
 
     // A public no-arg constructor is required by FilterFactory
     public AuthenticationFilter() {}
@@ -182,14 +181,12 @@
         String value = "Basic " + s;
         if (proxy) {
             if (r.isConnect()) {
-                if (!Utils.PROXY_TUNNEL_FILTER
-                        .test(hdrname, List.of(value))) {
+                if (!Utils.PROXY_TUNNEL_FILTER.test(hdrname, value)) {
                     Log.logError("{0} disabled", hdrname);
                     return;
                 }
             } else if (r.proxy() != null) {
-                if (!Utils.PROXY_FILTER
-                        .test(hdrname, List.of(value))) {
+                if (!Utils.PROXY_FILTER.test(hdrname, value)) {
                     Log.logError("{0} disabled", hdrname);
                     return;
                 }
@@ -261,9 +258,16 @@
 
         boolean proxy = status == PROXY_UNAUTHORIZED;
         String authname = proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
-        String authval = hdrs.firstValue(authname).orElseThrow(() -> {
-            return new IOException("Invalid auth header");
-        });
+        String authval = hdrs.firstValue(authname).orElse(null);
+        if (authval == null) {
+            if (exchange.client().authenticator().isPresent()) {
+                throw new IOException(authname + " header missing for response code " + status);
+            } else {
+                // No authenticator? let the caller deal with this.
+                return null;
+            }
+        }
+
         HeaderParser parser = new HeaderParser(authval);
         String scheme = parser.findKey(0);
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java	Thu Jun 21 09:53:50 2018 -0700
@@ -53,6 +53,8 @@
 
     static final long KEEP_ALIVE = Utils.getIntegerNetProperty(
             "jdk.httpclient.keepalive.timeout", 1200); // seconds
+    static final long MAX_POOL_SIZE = Utils.getIntegerNetProperty(
+            "jdk.httpclient.connectionPoolSize", 0); // unbounded
     final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
 
     // Pools of idle connections
@@ -160,6 +162,7 @@
         CleanupTrigger cleanup = registerCleanupTrigger(conn);
 
         // it's possible that cleanup may have been called.
+        HttpConnection toClose = null;
         synchronized(this) {
             if (cleanup.isDone()) {
                 return;
@@ -167,6 +170,10 @@
                 conn.close();
                 return;
             }
+            if (MAX_POOL_SIZE > 0 && expiryList.size() >= MAX_POOL_SIZE) {
+                toClose = expiryList.removeOldest();
+                if (toClose != null) removeFromPool(toClose);
+            }
             if (conn instanceof PlainHttpConnection) {
                 putConnection(conn, plainPool);
             } else {
@@ -175,6 +182,13 @@
             }
             expiryList.add(conn, now, keepAlive);
         }
+        if (toClose != null) {
+            if (debug.on()) {
+                debug.log("Maximum pool size reached: removing oldest connection %s",
+                          toClose.dbgString());
+            }
+            close(toClose);
+        }
         //System.out.println("Return to pool: " + conn);
     }
 
@@ -314,6 +328,8 @@
         private final LinkedList<ExpiryEntry> list = new LinkedList<>();
         private volatile boolean mayContainEntries;
 
+        int size() { return list.size(); }
+
         // A loosely accurate boolean whose value is computed
         // at the end of each operation performed on ExpiryList;
         // Does not require synchronizing on the ConnectionPool.
@@ -331,6 +347,13 @@
 
         // should only be called while holding a synchronization
         // lock on the ConnectionPool
+        HttpConnection removeOldest() {
+            ExpiryEntry entry = list.pollLast();
+            return entry == null ? null : entry.connection;
+        }
+
+        // should only be called while holding a synchronization
+        // lock on the ConnectionPool
         void add(HttpConnection conn) {
             add(conn, Instant.now(), KEEP_ALIVE);
         }
@@ -419,17 +442,38 @@
         }
     }
 
+    // Remove a connection from the pool.
+    // should only be called while holding a synchronization
+    // lock on the ConnectionPool
+    private void removeFromPool(HttpConnection c) {
+        assert Thread.holdsLock(this);
+        if (c instanceof PlainHttpConnection) {
+            removeFromPool(c, plainPool);
+        } else {
+            assert c.isSecure();
+            removeFromPool(c, sslPool);
+        }
+    }
+
+    // Used by tests
+    synchronized boolean contains(HttpConnection c) {
+        final CacheKey key = c.cacheKey();
+        List<HttpConnection> list;
+        if ((list = plainPool.get(key)) != null) {
+            if (list.contains(c)) return true;
+        }
+        if ((list = sslPool.get(key)) != null) {
+            if (list.contains(c)) return true;
+        }
+        return false;
+    }
+
     void cleanup(HttpConnection c, Throwable error) {
         if (debug.on())
             debug.log("%s : ConnectionPool.cleanup(%s)",
                     String.valueOf(c.getConnectionFlow()), error);
         synchronized(this) {
-            if (c instanceof PlainHttpConnection) {
-                removeFromPool(c, plainPool);
-            } else {
-                assert c.isSecure();
-                removeFromPool(c, sslPool);
-            }
+            removeFromPool(c);
             expiryList.remove(c);
         }
         c.close();
--- a/src/java.net.http/share/classes/jdk/internal/net/http/CookieFilter.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/CookieFilter.java	Thu Jun 21 09:53:50 2018 -0700
@@ -31,7 +31,7 @@
 import java.util.Map;
 import java.util.Optional;
 import java.net.http.HttpHeaders;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Log;
 import jdk.internal.net.http.common.Utils;
 
@@ -50,7 +50,7 @@
             Map<String,List<String>> cookies = cookieHandler.get(r.uri(), userheaders);
 
             // add the returned cookies
-            HttpHeadersImpl systemHeaders = r.getSystemHeaders();
+            HttpHeadersBuilder systemHeadersBuilder = r.getSystemHeadersBuilder();
             if (cookies.isEmpty()) {
                 Log.logTrace("Request: no cookie to add for {0}", r.uri());
             } else {
@@ -65,7 +65,7 @@
                 if (values == null || values.isEmpty()) continue;
                 for (String val : values) {
                     if (Utils.isValidValue(val)) {
-                        systemHeaders.addHeader(hdrname, val);
+                        systemHeadersBuilder.addHeader(hdrname, val);
                     }
                 }
             }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java	Thu Jun 21 09:53:50 2018 -0700
@@ -307,6 +307,7 @@
                                                     Function<ExchangeImpl<T>,CompletableFuture<Response>> andThen) {
         t = Utils.getCompletionCause(t);
         if (t instanceof ProxyAuthenticationRequired) {
+            if (debug.on()) debug.log("checkFor407: ProxyAuthenticationRequired: building synthetic response");
             bodyIgnored = MinimalFuture.completedFuture(null);
             Response proxyResponse = ((ProxyAuthenticationRequired)t).proxyResponse;
             HttpConnection c = ex == null ? null : ex.connection();
@@ -315,8 +316,10 @@
                     proxyResponse.version, true);
             return MinimalFuture.completedFuture(syntheticResponse);
         } else if (t != null) {
+            if (debug.on()) debug.log("checkFor407: no response - %s", t);
             return MinimalFuture.failedFuture(t);
         } else {
+            if (debug.on()) debug.log("checkFor407: all clear");
             return andThen.apply(ex);
         }
     }
@@ -332,6 +335,7 @@
             int rcode = r1.statusCode();
             if (rcode == 100) {
                 Log.logTrace("Received 100-Continue: sending body");
+                if (debug.on()) debug.log("Received 100-Continue for %s", r1);
                 CompletableFuture<Response> cf =
                         exchImpl.sendBodyAsync()
                                 .thenCompose(exIm -> exIm.getResponseAsync(parentExecutor));
@@ -341,6 +345,7 @@
             } else {
                 Log.logTrace("Expectation failed: Received {0}",
                         rcode);
+                if (debug.on()) debug.log("Expect-Continue failed (%d) for: %s", rcode, r1);
                 if (upgrading && rcode == 101) {
                     IOException failed = new IOException(
                             "Unable to handle 101 while waiting for 100");
@@ -357,6 +362,7 @@
     // send the request body and proceed.
     private CompletableFuture<Response> sendRequestBody(ExchangeImpl<T> ex) {
         assert !request.expectContinue();
+        if (debug.on()) debug.log("sendRequestBody");
         CompletableFuture<Response> cf = ex.sendBodyAsync()
                 .thenCompose(exIm -> exIm.getResponseAsync(parentExecutor));
         cf = wrapForUpgrade(cf);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -32,8 +32,8 @@
 import java.net.http.HttpResponse;
 import jdk.internal.net.http.common.Logger;
 import jdk.internal.net.http.common.MinimalFuture;
+import jdk.internal.net.http.common.Utils;
 import static java.net.http.HttpClient.Version.HTTP_1_1;
-import jdk.internal.net.http.common.Utils;
 
 /**
  * Splits request so that headers and body can be sent separately with optional
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1AsyncReceiver.java	Thu Jun 21 09:53:50 2018 -0700
@@ -27,7 +27,6 @@
 
 import java.io.EOFException;
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -42,7 +41,9 @@
 import java.util.function.Consumer;
 import jdk.internal.net.http.common.Demand;
 import jdk.internal.net.http.common.FlowTube.TubeSubscriber;
+import jdk.internal.net.http.common.Log;
 import jdk.internal.net.http.common.Logger;
+import jdk.internal.net.http.common.MinimalFuture;
 import jdk.internal.net.http.common.SequentialScheduler;
 import jdk.internal.net.http.common.ConnectionExpiredException;
 import jdk.internal.net.http.common.Utils;
@@ -166,6 +167,7 @@
             = new ConcurrentLinkedDeque<>();
     private final SequentialScheduler scheduler =
             SequentialScheduler.synchronizedScheduler(this::flush);
+    final MinimalFuture<Void> whenFinished;
     private final Executor executor;
     private final Http1TubeSubscriber subscriber = new Http1TubeSubscriber();
     private final AtomicReference<Http1AsyncDelegate> pendingDelegateRef;
@@ -184,6 +186,7 @@
     public Http1AsyncReceiver(Executor executor, Http1Exchange<?> owner) {
         this.pendingDelegateRef = new AtomicReference<>();
         this.executor = executor;
+        this.whenFinished = new MinimalFuture<>();
         this.owner = owner;
         this.client = owner.client;
     }
@@ -261,6 +264,14 @@
         }
     }
 
+    private String describe() {
+        Http1Exchange<?> exchange = owner;
+        if (exchange != null) {
+            return String.valueOf(exchange.request());
+        }
+        return "<uri unavailable>";
+    }
+
     /**
      * Must be called from within the scheduler main loop.
      * Handles any pending errors by calling delegate.onReadError().
@@ -284,6 +295,10 @@
                           + "\t\t queue.isEmpty: " + queue.isEmpty());
             scheduler.stop();
             delegate.onReadError(x);
+            whenFinished.completeExceptionally(x);
+            if (Log.channel()) {
+                Log.logChannel("HTTP/1 read subscriber stopped for: {0}", describe());
+            }
             if (stopRequested) {
                 // This is the special case where the subscriber
                 // has requested an illegal number of items.
@@ -464,27 +479,35 @@
                         // throw ConnectionExpiredException
                         // to try & force a retry of the request.
                         retry = false;
-                        ex = new ConnectionExpiredException(
-                                "subscription is finished", ex);
+                        ex = new ConnectionExpiredException(ex);
                     }
                 }
                 error = ex;
             }
+        }
             final Throwable t = (recorded == null ? ex : recorded);
             if (debug.on())
                 debug.log("recorded " + t + "\n\t delegate: " + delegate
                           + "\t\t queue.isEmpty: " + queue.isEmpty(), ex);
+        if (Log.errors()) {
+            Log.logError("HTTP/1 read subscriber recorded error: {0} - {1}", describe(), t);
         }
         if (queue.isEmpty() || pendingDelegateRef.get() != null || stopRequested) {
             // This callback is called from within the selector thread.
             // Use an executor here to avoid doing the heavy lifting in the
             // selector.
+            if (Log.errors()) {
+                Log.logError("HTTP/1 propagating recorded error: {0} - {1}", describe(), t);
+            }
             scheduler.runOrSchedule(executor);
         }
     }
 
     void stop() {
         if (debug.on()) debug.log("stopping");
+        if (Log.channel() && !scheduler.isStopped()) {
+            Log.logChannel("HTTP/1 read subscriber stopped for {0}", describe());
+        }
         scheduler.stop();
         // make sure ref count is handled properly by
         // closing the delegate.
@@ -492,6 +515,7 @@
         if (previous != null) previous.close(error);
         delegate = null;
         owner  = null;
+        whenFinished.complete(null);
     }
 
     /**
@@ -514,12 +538,18 @@
             // supports being called multiple time.
             // doesn't cancel the previous subscription, since that is
             // most probably the same as the new subscription.
+            if (debug.on()) debug.log("Received onSubscribed from upstream");
+            if (Log.channel()) {
+                Log.logChannel("HTTP/1 read subscriber got subscription from {0}", describe());
+            }
             assert this.subscription == null || dropped == false;
             this.subscription = subscription;
             dropped = false;
             canRequestMore.set(true);
             if (delegate != null) {
                 scheduler.runOrSchedule(executor);
+            } else {
+                if (debug.on()) debug.log("onSubscribe: read delegate not present yet");
             }
         }
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,7 +26,6 @@
 package jdk.internal.net.http;
 
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.net.InetSocketAddress;
 import java.net.http.HttpResponse.BodyHandler;
 import java.net.http.HttpResponse.BodySubscriber;
@@ -46,6 +45,7 @@
 import jdk.internal.net.http.common.MinimalFuture;
 import jdk.internal.net.http.common.Utils;
 import static java.net.http.HttpClient.Version.HTTP_1_1;
+import static jdk.internal.net.http.common.Utils.wrapWithExtraDetail;
 
 /**
  * Encapsulates one HTTP/1.1 request/response exchange.
@@ -134,6 +134,9 @@
             subscription.request(n);
         }
 
+        /** A current-state message suitable for inclusion in an exception detail message. */
+        abstract String currentStateMessage();
+
         final boolean isSubscribed() {
             return subscription != null;
         }
@@ -159,6 +162,7 @@
                 @Override public void onNext(ByteBuffer item) { error(); }
                 @Override public void onError(Throwable throwable) { error(); }
                 @Override public void onComplete() { error(); }
+                @Override String currentStateMessage() { return null; }
                 private void error() {
                     throw new InternalError("should not reach here");
                 }
@@ -193,35 +197,6 @@
         }
         this.requestAction = new Http1Request(request, this);
         this.asyncReceiver = new Http1AsyncReceiver(executor, this);
-        asyncReceiver.subscribe(new InitialErrorReceiver());
-    }
-
-    /** An initial receiver that handles no data, but cancels the request if
-     * it receives an error. Will be replaced when reading response body. */
-    final class InitialErrorReceiver implements Http1AsyncReceiver.Http1AsyncDelegate {
-        volatile AbstractSubscription s;
-        @Override
-        public boolean tryAsyncReceive(ByteBuffer ref) {
-            return false;  // no data has been processed, leave it in the queue
-        }
-
-        @Override
-        public void onReadError(Throwable ex) {
-            cancelImpl(ex);
-        }
-
-        @Override
-        public void onSubscribe(AbstractSubscription s) {
-            this.s = s;
-        }
-
-        @Override
-        public AbstractSubscription subscription() {
-            return s;
-        }
-
-        @Override
-        public void close(Throwable error) {}
     }
 
     @Override
@@ -244,16 +219,16 @@
         // create the response before sending the request headers, so that
         // the response can set the appropriate receivers.
         if (debug.on()) debug.log("Sending headers only");
+        // If the first attempt to read something triggers EOF, or
+        // IOException("channel reset by peer"), we're going to retry.
+        // Instruct the asyncReceiver to throw ConnectionExpiredException
+        // to force a retry.
+        asyncReceiver.setRetryOnError(true);
         if (response == null) {
             response = new Http1Response<>(connection, this, asyncReceiver);
         }
 
         if (debug.on()) debug.log("response created in advance");
-        // If the first attempt to read something triggers EOF, or
-        // IOException("channel reset by peer"), we're going to retry.
-        // Instruct the asyncReceiver to throw ConnectionExpiredException
-        // to force a retry.
-        asyncReceiver.setRetryOnError(true);
 
         CompletableFuture<Void> connectCF;
         if (!connection.connected()) {
@@ -296,6 +271,8 @@
                         return cf;
                     } catch (Throwable t) {
                         if (debug.on()) debug.log("Failed to send headers: %s", t);
+                        headersSentCF.completeExceptionally(t);
+                        bodySentCF.completeExceptionally(t);
                         connection.close();
                         cf.completeExceptionally(t);
                         return cf;
@@ -303,28 +280,52 @@
                 .thenCompose(unused -> headersSentCF);
     }
 
+    private void cancelIfFailed(Flow.Subscription s) {
+        asyncReceiver.whenFinished.whenCompleteAsync((r,t) -> {
+            if (debug.on()) debug.log("asyncReceiver finished (failed=%s)", t);
+            if (t != null) {
+                s.cancel();
+                // Don't complete exceptionally here as 't'
+                // might not be the right exception: it will
+                // not have been decorated yet.
+                // t is an exception raised by the read side,
+                // an EOFException or Broken Pipe...
+                // We are cancelling the BodyPublisher subscription
+                // and completing bodySentCF to allow the next step
+                // to flow and call readHeaderAsync, which will
+                // get the right exception from the asyncReceiver.
+                bodySentCF.complete(this);
+            }
+        }, executor);
+    }
+
     @Override
     CompletableFuture<ExchangeImpl<T>> sendBodyAsync() {
         assert headersSentCF.isDone();
+        if (debug.on()) debug.log("sendBodyAsync");
         try {
             bodySubscriber = requestAction.continueRequest();
+            if (debug.on()) debug.log("bodySubscriber is %s",
+                    bodySubscriber == null ? null : bodySubscriber.getClass());
             if (bodySubscriber == null) {
                 bodySubscriber = Http1BodySubscriber.completeSubscriber(debug);
                 appendToOutgoing(Http1BodySubscriber.COMPLETED);
             } else {
                 // start
                 bodySubscriber.whenSubscribed
+                        .thenAccept((s) -> cancelIfFailed(s))
                         .thenAccept((s) -> requestMoreBody());
             }
         } catch (Throwable t) {
             cancelImpl(t);
             bodySentCF.completeExceptionally(t);
         }
-        return bodySentCF;
+        return Utils.wrapForDebug(debug, "sendBodyAsync", bodySentCF);
     }
 
     @Override
     CompletableFuture<Response> getResponseAsync(Executor executor) {
+        if (debug.on()) debug.log("reading headers");
         CompletableFuture<Response> cf = response.readHeadersAsync(executor);
         Throwable cause;
         synchronized (lock) {
@@ -348,7 +349,7 @@
                 debug.log(acknowledged ? ("completed response with " + cause)
                           : ("response already completed, ignoring " + cause));
         }
-        return cf;
+        return Utils.wrapForDebug(debug, "getResponseAsync", cf);
     }
 
     @Override
@@ -421,7 +422,6 @@
                     && response != null && response.finished()) {
                 return;
             }
-            connection.close();   // TODO: ensure non-blocking if holding the lock
             writePublisher.writeScheduler.stop();
             if (operations.isEmpty()) {
                 Log.logTrace("Http1Exchange: request [{0}/timeout={1}ms] no pending operation."
@@ -444,27 +444,31 @@
                 operations.clear();
             }
         }
-        Log.logError("Http1Exchange.cancel: count=" + count);
-        if (toComplete != null) {
-            // We might be in the selector thread in case of timeout, when
-            // the SelectorManager calls purgeTimeoutsAndReturnNextDeadline()
-            // There may or may not be other places that reach here
-            // from the SelectorManager thread, so just make sure we
-            // don't complete any CF from within the selector manager
-            // thread.
-            Executor exec = client.isSelectorThread()
-                            ? executor
-                            : this::runInline;
-            Throwable x = error;
-            while (!toComplete.isEmpty()) {
-                CompletableFuture<?> cf = toComplete.poll();
-                exec.execute(() -> {
-                    if (cf.completeExceptionally(x)) {
-                        if (debug.on())
-                            debug.log("%s: completed cf with %s", request.uri(), x);
-                    }
-                });
+        try {
+            Log.logError("Http1Exchange.cancel: count=" + count);
+            if (toComplete != null) {
+                // We might be in the selector thread in case of timeout, when
+                // the SelectorManager calls purgeTimeoutsAndReturnNextDeadline()
+                // There may or may not be other places that reach here
+                // from the SelectorManager thread, so just make sure we
+                // don't complete any CF from within the selector manager
+                // thread.
+                Executor exec = client.isSelectorThread()
+                        ? executor
+                        : this::runInline;
+                Throwable x = error;
+                while (!toComplete.isEmpty()) {
+                    CompletableFuture<?> cf = toComplete.poll();
+                    exec.execute(() -> {
+                        if (cf.completeExceptionally(x)) {
+                            if (debug.on())
+                                debug.log("%s: completed cf with %s", request.uri(), x);
+                        }
+                    });
+                }
             }
+        } finally {
+            connection.close();
         }
     }
 
@@ -511,7 +515,7 @@
 
     private void requestMoreBody() {
         try {
-            if (debug.on()) debug.log("requesting more body from the subscriber");
+            if (debug.on()) debug.log("requesting more request body from the subscriber");
             bodySubscriber.request(1);
         } catch (Throwable t) {
             if (debug.on()) debug.log("Subscription::request failed", t);
@@ -527,46 +531,62 @@
         final Executor exec = client.theExecutor();
         final DataPair dp = outgoing.pollFirst();
 
+        if (writePublisher.cancelled) {
+            if (debug.on()) debug.log("cancelling upstream publisher");
+            if (bodySubscriber != null) {
+                exec.execute(bodySubscriber::cancelSubscription);
+            } else if (debug.on()) {
+                debug.log("bodySubscriber is null");
+            }
+            headersSentCF.completeAsync(() -> this, exec);
+            bodySentCF.completeAsync(() -> this, exec);
+            return null;
+        }
+
         if (dp == null)  // publisher has not published anything yet
             return null;
 
-        synchronized (lock) {
-            if (dp.throwable != null) {
+        if (dp.throwable != null) {
+            synchronized (lock) {
                 state = State.ERROR;
-                exec.execute(() -> {
-                    headersSentCF.completeExceptionally(dp.throwable);
-                    bodySentCF.completeExceptionally(dp.throwable);
-                    connection.close();
-                });
-                return dp;
             }
-
-            switch (state) {
-                case HEADERS:
-                    state = State.BODY;
-                    // completeAsync, since dependent tasks should run in another thread
-                    if (debug.on()) debug.log("initiating completion of headersSentCF");
-                    headersSentCF.completeAsync(() -> this, exec);
-                    break;
-                case BODY:
-                    if (dp.data == Http1BodySubscriber.COMPLETED) {
-                        state = State.COMPLETING;
-                        if (debug.on()) debug.log("initiating completion of bodySentCF");
-                        bodySentCF.completeAsync(() -> this, exec);
-                    } else {
-                        exec.execute(this::requestMoreBody);
-                    }
-                    break;
-                case INITIAL:
-                case ERROR:
-                case COMPLETING:
-                case COMPLETED:
-                default:
-                    assert false : "Unexpected state:" + state;
-            }
-
+            exec.execute(() -> {
+                headersSentCF.completeExceptionally(dp.throwable);
+                bodySentCF.completeExceptionally(dp.throwable);
+                connection.close();
+            });
             return dp;
         }
+
+        switch (state) {
+            case HEADERS:
+                synchronized (lock) {
+                    state = State.BODY;
+                }
+                // completeAsync, since dependent tasks should run in another thread
+                if (debug.on()) debug.log("initiating completion of headersSentCF");
+                headersSentCF.completeAsync(() -> this, exec);
+                break;
+            case BODY:
+                if (dp.data == Http1BodySubscriber.COMPLETED) {
+                    synchronized (lock) {
+                        state = State.COMPLETING;
+                    }
+                    if (debug.on()) debug.log("initiating completion of bodySentCF");
+                    bodySentCF.completeAsync(() -> this, exec);
+                } else {
+                    exec.execute(this::requestMoreBody);
+                }
+                break;
+            case INITIAL:
+            case ERROR:
+            case COMPLETING:
+            case COMPLETED:
+            default:
+                assert false : "Unexpected state:" + state;
+        }
+
+        return dp;
     }
 
     /** A Publisher of HTTP/1.1 headers and request body. */
@@ -608,6 +628,14 @@
             public void run() {
                 assert state != State.COMPLETED : "Unexpected state:" + state;
                 if (debug.on()) debug.log("WriteTask");
+
+                if (cancelled) {
+                    if (debug.on()) debug.log("handling cancellation");
+                    writeScheduler.stop();
+                    getOutgoing();
+                    return;
+                }
+
                 if (subscriber == null) {
                     if (debug.on()) debug.log("no subscriber yet");
                     return;
@@ -615,6 +643,8 @@
                 if (debug.on()) debug.log(() -> "hasOutgoing = " + hasOutgoing());
                 while (hasOutgoing() && demand.tryDecrement()) {
                     DataPair dp = getOutgoing();
+                    if (dp == null)
+                        break;
 
                     if (dp.throwable != null) {
                         if (debug.on()) debug.log("onError");
@@ -661,7 +691,7 @@
                 if (cancelled)
                     return;  //no-op
                 cancelled = true;
-                writeScheduler.stop();
+                writeScheduler.runOrSchedule(client.theExecutor());
             }
         }
     }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1HeaderParser.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1HeaderParser.java	Thu Jun 21 09:53:50 2018 -0700
@@ -35,6 +35,7 @@
 import java.net.http.HttpHeaders;
 import static java.lang.String.format;
 import static java.util.Objects.requireNonNull;
+import static jdk.internal.net.http.common.Utils.ACCEPT_ALL;
 
 class Http1HeaderParser {
 
@@ -49,10 +50,13 @@
     private HttpHeaders headers;
     private Map<String,List<String>> privateMap = new HashMap<>();
 
-    enum State { STATUS_LINE,
+    enum State { INITIAL,
+                 STATUS_LINE,
                  STATUS_LINE_FOUND_CR,
+                 STATUS_LINE_FOUND_LF,
                  STATUS_LINE_END,
                  STATUS_LINE_END_CR,
+                 STATUS_LINE_END_LF,
                  HEADER,
                  HEADER_FOUND_CR,
                  HEADER_FOUND_LF,
@@ -60,7 +64,7 @@
                  HEADER_FOUND_CR_LF_CR,
                  FINISHED }
 
-    private State state = State.STATUS_LINE;
+    private State state = State.INITIAL;
 
     /** Returns the status-line. */
     String statusLine() { return statusLine; }
@@ -69,7 +73,29 @@
     int responseCode() { return responseCode; }
 
     /** Returns the headers, possibly empty. */
-    HttpHeaders headers() { assert state == State.FINISHED; return headers; }
+    HttpHeaders headers() {
+        assert state == State.FINISHED : "Unexpected state " + state;
+        return headers;
+    }
+
+    /** A current-state message suitable for inclusion in an exception detail message. */
+    public String currentStateMessage() {
+        String stateName = state.name();
+        String msg;
+        if (stateName.contains("INITIAL")) {
+            return format("HTTP/1.1 header parser received no bytes");
+        } else if (stateName.contains("STATUS")) {
+            msg = format("parsing HTTP/1.1 status line, receiving [%s]", sb.toString());
+        } else if (stateName.contains("HEADER")) {
+            String headerName = sb.toString();
+            if (headerName.indexOf(':') != -1)
+                headerName = headerName.substring(0, headerName.indexOf(':')+1) + "...";
+            msg = format("parsing HTTP/1.1 header, receiving [%s]", headerName);
+        } else {
+            msg =format("HTTP/1.1 parser receiving [%s]", state, sb.toString());
+        }
+        return format("%s, parser state [%s]", msg , state);
+    }
 
     /**
      * Parses HTTP/1.X status-line and headers from the given bytes. Must be
@@ -84,18 +110,25 @@
     boolean parse(ByteBuffer input) throws ProtocolException {
         requireNonNull(input, "null input");
 
-        while (input.hasRemaining() && state != State.FINISHED) {
+        while (canContinueParsing(input)) {
             switch (state) {
+                case INITIAL:
+                    state = State.STATUS_LINE;
+                    break;
                 case STATUS_LINE:
                     readResumeStatusLine(input);
                     break;
+                // fallthrough
                 case STATUS_LINE_FOUND_CR:
+                case STATUS_LINE_FOUND_LF:
                     readStatusLineFeed(input);
                     break;
                 case STATUS_LINE_END:
                     maybeStartHeaders(input);
                     break;
+                // fallthrough
                 case STATUS_LINE_END_CR:
+                case STATUS_LINE_END_LF:
                     maybeEndHeaders(input);
                     break;
                 case HEADER:
@@ -121,21 +154,35 @@
         return state == State.FINISHED;
     }
 
+    private boolean canContinueParsing(ByteBuffer buffer) {
+        // some states don't require any input to transition
+        // to the next state.
+        switch (state) {
+            case FINISHED: return false;
+            case STATUS_LINE_FOUND_LF: return true;
+            case STATUS_LINE_END_LF: return true;
+            case HEADER_FOUND_LF: return true;
+            default: return buffer.hasRemaining();
+        }
+    }
+
     private void readResumeStatusLine(ByteBuffer input) {
         char c = 0;
         while (input.hasRemaining() && (c =(char)input.get()) != CR) {
+            if (c == LF) break;
             sb.append(c);
         }
-
         if (c == CR) {
             state = State.STATUS_LINE_FOUND_CR;
+        } else if (c == LF) {
+            state = State.STATUS_LINE_FOUND_LF;
         }
     }
 
     private void readStatusLineFeed(ByteBuffer input) throws ProtocolException {
-        char c = (char)input.get();
+        char c = state == State.STATUS_LINE_FOUND_LF ? LF : (char)input.get();
         if (c != LF) {
-            throw protocolException("Bad trailing char, \"%s\", when parsing status-line, \"%s\"",
+            throw protocolException("Bad trailing char, \"%s\", when parsing status line, \"%s\"",
                                     c, sb.toString());
         }
 
@@ -158,6 +205,8 @@
         char c = (char)input.get();
         if (c == CR) {
             state = State.STATUS_LINE_END_CR;
+        } else if (c == LF) {
+            state = State.STATUS_LINE_END_LF;
         } else {
             sb.append(c);
             state = State.HEADER;
@@ -165,15 +214,15 @@
     }
 
     private void maybeEndHeaders(ByteBuffer input) throws ProtocolException {
-        assert state == State.STATUS_LINE_END_CR;
+        assert state == State.STATUS_LINE_END_CR || state == State.STATUS_LINE_END_LF;
         assert sb.length() == 0;
-        char c = (char)input.get();
+        char c = state == State.STATUS_LINE_END_LF ? LF : (char)input.get();
         if (c == LF) {
-            headers = ImmutableHeaders.of(privateMap);
+            headers = HttpHeaders.of(privateMap, ACCEPT_ALL);
             privateMap = null;
             state = State.FINISHED;  // no headers
         } else {
-            throw protocolException("Unexpected \"%s\", after status-line CR", c);
+            throw protocolException("Unexpected \"%s\", after status line CR", c);
         }
     }
 
@@ -212,8 +261,8 @@
 
     private void resumeOrLF(ByteBuffer input) {
         assert state == State.HEADER_FOUND_CR || state == State.HEADER_FOUND_LF;
-        char c = (char)input.get();
-        if (c == LF && state == State.HEADER_FOUND_CR) {
+        char c = state == State.HEADER_FOUND_LF ? LF : (char)input.get();
+        if (c == LF) {
             // header value will be flushed by
             // resumeOrSecondCR if next line does not
             // begin by SP or HT
@@ -231,7 +280,7 @@
     private void resumeOrSecondCR(ByteBuffer input) {
         assert state == State.HEADER_FOUND_CR_LF;
         char c = (char)input.get();
-        if (c == CR) {
+        if (c == CR || c == LF) {
             if (sb.length() > 0) {
                 // no continuation line - flush
                 // previous header value.
@@ -239,7 +288,13 @@
                 sb = new StringBuilder();
                 addHeaderFromString(headerString);
             }
-            state = State.HEADER_FOUND_CR_LF_CR;
+            if (c == CR) {
+                state = State.HEADER_FOUND_CR_LF_CR;
+            } else {
+                state = State.FINISHED;
+                headers = HttpHeaders.of(privateMap, ACCEPT_ALL);
+                privateMap = null;
+            }
         } else if (c == SP || c == HT) {
             assert sb.length() != 0;
             sb.append(SP); // continuation line
@@ -262,7 +317,7 @@
         char c = (char)input.get();
         if (c == LF) {
             state = State.FINISHED;
-            headers = ImmutableHeaders.of(privateMap);
+            headers = HttpHeaders.of(privateMap, ACCEPT_ALL);
             privateMap = null;
         } else {
             throw protocolException("Unexpected \"%s\", after CR LF CR", c);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,7 +26,6 @@
 package jdk.internal.net.http;
 
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -39,11 +38,12 @@
 import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
 import jdk.internal.net.http.Http1Exchange.Http1BodySubscriber;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Log;
 import jdk.internal.net.http.common.Logger;
 import jdk.internal.net.http.common.Utils;
 
+import static java.lang.String.format;
 import static java.nio.charset.StandardCharsets.US_ASCII;
 
 /**
@@ -52,7 +52,7 @@
 class Http1Request {
 
     private static final String COOKIE_HEADER = "Cookie";
-    private static final BiPredicate<String,List<String>> NOCOOKIES =
+    private static final BiPredicate<String,String> NOCOOKIES =
             (k,v) -> !COOKIE_HEADER.equalsIgnoreCase(k);
 
     private final HttpRequestImpl request;
@@ -60,7 +60,7 @@
     private final HttpConnection connection;
     private final HttpRequest.BodyPublisher requestPublisher;
     private final HttpHeaders userHeaders;
-    private final HttpHeadersImpl systemHeaders;
+    private final HttpHeadersBuilder systemHeadersBuilder;
     private volatile boolean streaming;
     private volatile long contentLength;
 
@@ -73,7 +73,7 @@
         this.connection = http1Exchange.connection();
         this.requestPublisher = request.requestPublisher;  // may be null
         this.userHeaders = request.getUserHeaders();
-        this.systemHeaders = request.getSystemHeaders();
+        this.systemHeadersBuilder = request.getSystemHeadersBuilder();
     }
 
     private void logHeaders(String completeHeaders) {
@@ -92,12 +92,13 @@
 
 
     private void collectHeaders0(StringBuilder sb) {
-        BiPredicate<String,List<String>> filter =
+        BiPredicate<String,String> filter =
                 connection.headerFilter(request);
 
         // Filter out 'Cookie:' headers, we will collect them at the end.
-        BiPredicate<String,List<String>> nocookies =
-                NOCOOKIES.and(filter);
+        BiPredicate<String,String> nocookies = NOCOOKIES.and(filter);
+
+        HttpHeaders systemHeaders = systemHeadersBuilder.build();
 
         // If we're sending this request through a tunnel,
         // then don't send any preemptive proxy-* headers that
@@ -112,8 +113,7 @@
 
         // Gather all 'Cookie:' headers and concatenate their
         // values in a single line.
-        collectCookies(sb, COOKIE_HEADER,
-                systemHeaders, userHeaders, filter);
+        collectCookies(sb, systemHeaders, userHeaders);
 
         // terminate headers
         sb.append('\r').append('\n');
@@ -142,20 +142,16 @@
     // any illegal character for header field values.
     //
     private void collectCookies(StringBuilder sb,
-                                String key,
                                 HttpHeaders system,
-                                HttpHeaders user,
-                                BiPredicate<String, List<String>> filter) {
-        List<String> systemList = system.allValues(key);
-        if (systemList != null && !filter.test(key, systemList)) systemList = null;
-        List<String> userList = user.allValues(key);
-        if (userList != null && !filter.test(key, userList)) userList = null;
+                                HttpHeaders user) {
+        List<String> systemList = system.allValues(COOKIE_HEADER);
+        List<String> userList = user.allValues(COOKIE_HEADER);
         boolean found = false;
         if (systemList != null) {
             for (String cookie : systemList) {
                 if (!found) {
                     found = true;
-                    sb.append(key).append(':').append(' ');
+                    sb.append(COOKIE_HEADER).append(':').append(' ');
                 } else {
                     sb.append(';').append(' ');
                 }
@@ -166,7 +162,7 @@
             for (String cookie : userList) {
                 if (!found) {
                     found = true;
-                    sb.append(key).append(':').append(' ');
+                    sb.append(COOKIE_HEADER).append(':').append(' ');
                 } else {
                     sb.append(';').append(' ');
                 }
@@ -176,13 +172,15 @@
         if (found) sb.append('\r').append('\n');
     }
 
-    private void collectHeaders1(StringBuilder sb, HttpHeaders headers,
-                                 BiPredicate<String, List<String>> filter) {
+    private void collectHeaders1(StringBuilder sb,
+                                 HttpHeaders headers,
+                                 BiPredicate<String,String> filter) {
         for (Map.Entry<String,List<String>> entry : headers.map().entrySet()) {
             String key = entry.getKey();
             List<String> values = entry.getValue();
-            if (!filter.test(key, values)) continue;
             for (String value : values) {
+                if (!filter.test(key, value))
+                    continue;
                 sb.append(key).append(':').append(' ')
                         .append(value)
                         .append('\r').append('\n');
@@ -279,7 +277,7 @@
 
         URI uri = request.uri();
         if (uri != null) {
-            systemHeaders.setHeader("Host", hostString());
+            systemHeadersBuilder.setHeader("Host", hostString());
         }
         if (requestPublisher == null) {
             // Not a user request, or maybe a method, e.g. GET, with no body.
@@ -289,13 +287,13 @@
         }
 
         if (contentLength == 0) {
-            systemHeaders.setHeader("Content-Length", "0");
+            systemHeadersBuilder.setHeader("Content-Length", "0");
         } else if (contentLength > 0) {
-            systemHeaders.setHeader("Content-Length", Long.toString(contentLength));
+            systemHeadersBuilder.setHeader("Content-Length", Long.toString(contentLength));
             streaming = false;
         } else {
             streaming = true;
-            systemHeaders.setHeader("Transfer-encoding", "chunked");
+            systemHeadersBuilder.setHeader("Transfer-encoding", "chunked");
         }
         collectHeaders0(sb);
         String hs = sb.toString();
@@ -350,6 +348,11 @@
         }
 
         @Override
+        public String currentStateMessage() {
+            return "streaming request body " + (complete ? "complete" : "incomplete");
+        }
+
+        @Override
         public void onError(Throwable throwable) {
             if (complete)
                 return;
@@ -417,6 +420,12 @@
         }
 
         @Override
+        public String currentStateMessage() {
+            return format("fixed content-length: %d, bytes sent: %d",
+                           contentLength, contentWritten);
+        }
+
+        @Override
         public void onError(Throwable throwable) {
             if (debug.on()) debug.log("onError");
             if (complete)  // TODO: error?
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java	Thu Jun 21 09:53:50 2018 -0700
@@ -44,9 +44,10 @@
 import jdk.internal.net.http.common.Logger;
 import jdk.internal.net.http.common.MinimalFuture;
 import jdk.internal.net.http.common.Utils;
-
 import static java.net.http.HttpClient.Version.HTTP_1_1;
 import static java.net.http.HttpResponse.BodySubscribers.discarding;
+import static jdk.internal.net.http.common.Utils.wrapWithExtraDetail;
+import static jdk.internal.net.http.RedirectFilter.HTTP_NOT_MODIFIED;
 
 /**
  * Handles a HTTP/1.1 response (headers + body).
@@ -76,6 +77,7 @@
     final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
     final static AtomicLong responseCount = new AtomicLong();
     final long id = responseCount.incrementAndGet();
+    private Http1HeaderParser hd;
 
     Http1Response(HttpConnection conn,
                   Http1Exchange<T> exchange,
@@ -87,6 +89,11 @@
         this.asyncReceiver = asyncReceiver;
         headersReader = new HeadersReader(this::advance);
         bodyReader = new BodyReader(this::advance);
+
+        hd = new Http1HeaderParser();
+        readProgress = State.READING_HEADERS;
+        headersReader.start(hd);
+        asyncReceiver.subscribe(headersReader);
     }
 
     String dbgTag;
@@ -150,19 +157,36 @@
         }
     }
 
+    private volatile boolean firstTimeAround = true;
+
     public CompletableFuture<Response> readHeadersAsync(Executor executor) {
         if (debug.on())
             debug.log("Reading Headers: (remaining: "
                       + asyncReceiver.remaining() +") "  + readProgress);
-        // with expect continue we will resume reading headers + body.
-        asyncReceiver.unsubscribe(bodyReader);
-        bodyReader.reset();
-        Http1HeaderParser hd = new Http1HeaderParser();
-        readProgress = State.READING_HEADERS;
-        headersReader.start(hd);
-        asyncReceiver.subscribe(headersReader);
+
+        if (firstTimeAround) {
+            if (debug.on()) debug.log("First time around");
+            firstTimeAround = false;
+        } else {
+            // with expect continue we will resume reading headers + body.
+            asyncReceiver.unsubscribe(bodyReader);
+            bodyReader.reset();
+
+            hd = new Http1HeaderParser();
+            readProgress = State.READING_HEADERS;
+            headersReader.reset();
+            headersReader.start(hd);
+            asyncReceiver.subscribe(headersReader);
+        }
+
         CompletableFuture<State> cf = headersReader.completion();
         assert cf != null : "parsing not started";
+        if (debug.on()) {
+            debug.log("headersReader is %s",
+                    cf == null ? "not yet started"
+                            : cf.isDone() ? "already completed"
+                            : "not yet completed");
+        }
 
         Function<State, Response> lambda = (State completed) -> {
                 assert completed == State.READING_HEADERS;
@@ -207,7 +231,7 @@
     }
 
     int fixupContentLen(int clen) {
-        if (request.method().equalsIgnoreCase("HEAD")) {
+        if (request.method().equalsIgnoreCase("HEAD") || responseCode == HTTP_NOT_MODIFIED) {
             return 0;
         }
         if (clen == -1) {
@@ -289,13 +313,19 @@
                     try {
                         userSubscriber.onComplete();
                     } catch (Throwable x) {
-                        propagateError(t = withError = Utils.getCompletionCause(x));
-                        // rethrow and let the caller deal with it.
+                        // Simply propagate the error by calling
+                        // onError on the user subscriber, and let the
+                        // connection be reused since we should have received
+                        // and parsed all the bytes when we reach here.
+                        // If onError throws in turn, then we will simply
+                        // let that new exception flow up to the caller
+                        // and let it deal with it.
                         // (i.e: log and close the connection)
-                        // arguably we could decide to not throw and let the
-                        // connection be reused since we should have received and
-                        // parsed all the bytes when we reach here.
-                        throw x;
+                        // Note that rethrowing here could introduce a
+                        // race that might cause the next send() operation to
+                        // fail as the connection has already been put back
+                        // into the cache when we reach here.
+                        propagateError(t = withError = Utils.getCompletionCause(x));
                     }
                 } else {
                     propagateError(t);
@@ -613,6 +643,7 @@
 
         @Override
         public final void onReadError(Throwable t) {
+            t = wrapWithExtraDetail(t, parser::currentStateMessage);
             Http1Response.this.onReadError(t);
         }
 
@@ -692,6 +723,7 @@
 
         @Override
         public final void onReadError(Throwable t) {
+            t = wrapWithExtraDetail(t, parser::currentStateMessage);
             Http1Response.this.onReadError(t);
         }
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,6 +25,9 @@
 
 package jdk.internal.net.http;
 
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.ConnectException;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.util.Base64;
@@ -95,15 +98,20 @@
         synchronized (this) {
             Http2Connection connection = connections.get(key);
             if (connection != null) {
-                if (connection.closed || !connection.reserveStream(true)) {
-                    if (debug.on())
-                        debug.log("removing found closed or closing connection: %s", connection);
-                    deleteConnection(connection);
-                } else {
-                    // fast path if connection already exists
-                    if (debug.on())
-                        debug.log("found connection in the pool: %s", connection);
-                    return MinimalFuture.completedFuture(connection);
+                try {
+                    if (connection.closed || !connection.reserveStream(true)) {
+                        if (debug.on())
+                            debug.log("removing found closed or closing connection: %s", connection);
+                        deleteConnection(connection);
+                    } else {
+                        // fast path if connection already exists
+                        if (debug.on())
+                            debug.log("found connection in the pool: %s", connection);
+                        return MinimalFuture.completedFuture(connection);
+                    }
+                } catch (IOException e) {
+                    // thrown by connection.reserveStream()
+                    return MinimalFuture.failedFuture(e);
                 }
             }
 
@@ -119,6 +127,11 @@
                 .whenComplete((conn, t) -> {
                     synchronized (Http2ClientImpl.this) {
                         if (conn != null) {
+                            try {
+                                conn.reserveStream(true);
+                            } catch (IOException e) {
+                                throw new UncheckedIOException(e); // shouldn't happen
+                            }
                             offerConnection(conn);
                         } else {
                             Throwable cause = Utils.getCompletionCause(t);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java	Thu Jun 21 09:53:50 2018 -0700
@@ -28,7 +28,6 @@
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.lang.System.Logger.Level;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.nio.ByteBuffer;
@@ -54,7 +53,7 @@
 import jdk.internal.net.http.HttpConnection.HttpPublisher;
 import jdk.internal.net.http.common.FlowTube;
 import jdk.internal.net.http.common.FlowTube.TubeSubscriber;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Log;
 import jdk.internal.net.http.common.Logger;
 import jdk.internal.net.http.common.MinimalFuture;
@@ -82,7 +81,6 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static jdk.internal.net.http.frame.SettingsFrame.*;
 
-
 /**
  * An Http2Connection. Encapsulates the socket(channel) and any SSLEngine used
  * over it. Contains an HttpConnection which hides the SocketChannel SSL stuff.
@@ -259,6 +257,8 @@
     // assigning a stream to a connection.
     private int lastReservedClientStreamid = 1;
     private int lastReservedServerStreamid = 0;
+    private int numReservedClientStreams = 0; // count of current streams
+    private int numReservedServerStreams = 0; // count of current streams
     private final Encoder hpackOut;
     private final Decoder hpackIn;
     final SettingsFrame clientSettings;
@@ -273,7 +273,7 @@
      */
     private final WindowController windowController = new WindowController();
     private final FramesController framesController = new FramesController();
-    private final Http2TubeSubscriber subscriber = new Http2TubeSubscriber();
+    private final Http2TubeSubscriber subscriber;
     final ConnectionWindowUpdateSender windowUpdater;
     private volatile Throwable cause;
     private volatile Supplier<ByteBuffer> initial;
@@ -290,6 +290,7 @@
                             String key) {
         this.connection = connection;
         this.client2 = client2;
+        this.subscriber = new Http2TubeSubscriber(client2.client());
         this.nextstreamid = nextstreamid;
         this.key = key;
         this.clientSettings = this.client2.getClientSettings();
@@ -310,7 +311,7 @@
 
     /**
      * Case 1) Create from upgraded HTTP/1.1 connection.
-     * Is ready to use. Can be SSL. exchange is the Exchange
+     * Is ready to use. Can't be SSL. exchange is the Exchange
      * that initiated the connection, whose response will be delivered
      * on a Stream.
      */
@@ -324,6 +325,7 @@
                 client2,
                 3, // stream 1 is registered during the upgrade
                 keyFor(connection));
+        reserveStream(true);
         Log.logTrace("Connection send window size {0} ", windowController.connectionWindowSize());
 
         Stream<?> initialStream = createStream(exchange);
@@ -407,7 +409,8 @@
     // call these before assigning a request/stream to a connection
     // if false returned then a new Http2Connection is required
     // if true, the the stream may be assigned to this connection
-    synchronized boolean reserveStream(boolean clientInitiated) {
+    // for server push, if false returned, then the stream should be cancelled
+    synchronized boolean reserveStream(boolean clientInitiated) throws IOException {
         if (finalStream) {
             return false;
         }
@@ -424,6 +427,19 @@
             lastReservedClientStreamid+=2;
         else
             lastReservedServerStreamid+=2;
+
+        assert numReservedClientStreams >= 0;
+        assert numReservedServerStreams >= 0;
+        if (clientInitiated && numReservedClientStreams >= getMaxConcurrentClientStreams()) {
+            throw new IOException("too many concurrent streams");
+        } else if (clientInitiated) {
+            numReservedClientStreams++;
+        }
+        if (!clientInitiated && numReservedServerStreams >= getMaxConcurrentServerStreams()) {
+            return false;
+        } else if (!clientInitiated) {
+            numReservedServerStreams++;
+        }
         return true;
     }
 
@@ -564,6 +580,14 @@
         return serverSettings.getParameter(INITIAL_WINDOW_SIZE);
     }
 
+    final int getMaxConcurrentClientStreams() {
+        return serverSettings.getParameter(MAX_CONCURRENT_STREAMS);
+    }
+
+    final int getMaxConcurrentServerStreams() {
+        return clientSettings.getParameter(MAX_CONCURRENT_STREAMS);
+    }
+
     void close() {
         Log.logTrace("Closing HTTP/2 connection: to {0}", connection.address());
         GoAwayFrame f = new GoAwayFrame(0,
@@ -637,13 +661,19 @@
             if (closed == true) return;
             closed = true;
         }
-        Log.logError(t);
+        if (Log.errors()) {
+            if (!(t instanceof EOFException) || isActive()) {
+                Log.logError(t);
+            } else if (t != null) {
+                Log.logError("Shutting down connection: {0}", t.getMessage());
+            }
+        }
         Throwable initialCause = this.cause;
         if (initialCause == null) this.cause = t;
         client2.deleteConnection(this);
         List<Stream<?>> c = new LinkedList<>(streams.values());
         for (Stream<?> s : c) {
-            s.cancelImpl(t);
+            s.connectionClosing(t);
         }
         connection.close();
     }
@@ -766,7 +796,7 @@
             nextPushStream += 2;
         }
 
-        HttpHeadersImpl headers = decoder.headers();
+        HttpHeaders headers = decoder.headers();
         HttpRequestImpl pushReq = HttpRequestImpl.createPushRequest(parentReq, headers);
         Exchange<T> pushExch = new Exchange<>(pushReq, parent.exchange.multi);
         Stream.PushedStream<T> pushStream = createPushStream(parent, pushExch);
@@ -797,16 +827,44 @@
     }
 
     void resetStream(int streamid, int code) throws IOException {
-        Log.logError(
-            "Resetting stream {0,number,integer} with error code {1,number,integer}",
-            streamid, code);
-        ResetFrame frame = new ResetFrame(streamid, code);
-        sendFrame(frame);
-        closeStream(streamid);
+        try {
+            if (connection.channel().isOpen()) {
+                // no need to try & send a reset frame if the
+                // connection channel is already closed.
+                Log.logError(
+                        "Resetting stream {0,number,integer} with error code {1,number,integer}",
+                        streamid, code);
+                ResetFrame frame = new ResetFrame(streamid, code);
+                sendFrame(frame);
+            } else if (debug.on()) {
+                debug.log("Channel already closed, no need to reset stream %d",
+                          streamid);
+            }
+        } finally {
+            decrementStreamsCount(streamid);
+            closeStream(streamid);
+        }
+    }
+
+    // reduce count of streams by 1 if stream still exists
+    synchronized void decrementStreamsCount(int streamid) {
+        Stream<?> s = streams.get(streamid);
+        if (s == null || !s.deRegister())
+            return;
+        if (streamid % 2 == 1) {
+            numReservedClientStreams--;
+            assert numReservedClientStreams >= 0 :
+                    "negative client stream count for stream=" + streamid;
+        } else {
+            numReservedServerStreams--;
+            assert numReservedServerStreams >= 0 :
+                    "negative server stream count for stream=" + streamid;
+        }
     }
 
     void closeStream(int streamid) {
         if (debug.on()) debug.log("Closed stream %d", streamid);
+        boolean isClient = (streamid % 2) == 1;
         Stream<?> s = streams.remove(streamid);
         if (s != null) {
             // decrement the reference count on the HttpClientImpl
@@ -1148,14 +1206,19 @@
      * A simple tube subscriber for reading from the connection flow.
      */
     final class Http2TubeSubscriber implements TubeSubscriber {
-        volatile Flow.Subscription subscription;
-        volatile boolean completed;
-        volatile boolean dropped;
-        volatile Throwable error;
-        final ConcurrentLinkedQueue<ByteBuffer> queue
+        private volatile Flow.Subscription subscription;
+        private volatile boolean completed;
+        private volatile boolean dropped;
+        private volatile Throwable error;
+        private final ConcurrentLinkedQueue<ByteBuffer> queue
                 = new ConcurrentLinkedQueue<>();
-        final SequentialScheduler scheduler =
+        private final SequentialScheduler scheduler =
                 SequentialScheduler.synchronizedScheduler(this::processQueue);
+        private final HttpClientImpl client;
+
+        Http2TubeSubscriber(HttpClientImpl client) {
+            this.client = Objects.requireNonNull(client);
+        }
 
         final void processQueue() {
             try {
@@ -1179,6 +1242,12 @@
             }
         }
 
+        private final void runOrSchedule() {
+            if (client.isSelectorThread()) {
+                scheduler.runOrSchedule(client.theExecutor());
+            } else scheduler.runOrSchedule();
+        }
+
         @Override
         public void onSubscribe(Flow.Subscription subscription) {
             // supports being called multiple time.
@@ -1202,7 +1271,7 @@
             if (debug.on()) debug.log(() -> "onNext: got " + Utils.remaining(item)
                     + " bytes in " + item.size() + " buffers");
             queue.addAll(item);
-            scheduler.runOrSchedule(client().theExecutor());
+            runOrSchedule();
         }
 
         @Override
@@ -1210,15 +1279,18 @@
             if (debug.on()) debug.log(() -> "onError: " + throwable);
             error = throwable;
             completed = true;
-            scheduler.runOrSchedule(client().theExecutor());
+            runOrSchedule();
         }
 
         @Override
         public void onComplete() {
-            if (debug.on()) debug.log("EOF");
-            error = new EOFException("EOF reached while reading");
+            String msg = isActive()
+                    ? "EOF reached while reading"
+                    : "Idle connection closed by HTTP/2 peer";
+            if (debug.on()) debug.log(msg);
+            error = new EOFException(msg);
             completed = true;
-            scheduler.runOrSchedule(client().theExecutor());
+            runOrSchedule();
         }
 
         @Override
@@ -1230,6 +1302,10 @@
         }
     }
 
+    synchronized boolean isActive() {
+        return numReservedClientStreams > 0 || numReservedServerStreams > 0;
+    }
+
     @Override
     public final String toString() {
         return dbgString();
@@ -1242,10 +1318,10 @@
 
     static class HeaderDecoder extends ValidatingHeadersConsumer {
 
-        HttpHeadersImpl headers;
+        HttpHeadersBuilder headersBuilder;
 
         HeaderDecoder() {
-            this.headers = new HttpHeadersImpl();
+            this.headersBuilder = new HttpHeadersBuilder();
         }
 
         @Override
@@ -1253,11 +1329,11 @@
             String n = name.toString();
             String v = value.toString();
             super.onDecoded(n, v);
-            headers.addHeader(n, v);
+            headersBuilder.addHeader(n, v);
         }
 
-        HttpHeadersImpl headers() {
-            return headers;
+        HttpHeaders headers() {
+            return headersBuilder.build();
         }
     }
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -28,11 +28,14 @@
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLParameters;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.net.Authenticator;
+import java.net.ConnectException;
 import java.net.CookieHandler;
 import java.net.ProxySelector;
+import java.net.http.HttpTimeoutException;
 import java.nio.ByteBuffer;
 import java.nio.channels.CancelledKeyException;
 import java.nio.channels.ClosedChannelException;
@@ -56,13 +59,14 @@
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CompletionException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BooleanSupplier;
 import java.util.stream.Stream;
 import java.net.http.HttpClient;
 import java.net.http.HttpRequest;
@@ -121,6 +125,34 @@
         }
     }
 
+    /**
+     * A DelegatingExecutor is an executor that delegates tasks to
+     * a wrapped executor when it detects that the current thread
+     * is the SelectorManager thread. If the current thread is not
+     * the selector manager thread the given task is executed inline.
+     */
+    final static class DelegatingExecutor implements Executor {
+        private final BooleanSupplier isInSelectorThread;
+        private final Executor delegate;
+        DelegatingExecutor(BooleanSupplier isInSelectorThread, Executor delegate) {
+            this.isInSelectorThread = isInSelectorThread;
+            this.delegate = delegate;
+        }
+
+        Executor delegate() {
+            return delegate;
+        }
+
+        @Override
+        public void execute(Runnable command) {
+            if (isInSelectorThread.getAsBoolean()) {
+                delegate.execute(command);
+            } else {
+                command.run();
+            }
+        }
+    }
+
     private final CookieHandler cookieHandler;
     private final Redirect followRedirects;
     private final Optional<ProxySelector> userProxySelector;
@@ -128,7 +160,7 @@
     private final Authenticator authenticator;
     private final Version version;
     private final ConnectionPool connections;
-    private final Executor executor;
+    private final DelegatingExecutor delegatingExecutor;
     private final boolean isDefaultExecutor;
     // Security parameters
     private final SSLContext sslContext;
@@ -240,12 +272,11 @@
             ex = Executors.newCachedThreadPool(new DefaultThreadFactory(id));
             isDefaultExecutor = true;
         } else {
-            ex = builder.executor;
             isDefaultExecutor = false;
         }
+        delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex);
         facadeRef = new WeakReference<>(facadeFactory.createFacade(this));
         client2 = new Http2ClientImpl(this);
-        executor = ex;
         cookieHandler = builder.cookieHandler;
         followRedirects = builder.followRedirects == null ?
                 Redirect.NEVER : builder.followRedirects;
@@ -489,21 +520,38 @@
     send(HttpRequest req, BodyHandler<T> responseHandler)
         throws IOException, InterruptedException
     {
+        CompletableFuture<HttpResponse<T>> cf = null;
         try {
-            return sendAsync(req, responseHandler, null).get();
+            cf = sendAsync(req, responseHandler, null, null);
+            return cf.get();
+        } catch (InterruptedException ie) {
+            if (cf != null )
+                cf.cancel(true);
+            throw ie;
         } catch (ExecutionException e) {
-            Throwable t = e.getCause();
-            if (t instanceof Error)
-                throw (Error)t;
-            if (t instanceof RuntimeException)
-                throw (RuntimeException)t;
-            else if (t instanceof IOException)
-                throw Utils.getIOException(t);
-            else
-                throw new InternalError("Unexpected exception", t);
+            final Throwable throwable = e.getCause();
+            final String msg = throwable.getMessage();
+
+            if (throwable instanceof IllegalArgumentException) {
+                throw new IllegalArgumentException(msg, throwable);
+            } else if (throwable instanceof SecurityException) {
+                throw new SecurityException(msg, throwable);
+            } else if (throwable instanceof HttpTimeoutException) {
+                throw new HttpTimeoutException(msg);
+            } else if (throwable instanceof ConnectException) {
+                ConnectException ce = new ConnectException(msg);
+                ce.initCause(throwable);
+                throw ce;
+            } else if (throwable instanceof IOException) {
+                throw new IOException(msg, throwable);
+            } else {
+                throw new IOException(msg, throwable);
+            }
         }
     }
 
+    private static final Executor ASYNC_POOL = new CompletableFuture<Void>().defaultExecutor();
+
     @Override
     public <T> CompletableFuture<HttpResponse<T>>
     sendAsync(HttpRequest userRequest, BodyHandler<T> responseHandler)
@@ -511,13 +559,20 @@
         return sendAsync(userRequest, responseHandler, null);
     }
 
-
     @Override
     public <T> CompletableFuture<HttpResponse<T>>
     sendAsync(HttpRequest userRequest,
               BodyHandler<T> responseHandler,
-              PushPromiseHandler<T> pushPromiseHandler)
-    {
+              PushPromiseHandler<T> pushPromiseHandler) {
+        return sendAsync(userRequest, responseHandler, pushPromiseHandler, delegatingExecutor.delegate);
+    }
+
+    private <T> CompletableFuture<HttpResponse<T>>
+    sendAsync(HttpRequest userRequest,
+              BodyHandler<T> responseHandler,
+              PushPromiseHandler<T> pushPromiseHandler,
+              Executor exchangeExecutor)    {
+
         Objects.requireNonNull(userRequest);
         Objects.requireNonNull(responseHandler);
 
@@ -536,9 +591,17 @@
             if (debugelapsed.on())
                 debugelapsed.log("ClientImpl (async) send %s", userRequest);
 
-            Executor executor = acc == null
-                    ? this.executor
-                    : new PrivilegedExecutor(this.executor, acc);
+            // When using sendAsync(...) we explicitly pass the
+            // executor's delegate as exchange executor to force
+            // asynchronous scheduling of the exchange.
+            // When using send(...) we don't specify any executor
+            // and default to using the client's delegating executor
+            // which only spawns asynchronous tasks if it detects
+            // that the current thread is the selector manager
+            // thread. This will cause everything to execute inline
+            // until we need to schedule some event with the selector.
+            Executor executor = exchangeExecutor == null
+                    ? this.delegatingExecutor : exchangeExecutor;
 
             MultiExchange<T> mex = new MultiExchange<>(userRequest,
                                                             requestImpl,
@@ -547,15 +610,18 @@
                                                             pushPromiseHandler,
                                                             acc);
             CompletableFuture<HttpResponse<T>> res =
-                    mex.responseAsync().whenComplete((b,t) -> unreference());
+                    mex.responseAsync(executor).whenComplete((b,t) -> unreference());
             if (DEBUGELAPSED) {
                 res = res.whenComplete(
                         (b,t) -> debugCompleted("ClientImpl (async)", start, userRequest));
             }
 
-            // makes sure that any dependent actions happen in the executor
-            res = res.whenCompleteAsync((r, t) -> { /* do nothing */}, executor);
-
+            // makes sure that any dependent actions happen in the CF default
+            // executor. This is only needed for sendAsync(...), when
+            // exchangeExecutor is non-null.
+            if (exchangeExecutor != null) {
+                res = res.whenCompleteAsync((r, t) -> { /* do nothing */}, ASYNC_POOL);
+            }
             return res;
         } catch(Throwable t) {
             unreference();
@@ -654,6 +720,7 @@
         }
 
         synchronized void shutdown() {
+            Log.logTrace("{0}: shutting down", getName());
             if (debug.on()) debug.log("SelectorManager shutting down");
             closed = true;
             try {
@@ -670,6 +737,7 @@
             List<AsyncEvent> readyList = new ArrayList<>();
             List<Runnable> resetList = new ArrayList<>();
             try {
+                if (Log.channel()) Log.logChannel(getName() + ": starting");
                 while (!Thread.currentThread().isInterrupted()) {
                     synchronized (this) {
                         assert errorList.isEmpty();
@@ -706,7 +774,7 @@
                                     throw new IOException("Channel closed");
                                 }
                             } catch (IOException e) {
-                                Log.logTrace("HttpClientImpl: " + e);
+                                Log.logTrace("{0}: {1}", getName(), e);
                                 if (debug.on())
                                     debug.log("Got " + e.getClass().getName()
                                               + " while handling registration events");
@@ -738,7 +806,9 @@
                     // Check whether client is still alive, and if not,
                     // gracefully stop this thread
                     if (!owner.isReferenced()) {
-                        Log.logTrace("HttpClient no longer referenced. Exiting...");
+                        Log.logTrace("{0}: {1}",
+                                getName(),
+                                "HttpClient no longer referenced. Exiting...");
                         return;
                     }
 
@@ -780,7 +850,9 @@
                         // Check whether client is still alive, and if not,
                         // gracefully stop this thread
                         if (!owner.isReferenced()) {
-                            Log.logTrace("HttpClient no longer referenced. Exiting...");
+                            Log.logTrace("{0}: {1}",
+                                    getName(),
+                                    "HttpClient no longer referenced. Exiting...");
                             return;
                         }
                         owner.purgeTimeoutsAndReturnNextDeadline();
@@ -831,17 +903,18 @@
 
                 }
             } catch (Throwable e) {
-                //e.printStackTrace();
                 if (!closed) {
                     // This terminates thread. So, better just print stack trace
                     String err = Utils.stackTrace(e);
-                    Log.logError("HttpClientImpl: fatal error: " + err);
+                    Log.logError("{0}: {1}: {2}", getName(),
+                            "HttpClientImpl shutting down due to fatal error", err);
                 }
                 if (debug.on()) debug.log("shutting down", e);
                 if (Utils.ASSERTIONSENABLED && !debug.on()) {
                     e.printStackTrace(System.err); // always print the stack
                 }
             } finally {
+                if (Log.channel()) Log.logChannel(getName() + ": stopping");
                 shutdown();
             }
         }
@@ -1013,13 +1086,15 @@
         return Optional.ofNullable(authenticator);
     }
 
-    /*package-private*/ final Executor theExecutor() {
-        return executor;
+    /*package-private*/ final DelegatingExecutor theExecutor() {
+        return delegatingExecutor;
     }
 
     @Override
     public final Optional<Executor> executor() {
-        return isDefaultExecutor ? Optional.empty() : Optional.of(executor);
+        return isDefaultExecutor
+                ? Optional.empty()
+                : Optional.of(delegatingExecutor.delegate());
     }
 
     ConnectionPool connectionPool() {
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java	Thu Jun 21 09:53:50 2018 -0700
@@ -27,7 +27,6 @@
 
 import java.io.Closeable;
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
@@ -250,7 +249,7 @@
      * @param request
      * @return
      */
-    BiPredicate<String,List<String>> headerFilter(HttpRequestImpl request) {
+    BiPredicate<String,String> headerFilter(HttpRequestImpl request) {
         if (isTunnel()) {
             // talking to a server through a proxy tunnel
             // don't send proxy-* headers to a plain server
@@ -280,12 +279,12 @@
     // start with "proxy-"
     private static HttpHeaders proxyTunnelHeaders(HttpRequestImpl request) {
         Map<String, List<String>> combined = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        combined.putAll(request.getSystemHeaders().map());
+        combined.putAll(request.getSystemHeadersBuilder().map());
         combined.putAll(request.headers().map()); // let user override system
 
         // keep only proxy-* - and also strip authorization headers
         // for disabled schemes
-        return ImmutableHeaders.of(combined, Utils.PROXY_TUNNEL_FILTER);
+        return HttpHeaders.of(combined, Utils.PROXY_TUNNEL_FILTER);
     }
 
     /* Returns either a plain HTTP connection or a plain tunnelling connection
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestBuilderImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestBuilderImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -32,9 +32,9 @@
 import java.net.http.HttpClient;
 import java.net.http.HttpRequest;
 import java.net.http.HttpRequest.BodyPublisher;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Utils;
-import static java.lang.String.format;
 import static java.util.Objects.requireNonNull;
 import static jdk.internal.net.http.common.Utils.isValidName;
 import static jdk.internal.net.http.common.Utils.isValidValue;
@@ -42,7 +42,7 @@
 
 public class HttpRequestBuilderImpl implements HttpRequest.Builder {
 
-    private HttpHeadersImpl userHeaders;
+    private HttpHeadersBuilder headersBuilder;
     private URI uri;
     private String method;
     private boolean expectContinue;
@@ -54,13 +54,13 @@
         requireNonNull(uri, "uri must be non-null");
         checkURI(uri);
         this.uri = uri;
-        this.userHeaders = new HttpHeadersImpl();
+        this.headersBuilder = new HttpHeadersBuilder();
         this.method = "GET"; // default, as per spec
         this.version = Optional.empty();
     }
 
     public HttpRequestBuilderImpl() {
-        this.userHeaders = new HttpHeadersImpl();
+        this.headersBuilder = new HttpHeadersBuilder();
         this.method = "GET"; // default, as per spec
         this.version = Optional.empty();
     }
@@ -90,7 +90,7 @@
     public HttpRequestBuilderImpl copy() {
         HttpRequestBuilderImpl b = new HttpRequestBuilderImpl();
         b.uri = this.uri;
-        b.userHeaders = this.userHeaders.deepCopy();
+        b.headersBuilder = this.headersBuilder.structuralCopy();
         b.method = this.method;
         b.expectContinue = this.expectContinue;
         b.bodyPublisher = bodyPublisher;
@@ -106,7 +106,7 @@
         if (!isValidName(name)) {
             throw newIAE("invalid header name: \"%s\"", name);
         }
-        if (!Utils.ALLOWED_HEADERS.test(name)) {
+        if (!Utils.ALLOWED_HEADERS.test(name, null)) {
             throw newIAE("restricted header name: \"%s\"", name);
         }
         if (!isValidValue(value)) {
@@ -117,14 +117,14 @@
     @Override
     public HttpRequestBuilderImpl setHeader(String name, String value) {
         checkNameAndValue(name, value);
-        userHeaders.setHeader(name, value);
+        headersBuilder.setHeader(name, value);
         return this;
     }
 
     @Override
     public HttpRequestBuilderImpl header(String name, String value) {
         checkNameAndValue(name, value);
-        userHeaders.addHeader(name, value);
+        headersBuilder.addHeader(name, value);
         return this;
     }
 
@@ -155,7 +155,7 @@
         return this;
     }
 
-    HttpHeadersImpl headers() {  return userHeaders; }
+    HttpHeadersBuilder headersBuilder() {  return headersBuilder; }
 
     URI uri() { return uri; }
 
@@ -216,6 +216,13 @@
         if (uri == null)
             throw new IllegalStateException("uri is null");
         assert method != null;
+        return new ImmutableHttpRequest(this);
+    }
+
+    public HttpRequestImpl buildForWebSocket() {
+        if (uri == null)
+            throw new IllegalStateException("uri is null");
+        assert method != null;
         return new HttpRequestImpl(this);
     }
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -41,16 +41,16 @@
 import java.net.http.HttpClient;
 import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Utils;
 import jdk.internal.net.http.websocket.WebSocketRequest;
 
 import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
 
-class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
 
     private final HttpHeaders userHeaders;
-    private final HttpHeadersImpl systemHeaders;
+    private final HttpHeadersBuilder systemHeadersBuilder;
     private final URI uri;
     private volatile Proxy proxy; // ensure safe publishing
     private final InetSocketAddress authority; // only used when URI not specified
@@ -78,8 +78,8 @@
     public HttpRequestImpl(HttpRequestBuilderImpl builder) {
         String method = builder.method();
         this.method = method == null ? "GET" : method;
-        this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS);
-        this.systemHeaders = new HttpHeadersImpl();
+        this.userHeaders = HttpHeaders.of(builder.headersBuilder().map(), ALLOWED_HEADERS);
+        this.systemHeadersBuilder = new HttpHeadersBuilder();
         this.uri = builder.uri();
         assert uri != null;
         this.proxy = null;
@@ -106,21 +106,23 @@
                 "uri must be non null");
         Duration timeout = request.timeout().orElse(null);
         this.method = method == null ? "GET" : method;
-        this.userHeaders = ImmutableHeaders.validate(request.headers());
+        this.userHeaders = HttpHeaders.of(request.headers().map(), Utils.VALIDATE_USER_HEADER);
         if (request instanceof HttpRequestImpl) {
             // all cases exception WebSocket should have a new system headers
             this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
             if (isWebSocket) {
-                this.systemHeaders = ((HttpRequestImpl) request).systemHeaders;
+                this.systemHeadersBuilder = ((HttpRequestImpl)request).systemHeadersBuilder;
             } else {
-                this.systemHeaders = new HttpHeadersImpl();
+                this.systemHeadersBuilder = new HttpHeadersBuilder();
             }
         } else {
             HttpRequestBuilderImpl.checkURI(requestURI);
             checkTimeout(timeout);
-            this.systemHeaders = new HttpHeadersImpl();
+            this.systemHeadersBuilder = new HttpHeadersBuilder();
         }
-        this.systemHeaders.setHeader("User-Agent", USER_AGENT);
+        if (!userHeaders.firstValue("User-Agent").isPresent()) {
+            this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
+        }
         this.uri = requestURI;
         if (isWebSocket) {
             // WebSocket determines and sets the proxy itself
@@ -169,8 +171,10 @@
         this.method = method == null? "GET" : method;
         this.userHeaders = other.userHeaders;
         this.isWebSocket = other.isWebSocket;
-        this.systemHeaders = new HttpHeadersImpl();
-        this.systemHeaders.setHeader("User-Agent", USER_AGENT);
+        this.systemHeadersBuilder = new HttpHeadersBuilder();
+        if (!userHeaders.firstValue("User-Agent").isPresent()) {
+            this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
+        }
         this.uri = uri;
         this.proxy = other.proxy;
         this.expectContinue = other.expectContinue;
@@ -189,8 +193,8 @@
         // to the connection pool (we might need to revisit this constructor later)
         assert "CONNECT".equalsIgnoreCase(method);
         this.method = method;
-        this.systemHeaders = new HttpHeadersImpl();
-        this.userHeaders = ImmutableHeaders.of(headers);
+        this.systemHeadersBuilder = new HttpHeadersBuilder();
+        this.userHeaders = headers;
         this.uri = URI.create("socket://" + authority.getHostString() + ":"
                               + Integer.toString(authority.getPort()) + "/");
         this.proxy = null;
@@ -218,14 +222,14 @@
      * parent.
      */
     static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
-                                             HttpHeadersImpl headers)
+                                             HttpHeaders headers)
         throws IOException
     {
         return new HttpRequestImpl(parent, headers);
     }
 
     // only used for push requests
-    private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers)
+    private HttpRequestImpl(HttpRequestImpl parent, HttpHeaders headers)
         throws IOException
     {
         this.method = headers.firstValue(":method")
@@ -240,8 +244,8 @@
         sb.append(scheme).append("://").append(authority).append(path);
         this.uri = URI.create(sb.toString());
         this.proxy = null;
-        this.userHeaders = ImmutableHeaders.of(headers.map(), ALLOWED_HEADERS);
-        this.systemHeaders = parent.systemHeaders;
+        this.userHeaders = HttpHeaders.of(headers.map(), ALLOWED_HEADERS);
+        this.systemHeadersBuilder = parent.systemHeadersBuilder;
         this.expectContinue = parent.expectContinue;
         this.secure = parent.secure;
         this.requestPublisher = parent.requestPublisher;
@@ -264,9 +268,9 @@
     InetSocketAddress authority() { return authority; }
 
     void setH2Upgrade(Http2ClientImpl h2client) {
-        systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
-        systemHeaders.setHeader("Upgrade", "h2c");
-        systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
+        systemHeadersBuilder.setHeader("Connection", "Upgrade, HTTP2-Settings");
+        systemHeadersBuilder.setHeader("Upgrade", "h2c");
+        systemHeadersBuilder.setHeader("HTTP2-Settings", h2client.getSettingsString());
     }
 
     @Override
@@ -332,18 +336,18 @@
 
     HttpHeaders getUserHeaders() { return userHeaders; }
 
-    HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
+    HttpHeadersBuilder getSystemHeadersBuilder() { return systemHeadersBuilder; }
 
     @Override
     public Optional<HttpClient.Version> version() { return version; }
 
     void addSystemHeader(String name, String value) {
-        systemHeaders.addHeader(name, value);
+        systemHeadersBuilder.addHeader(name, value);
     }
 
     @Override
     public void setSystemHeader(String name, String value) {
-        systemHeaders.setHeader(name, value);
+        systemHeadersBuilder.setHeader(name, value);
     }
 
     InetSocketAddress getAddress() {
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ImmutableHeaders.java	Wed Jun 20 11:12:48 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.net.http;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.TreeMap;
-import java.util.function.BiPredicate;
-import java.util.function.Predicate;
-import java.net.http.HttpHeaders;
-import jdk.internal.net.http.common.HttpHeadersImpl;
-import jdk.internal.net.http.common.Utils;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.unmodifiableList;
-import static java.util.Collections.unmodifiableMap;
-import static java.util.Objects.requireNonNull;
-
-final class ImmutableHeaders extends HttpHeaders {
-
-    private final Map<String, List<String>> map;
-
-    public static ImmutableHeaders empty() {
-        return of(emptyMap());
-    }
-
-    public static ImmutableHeaders of(Map<String, List<String>> src) {
-        return of(src, x -> true);
-    }
-
-    public static ImmutableHeaders of(HttpHeaders headers) {
-        return (headers instanceof ImmutableHeaders)
-                ? (ImmutableHeaders)headers
-                : of(headers.map());
-    }
-
-    static ImmutableHeaders validate(HttpHeaders headers) {
-        if (headers instanceof ImmutableHeaders) {
-            return of(headers);
-        }
-        if (headers instanceof HttpHeadersImpl) {
-            return of(headers);
-        }
-        Map<String, List<String>> map = headers.map();
-        return new ImmutableHeaders(map, Utils.VALIDATE_USER_HEADER);
-    }
-
-    public static ImmutableHeaders of(Map<String, List<String>> src,
-                                      Predicate<? super String> keyAllowed) {
-        requireNonNull(src, "src");
-        requireNonNull(keyAllowed, "keyAllowed");
-        return new ImmutableHeaders(src, headerAllowed(keyAllowed));
-    }
-
-    public static ImmutableHeaders of(Map<String, List<String>> src,
-                                      BiPredicate<? super String, ? super List<String>> headerAllowed) {
-        requireNonNull(src, "src");
-        requireNonNull(headerAllowed, "headerAllowed");
-        return new ImmutableHeaders(src, headerAllowed);
-    }
-
-    private ImmutableHeaders(Map<String, List<String>> src,
-                             BiPredicate<? super String, ? super List<String>> headerAllowed) {
-        Map<String, List<String>> m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        src.entrySet().stream()
-                .forEach(e -> addIfAllowed(e, headerAllowed, m));
-        this.map = unmodifiableMap(m);
-    }
-
-    private static void addIfAllowed(Map.Entry<String, List<String>> e,
-                                     BiPredicate<? super String, ? super List<String>> headerAllowed,
-                                     Map<String, List<String>> map) {
-        String key = e.getKey();
-        List<String> values = unmodifiableValues(e.getValue());
-        if (headerAllowed.test(key, values)) {
-            map.put(key, values);
-        }
-    }
-
-    private static List<String> unmodifiableValues(List<String> values) {
-        return unmodifiableList(new ArrayList<>(Objects.requireNonNull(values)));
-    }
-
-    private static BiPredicate<String, List<String>> headerAllowed(Predicate<? super String> keyAllowed) {
-        return (n,v) -> keyAllowed.test(n);
-    }
-
-    @Override
-    public Map<String, List<String>> map() {
-        return map;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ImmutableHttpRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.net.http;
+
+import java.net.URI;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.time.Duration;
+import java.util.Objects;
+import java.util.Optional;
+import java.net.http.HttpClient.Version;
+import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
+
+final class ImmutableHttpRequest extends HttpRequest {
+
+    private final String method;
+    private final URI uri;
+    private final HttpHeaders headers;
+    private final Optional<BodyPublisher> requestPublisher;
+    private final boolean expectContinue;
+    private final Optional<Duration> timeout;
+    private final Optional<Version> version;
+
+    /** Creates an ImmutableHttpRequest from the given builder. */
+    ImmutableHttpRequest(HttpRequestBuilderImpl builder) {
+        this.method = Objects.requireNonNull(builder.method());
+        this.uri = Objects.requireNonNull(builder.uri());
+        this.headers = HttpHeaders.of(builder.headersBuilder().map(), ALLOWED_HEADERS);
+        this.requestPublisher = Optional.ofNullable(builder.bodyPublisher());
+        this.expectContinue = builder.expectContinue();
+        this.timeout = Optional.ofNullable(builder.timeout());
+        this.version = Objects.requireNonNull(builder.version());
+    }
+
+    @Override
+    public String method() { return method; }
+
+    @Override
+    public URI uri() { return uri; }
+
+    @Override
+    public HttpHeaders headers() {
+        return headers;
+    }
+
+    @Override
+    public Optional<BodyPublisher> bodyPublisher() { return requestPublisher; }
+
+    @Override
+    public boolean expectContinue() { return expectContinue; }
+
+    @Override
+    public Optional<Duration> timeout() { return timeout; }
+
+    @Override
+    public Optional<Version> version() { return version; }
+
+    @Override
+    public String toString() {
+        return uri.toString() + " " + method;
+    }
+}
--- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,7 +26,7 @@
 package jdk.internal.net.http;
 
 import java.io.IOException;
-import java.lang.System.Logger.Level;
+import java.net.ConnectException;
 import java.time.Duration;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -69,7 +69,7 @@
     final AccessControlContext acc;
     final HttpClientImpl client;
     final HttpResponse.BodyHandler<T> responseHandler;
-    final Executor executor;
+    final HttpClientImpl.DelegatingExecutor executor;
     final AtomicInteger attempts = new AtomicInteger();
     HttpRequestImpl currentreq; // used for retries & redirect
     HttpRequestImpl previousreq; // used for retries & redirect
@@ -124,8 +124,8 @@
 
         if (pushPromiseHandler != null) {
             Executor executor = acc == null
-                    ? this.executor
-                    : new PrivilegedExecutor(this.executor, acc);
+                    ? this.executor.delegate()
+                    : new PrivilegedExecutor(this.executor.delegate(), acc);
             this.pushGroup = new PushGroup<>(pushPromiseHandler, request, executor);
         } else {
             pushGroup = null;
@@ -193,7 +193,7 @@
         getExchange().cancel(cause);
     }
 
-    public CompletableFuture<HttpResponse<T>> responseAsync() {
+    public CompletableFuture<HttpResponse<T>> responseAsync(Executor executor) {
         CompletableFuture<Void> start = new MinimalFuture<>();
         CompletableFuture<HttpResponse<T>> cf = responseAsync0(start);
         start.completeAsync( () -> null, executor); // trigger execution
@@ -285,13 +285,22 @@
 
     private static boolean retryPostValue() {
         String s = Utils.getNetProperty("jdk.httpclient.enableAllMethodRetry");
-        if (s == "" || "true".equals(s))
-            return true;
-        return false;
+        if (s == null)
+            return false;
+        return s.isEmpty() ? true : Boolean.parseBoolean(s);
+    }
+
+    private static boolean retryConnect() {
+        String s = Utils.getNetProperty("jdk.httpclient.disableRetryConnect");
+        if (s == null)
+            return false;
+        return s.isEmpty() ? true : Boolean.parseBoolean(s);
     }
 
     /** True if ALL ( even non-idempotent ) requests can be automatic retried. */
     private static final boolean RETRY_ALWAYS = retryPostValue();
+    /** True if ConnectException should cause a retry. Enabled by default */
+    private static final boolean RETRY_CONNECT = retryConnect();
 
     /** Returns true is given request has an idempotent method. */
     private static boolean isIdempotentRequest(HttpRequest request) {
@@ -307,13 +316,23 @@
 
     /** Returns true if the given request can be automatically retried. */
     private static boolean canRetryRequest(HttpRequest request) {
+        if (RETRY_ALWAYS)
+            return true;
         if (isIdempotentRequest(request))
             return true;
-        if (RETRY_ALWAYS)
-            return true;
         return false;
     }
 
+    private boolean retryOnFailure(Throwable t) {
+        return t instanceof ConnectionExpiredException
+                || (RETRY_CONNECT && (t instanceof ConnectException));
+    }
+
+    private Throwable retryCause(Throwable t) {
+        Throwable cause = t instanceof ConnectionExpiredException ? t.getCause() : t;
+        return cause == null ? t : cause;
+    }
+
     /**
      * Takes a Throwable and returns a suitable CompletableFuture that is
      * completed exceptionally, or null.
@@ -326,21 +345,20 @@
         }
         if (cancelled && t instanceof IOException) {
             t = new HttpTimeoutException("request timed out");
-        } else if (t instanceof ConnectionExpiredException) {
-            Throwable cause = t;
-            if (t.getCause() != null) {
-                cause = t.getCause(); // unwrap the ConnectionExpiredException
-            }
+        } else if (retryOnFailure(t)) {
+            Throwable cause = retryCause(t);
 
-            if (!canRetryRequest(currentreq)) {
-                return failedFuture(cause); // fails with original cause
+            if (!(t instanceof ConnectException)) {
+                if (!canRetryRequest(currentreq)) {
+                    return failedFuture(cause); // fails with original cause
+                }
             }
 
             // allow the retry mechanism to do its work
             retryCause = cause;
             if (!expiredOnce) {
                 if (debug.on())
-                    debug.log("ConnectionExpiredException (async): retrying...", t);
+                    debug.log(t.getClass().getSimpleName() + " (async): retrying...", t);
                 expiredOnce = true;
                 // The connection was abruptly closed.
                 // We return null to retry the same request a second time.
@@ -350,9 +368,11 @@
                 previousreq = currentreq;
                 return null;
             } else {
-                if (debug.on())
-                    debug.log("ConnectionExpiredException (async): already retried once.", t);
-                if (t.getCause() != null) t = t.getCause();
+                if (debug.on()) {
+                    debug.log(t.getClass().getSimpleName()
+                            + " (async): already retried once.", t);
+                }
+                t = cause;
             }
         }
         return failedFuture(t);
@@ -364,9 +384,10 @@
         }
         @Override
         public void handle() {
-            if (debug.on())
+            if (debug.on()) {
                 debug.log("Cancelling MultiExchange due to timeout for request %s",
-                          request);
+                        request);
+            }
             cancel(new HttpTimeoutException("request timed out"));
         }
     }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,10 +26,8 @@
 package jdk.internal.net.http;
 
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.net.InetSocketAddress;
 import java.net.StandardSocketOptions;
-import java.nio.ByteBuffer;
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.SocketChannel;
@@ -91,14 +89,16 @@
                 // complete async since the event runs on the SelectorManager thread
                 cf.completeAsync(() -> null, client().theExecutor());
             } catch (Throwable e) {
-                client().theExecutor().execute( () -> cf.completeExceptionally(e));
+                Throwable t = Utils.toConnectException(e);
+                client().theExecutor().execute( () -> cf.completeExceptionally(t));
+                close();
             }
         }
 
         @Override
         public void abort(IOException ioe) {
+            client().theExecutor().execute( () -> cf.completeExceptionally(ioe));
             close();
-            client().theExecutor().execute( () -> cf.completeExceptionally(ioe));
         }
     }
 
@@ -114,7 +114,7 @@
             try {
                  finished = AccessController.doPrivileged(pa);
             } catch (PrivilegedActionException e) {
-                cf.completeExceptionally(e.getCause());
+               throw e.getCause();
             }
             if (finished) {
                 if (debug.on()) debug.log("connect finished without blocking");
@@ -125,7 +125,13 @@
                 client().registerEvent(new ConnectEvent(cf));
             }
         } catch (Throwable throwable) {
-            cf.completeExceptionally(throwable);
+            cf.completeExceptionally(Utils.toConnectException(throwable));
+            try {
+                close();
+            } catch (Exception x) {
+                if (debug.on())
+                    debug.log("Failed to close channel after unsuccessful connect");
+            }
         }
         return cf;
     }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java	Thu Jun 21 09:53:50 2018 -0700
@@ -43,6 +43,13 @@
     static final int DEFAULT_MAX_REDIRECTS = 5;
     URI uri;
 
+    /*
+     * NOT_MODIFIED status code results from a conditional GET where
+     * the server does not (must not) return a response body because
+     * the condition specified in the request disallows it
+     */
+    static final int HTTP_NOT_MODIFIED = 304;
+
     static final int max_redirects = Utils.getIntegerNetProperty(
             "jdk.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS
     );
@@ -91,6 +98,10 @@
         if (rcode == 200 || policy == HttpClient.Redirect.NEVER) {
             return null;
         }
+
+        if (rcode == HTTP_NOT_MODIFIED)
+            return null;
+
         if (rcode >= 300 && rcode <= 399) {
             URI redir = getRedirectedURI(r.headers());
             String newMethod = redirectedMethod(rcode, method);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Response.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Response.java	Thu Jun 21 09:53:50 2018 -0700
@@ -64,7 +64,7 @@
              int statusCode,
              HttpClient.Version version,
              boolean isConnectResponse) {
-        this.headers = ImmutableHeaders.of(headers);
+        this.headers = headers;
         this.request = req;
         this.version = version;
         this.exchange = exchange;
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseContent.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,7 +26,6 @@
 package jdk.internal.net.http;
 
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -34,9 +33,9 @@
 import java.util.function.Consumer;
 import java.net.http.HttpHeaders;
 import java.net.http.HttpResponse;
-
 import jdk.internal.net.http.common.Logger;
 import jdk.internal.net.http.common.Utils;
+import static java.lang.String.format;
 
 /**
  * Implements chunked/fixed transfer encodings of HTTP/1.1 responses.
@@ -95,6 +94,9 @@
 
     interface BodyParser extends Consumer<ByteBuffer> {
         void onSubscribe(AbstractSubscription sub);
+        // A current-state message suitable for inclusion in an exception
+        // detail message.
+        String currentStateMessage();
     }
 
     // Returns a parser that will take care of parsing the received byte
@@ -145,6 +147,11 @@
         }
 
         @Override
+        public String currentStateMessage() {
+            return format("chunked transfer encoding, state: %s", state);
+        }
+
+        @Override
         public void accept(ByteBuffer b) {
             if (closedExceptionally != null) {
                 if (debug.on())
@@ -425,6 +432,12 @@
         }
 
         @Override
+        public String currentStateMessage() {
+            return format("fixed content-length: %d, bytes received: %d",
+                          contentLength, contentLength - remaining);
+        }
+
+        @Override
         public void accept(ByteBuffer b) {
             if (closedExceptionally != null) {
                 if (debug.on())
--- a/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java	Thu Jun 21 09:53:50 2018 -0700
@@ -41,6 +41,7 @@
 import jdk.internal.net.http.common.BufferSupplier;
 import jdk.internal.net.http.common.Demand;
 import jdk.internal.net.http.common.FlowTube;
+import jdk.internal.net.http.common.Log;
 import jdk.internal.net.http.common.Logger;
 import jdk.internal.net.http.common.SequentialScheduler;
 import jdk.internal.net.http.common.SequentialScheduler.DeferredCompleter;
@@ -149,6 +150,10 @@
     void signalClosed() {
         // Ensures that the subscriber will be terminated and that future
         // subscribers will be notified when the connection is closed.
+        if (Log.channel()) {
+            Log.logChannel("Connection close signalled: connection closed locally ({0})",
+                    channelDescr());
+        }
         readPublisher.subscriptionImpl.signalError(
                 new IOException("connection closed locally"));
     }
@@ -364,6 +369,10 @@
         void startSubscription() {
             try {
                 if (debug.on()) debug.log("write: starting subscription");
+                if (Log.channel()) {
+                    Log.logChannel("Start requesting bytes for writing to channel: {0}",
+                            channelDescr());
+                }
                 assert client.isSelectorThread();
                 // make sure read registrations are handled before;
                 readPublisher.subscriptionImpl.handlePending();
@@ -409,6 +418,10 @@
 
         void signalError(Throwable error) {
             debug.log(() -> "write error: " + error);
+            if (Log.channel()) {
+                Log.logChannel("Failed to write to channel ({0}: {1})",
+                        channelDescr(), error);
+            }
             completed = true;
             readPublisher.signalError(error);
         }
@@ -455,6 +468,7 @@
 
             @Override
             public void cancel() {
+                if (debug.on()) debug.log("write: cancel");
                 dropSubscription();
                 upstreamSubscription.cancel();
             }
@@ -558,6 +572,10 @@
             if (!errorRef.compareAndSet(null, error)) {
                 return;
             }
+            if (Log.channel()) {
+                Log.logChannel("Error signalled on channel {0}: {1}",
+                        channelDescr(), error);
+            }
             subscriptionImpl.handleError();
         }
 
@@ -665,6 +683,7 @@
             final void handleSubscribeEvent() {
                 assert client.isSelectorThread();
                 debug.log("subscribe event raised");
+                if (Log.channel()) Log.logChannel("Start reading from {0}", channelDescr());
                 readScheduler.runOrSchedule();
                 if (readScheduler.isStopped() || completed) {
                     // if already completed or stopped we can handle any
@@ -702,6 +721,10 @@
             @Override
             public final void cancel() {
                 pauseReadEvent();
+                if (Log.channel()) {
+                    Log.logChannel("Read subscription cancelled for channel {0}",
+                            channelDescr());
+                }
                 readScheduler.stop();
             }
 
@@ -726,6 +749,10 @@
                     return;
                 }
                 if (debug.on()) debug.log("got read error: " + error);
+                if (Log.channel()) {
+                    Log.logChannel("Read error signalled on channel {0}: {1}",
+                            channelDescr(), error);
+                }
                 readScheduler.runOrSchedule();
             }
 
@@ -772,6 +799,10 @@
                             if (debug.on())
                                 debug.log("Sending error " + error
                                           + " to subscriber " + subscriber);
+                            if (Log.channel()) {
+                                Log.logChannel("Raising error with subscriber for {0}: {1}",
+                                        channelDescr(), error);
+                            }
                             current.errorRef.compareAndSet(null, error);
                             current.signalCompletion();
                             readScheduler.stop();
@@ -788,6 +819,10 @@
                                 if (bytes == EOF) {
                                     if (!completed) {
                                         if (debug.on()) debug.log("got read EOF");
+                                        if (Log.channel()) {
+                                            Log.logChannel("EOF read from channel: {0}",
+                                                        channelDescr());
+                                        }
                                         completed = true;
                                         // safe to pause here because we're finished
                                         // anyway.
@@ -849,6 +884,12 @@
                     if (debug.on()) debug.log("Unexpected exception in read loop", t);
                     signalError(t);
                 } finally {
+                    if (readScheduler.isStopped()) {
+                        if (debug.on()) debug.log("Read scheduler stopped");
+                        if (Log.channel()) {
+                            Log.logChannel("Stopped reading from channel {0}", channelDescr());
+                        }
+                    }
                     handlePending();
                 }
             }
@@ -1238,4 +1279,8 @@
     final String dbgString() {
         return "SocketTube("+id+")";
     }
+
+    final String channelDescr() {
+        return String.valueOf(channel);
+    }
 }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,9 +25,9 @@
 
 package jdk.internal.net.http;
 
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.lang.System.Logger.Level;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
@@ -39,6 +39,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.Flow;
 import java.util.concurrent.Flow.Subscription;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiPredicate;
 import java.net.http.HttpClient;
@@ -114,8 +115,8 @@
     final Http2Connection connection;
     final HttpRequestImpl request;
     final HeadersConsumer rspHeadersConsumer;
-    final HttpHeadersImpl responseHeaders;
-    final HttpHeadersImpl requestPseudoHeaders;
+    final HttpHeadersBuilder responseHeadersBuilder;
+    final HttpHeaders requestPseudoHeaders;
     volatile HttpResponse.BodySubscriber<T> responseSubscriber;
     final HttpRequest.BodyPublisher requestPublisher;
     volatile RequestSubscriber requestSubscriber;
@@ -133,6 +134,8 @@
     private volatile boolean closed;
     private volatile boolean endStreamSent;
 
+    final AtomicBoolean deRegistered = new AtomicBoolean(false);
+
     // state flags
     private boolean requestSent, responseReceived;
 
@@ -171,7 +174,7 @@
                 Http2Frame frame = inputQ.peek();
                 if (frame instanceof ResetFrame) {
                     inputQ.remove();
-                    handleReset((ResetFrame)frame);
+                    handleReset((ResetFrame)frame, subscriber);
                     return;
                 }
                 DataFrame df = (DataFrame)frame;
@@ -185,6 +188,7 @@
                     Log.logTrace("responseSubscriber.onComplete");
                     if (debug.on()) debug.log("incoming: onComplete");
                     sched.stop();
+                    connection.decrementStreamsCount(streamid);
                     subscriber.onComplete();
                     onCompleteCalled = true;
                     setEndStreamReceived();
@@ -198,6 +202,7 @@
                         Log.logTrace("responseSubscriber.onComplete");
                         if (debug.on()) debug.log("incoming: onComplete");
                         sched.stop();
+                        connection.decrementStreamsCount(streamid);
                         subscriber.onComplete();
                         onCompleteCalled = true;
                         setEndStreamReceived();
@@ -251,6 +256,10 @@
         return true; // end of stream
     }
 
+    boolean deRegister() {
+        return deRegistered.compareAndSet(false, true);
+    }
+
     @Override
     CompletableFuture<T> readBodyAsync(HttpResponse.BodyHandler<T> handler,
                                        boolean returnConnectionToPool,
@@ -258,6 +267,7 @@
     {
         try {
             Log.logTrace("Reading body on stream {0}", streamid);
+            debug.log("Getting BodySubscriber for: " + response);
             BodySubscriber<T> bodySubscriber = handler.apply(new ResponseInfoImpl(response));
             CompletableFuture<T> cf = receiveData(bodySubscriber, executor);
 
@@ -337,10 +347,9 @@
         this.windowController = windowController;
         this.request = e.request();
         this.requestPublisher = request.requestPublisher;  // may be null
-        responseHeaders = new HttpHeadersImpl();
-        rspHeadersConsumer = new HeadersConsumer();
-        this.requestPseudoHeaders = new HttpHeadersImpl();
-        // NEW
+        this.responseHeadersBuilder = new HttpHeadersBuilder();
+        this.rspHeadersConsumer = new HeadersConsumer();
+        this.requestPseudoHeaders = createPseudoHeaders(request);
         this.windowUpdater = new StreamWindowUpdateSender(connection);
     }
 
@@ -391,6 +400,7 @@
     }
 
     protected void handleResponse() throws IOException {
+        HttpHeaders responseHeaders = responseHeadersBuilder.build();
         responseCode = (int)responseHeaders
                 .firstValueAsLong(":status")
                 .orElseThrow(() -> new IOException("no statuscode in response"));
@@ -424,25 +434,57 @@
         } else if (closed) {
             Log.logTrace("Ignoring RST_STREAM frame received on closed stream {0}", streamid);
         } else {
-            // put it in the input queue in order to read all
-            // pending data frames first. Indeed, a server may send
-            // RST_STREAM after sending END_STREAM, in which case we should
-            // ignore it. However, we won't know if we have received END_STREAM
-            // or not until all pending data frames are read.
-            receiveResetFrame(frame);
-            // RST_STREAM was pushed to the queue. It will be handled by
-            // asyncReceive after all pending data frames have been
-            // processed.
-            Log.logTrace("RST_STREAM pushed in queue for stream {0}", streamid);
+            Flow.Subscriber<?> subscriber =
+                    responseSubscriber == null ? pendingResponseSubscriber : responseSubscriber;
+            if (response == null && subscriber == null) {
+                // we haven't receive the headers yet, and won't receive any!
+                // handle reset now.
+                handleReset(frame, subscriber);
+            } else {
+                // put it in the input queue in order to read all
+                // pending data frames first. Indeed, a server may send
+                // RST_STREAM after sending END_STREAM, in which case we should
+                // ignore it. However, we won't know if we have received END_STREAM
+                // or not until all pending data frames are read.
+                receiveResetFrame(frame);
+                // RST_STREAM was pushed to the queue. It will be handled by
+                // asyncReceive after all pending data frames have been
+                // processed.
+                Log.logTrace("RST_STREAM pushed in queue for stream {0}", streamid);
+            }
         }
     }
 
-    void handleReset(ResetFrame frame) {
+    void handleReset(ResetFrame frame, Flow.Subscriber<?> subscriber) {
         Log.logTrace("Handling RST_STREAM on stream {0}", streamid);
         if (!closed) {
-            close();
-            int error = frame.getErrorCode();
-            completeResponseExceptionally(new IOException(ErrorFrame.stringForCode(error)));
+            synchronized (this) {
+                if (closed) {
+                    if (debug.on()) debug.log("Stream already closed: ignoring RESET");
+                    return;
+                }
+                closed = true;
+            }
+            try {
+                int error = frame.getErrorCode();
+                IOException e = new IOException("Received RST_STREAM: "
+                        + ErrorFrame.stringForCode(error));
+                if (errorRef.compareAndSet(null, e)) {
+                    if (subscriber != null) {
+                        subscriber.onError(e);
+                    }
+                }
+                completeResponseExceptionally(e);
+                if (!requestBodyCF.isDone()) {
+                    requestBodyCF.completeExceptionally(errorRef.get()); // we may be sending the body..
+                }
+                if (responseBodyCF != null) {
+                    responseBodyCF.completeExceptionally(errorRef.get());
+                }
+            } finally {
+                connection.decrementStreamsCount(streamid);
+                connection.closeStream(streamid);
+            }
         } else {
             Log.logTrace("Ignoring RST_STREAM frame received on closed stream {0}", streamid);
         }
@@ -535,13 +577,12 @@
     }
 
     private OutgoingHeaders<Stream<T>> headerFrame(long contentLength) {
-        HttpHeadersImpl h = request.getSystemHeaders();
+        HttpHeadersBuilder h = request.getSystemHeadersBuilder();
         if (contentLength > 0) {
             h.setHeader("content-length", Long.toString(contentLength));
         }
-        setPseudoHeaderFields();
-        HttpHeaders sysh = filter(h);
-        HttpHeaders userh = filter(request.getUserHeaders());
+        HttpHeaders sysh = filterHeaders(h.build());
+        HttpHeaders userh = filterHeaders(request.getUserHeaders());
         OutgoingHeaders<Stream<T>> f = new OutgoingHeaders<>(sysh, userh, this);
         if (contentLength == 0) {
             f.setFlag(HeadersFrame.END_STREAM);
@@ -565,7 +606,7 @@
     // If nothing needs filtering then we can just use the
     // original headers.
     private boolean needsFiltering(HttpHeaders headers,
-                                   BiPredicate<String, List<String>> filter) {
+                                   BiPredicate<String, String> filter) {
         if (filter == Utils.PROXY_TUNNEL_FILTER || filter == Utils.PROXY_FILTER) {
             // we're either connecting or proxying
             // slight optimization: we only need to filter out
@@ -583,18 +624,17 @@
         }
     }
 
-    private HttpHeaders filter(HttpHeaders headers) {
+    private HttpHeaders filterHeaders(HttpHeaders headers) {
         HttpConnection conn = connection();
-        BiPredicate<String, List<String>> filter =
-                conn.headerFilter(request);
+        BiPredicate<String, String> filter = conn.headerFilter(request);
         if (needsFiltering(headers, filter)) {
-            return ImmutableHeaders.of(headers.map(), filter);
+            return HttpHeaders.of(headers.map(), filter);
         }
         return headers;
     }
 
-    private void setPseudoHeaderFields() {
-        HttpHeadersImpl hdrs = requestPseudoHeaders;
+    private static HttpHeaders createPseudoHeaders(HttpRequest request) {
+        HttpHeadersBuilder hdrs = new HttpHeadersBuilder();
         String method = request.method();
         hdrs.setHeader(":method", method);
         URI uri = request.uri();
@@ -615,9 +655,10 @@
             path += "?" + query;
         }
         hdrs.setHeader(":path", Utils.encode(path));
+        return hdrs.build();
     }
 
-    HttpHeadersImpl getRequestPseudoHeaders() {
+    HttpHeaders getRequestPseudoHeaders() {
         return requestPseudoHeaders;
     }
 
@@ -657,6 +698,7 @@
         if (streamid > 0) {
             if (debug.on()) debug.log("Released stream %d", streamid);
             // remove this stream from the Http2Connection map.
+            connection.decrementStreamsCount(streamid);
             connection.closeStream(streamid);
         } else {
             if (debug.on()) debug.log("Can't release stream %d", streamid);
@@ -945,14 +987,18 @@
                 if (!cf.isDone()) {
                     Log.logTrace("Completing response (streamid={0}): {1}",
                                  streamid, cf);
+                    if (debug.on())
+                        debug.log("Completing responseCF(%d) with response headers", i);
+                    response_cfs.remove(cf);
                     cf.complete(resp);
-                    response_cfs.remove(cf);
                     return;
                 } // else we found the previous response: just leave it alone.
             }
             cf = MinimalFuture.completedFuture(resp);
             Log.logTrace("Created completed future (streamid={0}): {1}",
                          streamid, cf);
+            if (debug.on())
+                debug.log("Adding completed responseCF(0) with response headers");
             response_cfs.add(cf);
         }
     }
@@ -983,8 +1029,8 @@
             for (int i = 0; i < response_cfs.size(); i++) {
                 CompletableFuture<Response> cf = response_cfs.get(i);
                 if (!cf.isDone()) {
+                    response_cfs.remove(i);
                     cf.completeExceptionally(t);
-                    response_cfs.remove(i);
                     return;
                 }
             }
@@ -1033,6 +1079,15 @@
         cancelImpl(cause);
     }
 
+    void connectionClosing(Throwable cause) {
+        Flow.Subscriber<?> subscriber =
+                responseSubscriber == null ? pendingResponseSubscriber : responseSubscriber;
+        errorRef.compareAndSet(null, cause);
+        if (subscriber != null && !sched.isStopped() && !inputQ.isEmpty()) {
+            sched.runOrSchedule();
+        } else cancelImpl(cause);
+    }
+
     // This method sends a RST_STREAM frame
     void cancelImpl(Throwable e) {
         errorRef.compareAndSet(null, e);
@@ -1062,7 +1117,14 @@
         try {
             // will send a RST_STREAM frame
             if (streamid != 0) {
-                connection.resetStream(streamid, ResetFrame.CANCEL);
+                connection.decrementStreamsCount(streamid);
+                e = Utils.getCompletionCause(e);
+                if (e instanceof EOFException) {
+                    // read EOF: no need to try & send reset
+                    connection.closeStream(streamid);
+                } else {
+                    connection.resetStream(streamid, ResetFrame.CANCEL);
+                }
             }
         } catch (IOException ex) {
             Log.logError(ex);
@@ -1184,6 +1246,7 @@
         // create and return the PushResponseImpl
         @Override
         protected void handleResponse() {
+            HttpHeaders responseHeaders = responseHeadersBuilder.build();
             responseCode = (int)responseHeaders
                 .firstValueAsLong(":status")
                 .orElse(-1);
@@ -1252,17 +1315,18 @@
 
         void reset() {
             super.reset();
-            responseHeaders.clear();
+            responseHeadersBuilder.clear();
+            debug.log("Response builder cleared, ready to receive new headers.");
         }
 
         @Override
         public void onDecoded(CharSequence name, CharSequence value)
-                throws UncheckedIOException
+            throws UncheckedIOException
         {
             String n = name.toString();
             String v = value.toString();
             super.onDecoded(n, v);
-            responseHeaders.addHeader(n, v);
+            responseHeadersBuilder.addHeader(n, v);
             if (Log.headers() && Log.trace()) {
                 Log.logTrace("RECEIVED HEADER (streamid={0}): {1}: {2}",
                              streamid, n, v);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/ConnectionExpiredException.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/ConnectionExpiredException.java	Thu Jun 21 09:53:50 2018 -0700
@@ -35,13 +35,12 @@
     private static final long serialVersionUID = 0;
 
     /**
-     * Constructs a {@code ConnectionExpiredException} with the specified detail
-     * message and cause.
+     * Constructs a {@code ConnectionExpiredException} with a detail message of
+     * "subscription is finished" and the given cause.
      *
-     * @param   s     the detail message
      * @param   cause the throwable cause
      */
-    public ConnectionExpiredException(String s, Throwable cause) {
-        super(s, cause);
+    public ConnectionExpiredException(Throwable cause) {
+        super("subscription is finished", cause);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpHeadersBuilder.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.net.http.common;
+
+import java.net.http.HttpHeaders;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import static jdk.internal.net.http.common.Utils.ACCEPT_ALL;
+
+/** A mutable builder for collecting and building HTTP headers. */
+public class HttpHeadersBuilder {
+
+    private final TreeMap<String, List<String>> headersMap;
+
+    public HttpHeadersBuilder() {
+        headersMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+    }
+
+    public HttpHeadersBuilder structuralCopy() {
+        HttpHeadersBuilder builder = new HttpHeadersBuilder();
+        for (Map.Entry<String, List<String>> entry : headersMap.entrySet()) {
+            List<String> valuesCopy = new ArrayList<>(entry.getValue());
+            builder.headersMap.put(entry.getKey(), valuesCopy);
+        }
+        return builder;
+    }
+
+    public void addHeader(String name, String value) {
+        headersMap.computeIfAbsent(name, k -> new ArrayList<>(1))
+                  .add(value);
+    }
+
+    public void setHeader(String name, String value) {
+        // headers typically have one value
+        List<String> values = new ArrayList<>(1);
+        values.add(value);
+        headersMap.put(name, values);
+    }
+
+    public void clear() {
+        headersMap.clear();
+    }
+
+    public Map<String, List<String>> map() {
+        return headersMap;
+    }
+
+    public HttpHeaders build() {
+        return HttpHeaders.of(headersMap, ACCEPT_ALL);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString()).append(" { ");
+        sb.append(map());
+        sb.append(" }");
+        return sb.toString();
+    }
+}
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpHeadersImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.net.http.common;
-
-import java.net.http.HttpHeaders;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Implementation of HttpHeaders.
- *
- * The public HttpHeaders API provides a read-only view, while the
- * non-HttpHeaders members allow for implementation specific mutation, e.g.
- * during creation, etc.
- */
-public class HttpHeadersImpl extends HttpHeaders {
-
-    private final TreeMap<String, List<String>> headers;
-
-    public HttpHeadersImpl() {
-        headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-    }
-
-    @Override
-    public Map<String, List<String>> map() {
-        return Collections.unmodifiableMap(headersMap());
-    }
-
-    // non-HttpHeaders private mutators
-
-    public HttpHeadersImpl deepCopy() {
-        HttpHeadersImpl h1 = newDeepCopy();
-        for (Map.Entry<String, List<String>> entry : headersMap().entrySet()) {
-            List<String> valuesCopy = new ArrayList<>(entry.getValue());
-            h1.headersMap().put(entry.getKey(), valuesCopy);
-        }
-        return h1;
-    }
-
-    public void addHeader(String name, String value) {
-        headersMap().computeIfAbsent(name, k -> new ArrayList<>(1))
-                    .add(value);
-    }
-
-    public void setHeader(String name, String value) {
-        // headers typically have one value
-        List<String> values = new ArrayList<>(1);
-        values.add(value);
-        headersMap().put(name, values);
-    }
-
-    public void clear() {
-        headersMap().clear();
-    }
-
-    protected HttpHeadersImpl newDeepCopy() {
-        return new HttpHeadersImpl();
-    }
-
-    protected Map<String, List<String>> headersMap() {
-        return headers;
-    }
-}
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Log.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Log.java	Thu Jun 21 09:53:50 2018 -0700
@@ -43,7 +43,7 @@
 /**
  * -Djava.net.HttpClient.log=
  *          errors,requests,headers,
- *          frames[:control:data:window:all..],content,ssl,trace
+ *          frames[:control:data:window:all..],content,ssl,trace,channel
  *
  * Any of errors, requests, headers or content are optional.
  *
@@ -65,6 +65,7 @@
     public static final int FRAMES = 0x10;
     public static final int SSL = 0x20;
     public static final int TRACE = 0x40;
+    public static final int CHANNEL = 0x80;
     static int logging;
 
     // Frame types: "control", "data", "window", "all"
@@ -99,11 +100,15 @@
                     case "ssl":
                         logging |= SSL;
                         break;
+                    case "channel":
+                        logging |= CHANNEL;
+                        break;
                     case "trace":
                         logging |= TRACE;
                         break;
                     case "all":
-                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE|SSL;
+                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE|SSL| CHANNEL;
+                        frametypes |= ALL;
                         break;
                     default:
                         // ignore bad values
@@ -166,6 +171,10 @@
         return (logging & FRAMES) != 0;
     }
 
+    public static boolean channel() {
+        return (logging & CHANNEL) != 0;
+    }
+
     public static void logError(String s, Object... s1) {
         if (errors()) {
             logger.log(Level.INFO, "ERROR: " + s, s1);
@@ -191,9 +200,21 @@
         }
     }
 
+    public static void logChannel(String s, Object... s1) {
+        if (channel()) {
+            logger.log(Level.INFO, "CHANNEL: " + s, s1);
+        }
+    }
+
+    public static void logChannel(Supplier<String> msgSupplier) {
+        if (channel()) {
+            logger.log(Level.INFO, "CHANNEL: " + msgSupplier.get());
+        }
+    }
+
     public static void logTrace(String s, Object... s1) {
         if (trace()) {
-            String format = "TRACE: " + s;
+            String format = "MISC: " + s;
             logger.log(Level.INFO, format, s1);
         }
     }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLFlowDelegate.java	Thu Jun 21 09:53:50 2018 -0700
@@ -46,6 +46,7 @@
 import java.util.concurrent.Flow.Subscriber;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
+import java.util.function.IntBinaryOperator;
 
 /**
  * Implements SSL using two SubscriberWrappers.
@@ -87,13 +88,18 @@
     final Logger debug =
             Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
 
+    private static final ByteBuffer SENTINEL = Utils.EMPTY_BYTEBUFFER;
+    private static final ByteBuffer HS_TRIGGER = ByteBuffer.allocate(0);
+    // When handshake is in progress trying to wrap may produce no bytes.
+    private static final ByteBuffer NOTHING = ByteBuffer.allocate(0);
+    private static final String monProp = Utils.getProperty("jdk.internal.httpclient.monitorFlowDelegate");
+
     final Executor exec;
     final Reader reader;
     final Writer writer;
     final SSLEngine engine;
     final String tubeName; // hack
     final CompletableFuture<String> alpnCF; // completes on initial handshake
-    final static ByteBuffer SENTINEL = Utils.EMPTY_BYTEBUFFER;
     volatile boolean close_notify_received;
     final CompletableFuture<Void> readerCF;
     final CompletableFuture<Void> writerCF;
@@ -146,7 +152,8 @@
         // Writer to the downWriter.
         connect(downReader, downWriter);
 
-        //Monitor.add(this::monitor);
+        if (monProp != null && (monProp.equals("") || monProp.equalsIgnoreCase("true")))
+            Monitor.add(this::monitor);
     }
 
     /**
@@ -245,13 +252,16 @@
         final Logger debugr = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
 
         private final class ReaderDownstreamPusher implements Runnable {
-            @Override public void run() { processData(); }
+            @Override
+            public void run() {
+                processData();
+            }
         }
 
         Reader() {
             super();
             scheduler = SequentialScheduler.synchronizedScheduler(
-                                                new ReaderDownstreamPusher());
+                    new ReaderDownstreamPusher());
             this.readBuf = ByteBuffer.allocate(1024);
             readBuf.limit(0); // keep in read mode
         }
@@ -276,7 +286,7 @@
         public void incoming(List<ByteBuffer> buffers, boolean complete) {
             if (debugr.on())
                 debugr.log("Adding %d bytes to read buffer",
-                           Utils.remaining(buffers));
+                        Utils.remaining(buffers));
             addToReadBuf(buffers, complete);
             scheduler.runOrSchedule(exec);
         }
@@ -289,7 +299,7 @@
 
         private void reallocReadBuf() {
             int sz = readBuf.capacity();
-            ByteBuffer newb = ByteBuffer.allocate(sz*2);
+            ByteBuffer newb = ByteBuffer.allocate(sz * 2);
             readBuf.flip();
             Utils.copy(readBuf, newb);
             readBuf = newb;
@@ -300,7 +310,7 @@
             if (readBuf.remaining() > TARGET_BUFSIZE) {
                 if (debugr.on())
                     debugr.log("readBuf has more than TARGET_BUFSIZE: %d",
-                               readBuf.remaining());
+                            readBuf.remaining());
                 return 0;
             } else {
                 return super.upstreamWindowUpdate(currentWindow, downstreamQsize);
@@ -309,6 +319,7 @@
 
         // readBuf is kept ready for reading outside of this method
         private void addToReadBuf(List<ByteBuffer> buffers, boolean complete) {
+            assert Utils.remaining(buffers) > 0 || buffers.isEmpty();
             synchronized (readBufferLock) {
                 for (ByteBuffer buf : buffers) {
                     readBuf.compact();
@@ -344,14 +355,15 @@
         // In this case we need to wait for more bytes than what
         // we had before calling unwrap() again.
         volatile int minBytesRequired;
+
         // work function where it all happens
         final void processData() {
             try {
                 if (debugr.on())
                     debugr.log("processData:"
-                           + " readBuf remaining:" + readBuf.remaining()
-                           + ", state:" + states(handshakeState)
-                           + ", engine handshake status:" + engine.getHandshakeStatus());
+                            + " readBuf remaining:" + readBuf.remaining()
+                            + ", state:" + states(handshakeState)
+                            + ", engine handshake status:" + engine.getHandshakeStatus());
                 int len;
                 boolean complete = false;
                 while (readBuf.remaining() > (len = minBytesRequired)) {
@@ -400,14 +412,13 @@
                             outgoing(Utils.EMPTY_BB_LIST, true);
                             return;
                         }
-                        if (result.handshaking() && !complete) {
+                        if (result.handshaking()) {
+                            handshaking = true;
                             if (debugr.on()) debugr.log("handshaking");
-                            if (doHandshake(result, READER)) {
-                                resumeActivity();
-                            }
-                            handshaking = true;
+                            if (doHandshake(result, READER)) continue; // need unwrap
+                            else break; // doHandshake will have triggered the write scheduler if necessary
                         } else {
-                            if ((handshakeState.getAndSet(NOT_HANDSHAKING)& ~DOING_TASKS) == HANDSHAKING) {
+                            if ((handshakeState.getAndSet(NOT_HANDSHAKING) & ~DOING_TASKS) == HANDSHAKING) {
                                 handshaking = false;
                                 applicationBufferSize = engine.getSession().getApplicationBufferSize();
                                 packetBufferSize = engine.getSession().getPacketBufferSize();
@@ -443,12 +454,19 @@
 
         EngineResult unwrapBuffer(ByteBuffer src) throws IOException {
             ByteBuffer dst = getAppBuffer();
+            int len = src.remaining();
             while (true) {
                 SSLEngineResult sslResult = engine.unwrap(src, dst);
                 switch (sslResult.getStatus()) {
                     case BUFFER_OVERFLOW:
-                        // may happen only if app size buffer was changed.
-                        // get it again if app buffer size changed
+                        // may happen if app size buffer was changed, or if
+                        // our 'adaptiveBufferSize' guess was too small for
+                        // the current payload. In that case, update the
+                        // value of applicationBufferSize, and allocate a
+                        // buffer of that size, which we are sure will be
+                        // big enough to decode whatever needs to be
+                        // decoded. We will later update adaptiveBufferSize
+                        // in OK: below.
                         int appSize = applicationBufferSize =
                                 engine.getSession().getApplicationBufferSize();
                         ByteBuffer b = ByteBuffer.allocate(appSize + dst.position());
@@ -457,11 +475,26 @@
                         dst = b;
                         break;
                     case CLOSED:
+                        assert dst.position() == 0;
                         return doClosure(new EngineResult(sslResult));
                     case BUFFER_UNDERFLOW:
                         // handled implicitly by compaction/reallocation of readBuf
+                        assert dst.position() == 0;
                         return new EngineResult(sslResult);
                     case OK:
+                        int size = dst.position();
+                        if (debug.on()) {
+                            debugr.log("Decoded " + size + " bytes out of " + len
+                                    + " into buffer of " + dst.capacity()
+                                    + " remaining to decode: " + src.remaining());
+                        }
+                        // if the record payload was bigger than what was originally
+                        // allocated, then sets the adaptiveAppBufferSize to size
+                        // and we will use that new size as a guess for the next app
+                        // buffer.
+                        if (size > adaptiveAppBufferSize) {
+                            adaptiveAppBufferSize = ((size + 7) >>> 3) << 3;
+                        }
                         dst.flip();
                         return new EngineResult(sslResult, dst);
                 }
@@ -662,8 +695,8 @@
                     }
                     cleanList(writeList); // tidy up the source list
                     sendResultBytes(result);
-                    if (handshaking && !completing) {
-                        if (needWrap()) {
+                    if (handshaking) {
+                        if (!completing && needWrap()) {
                             continue;
                         } else {
                             return;
@@ -687,11 +720,30 @@
             }
         }
 
+        // The SSLEngine insists on being given a buffer that is at least
+        // SSLSession.getPacketBufferSize() long (usually 16K). If given
+        // a smaller buffer it will go in BUFFER_OVERFLOW, even if it only
+        // has 6 bytes to wrap. Typical usage shows that for GET we
+        // usually produce an average of ~ 100 bytes.
+        // To avoid wasting space, and because allocating and zeroing
+        // 16K buffers for encoding 6 bytes is costly, we are reusing the
+        // same writeBuffer to interact with SSLEngine.wrap().
+        // If the SSLEngine produces less than writeBuffer.capacity() / 2,
+        // then we copy off the bytes to a smaller buffer that we send
+        // downstream. Otherwise, we send the writeBuffer downstream
+        // and will allocate a new one next time.
+        volatile ByteBuffer writeBuffer;
         @SuppressWarnings("fallthrough")
         EngineResult wrapBuffers(ByteBuffer[] src) throws SSLException {
+            long len = Utils.remaining(src);
             if (debugw.on())
-                debugw.log("wrapping " + Utils.remaining(src) + " bytes");
-            ByteBuffer dst = getNetBuffer();
+                debugw.log("wrapping " + len + " bytes");
+
+            ByteBuffer dst = writeBuffer;
+            if (dst == null) dst = writeBuffer = getNetBuffer();
+            assert dst.position() == 0 : "buffer position is " + dst.position();
+            assert dst.hasRemaining() : "buffer has no remaining space: capacity=" + dst.capacity();
+
             while (true) {
                 SSLEngineResult sslResult = engine.wrap(src, dst);
                 if (debugw.on()) debugw.log("SSLResult: " + sslResult);
@@ -702,7 +754,7 @@
                         if (debugw.on()) debugw.log("BUFFER_OVERFLOW");
                         int netSize = packetBufferSize
                                 = engine.getSession().getPacketBufferSize();
-                        ByteBuffer b = ByteBuffer.allocate(netSize + dst.position());
+                        ByteBuffer b = writeBuffer = ByteBuffer.allocate(netSize + dst.position());
                         dst.flip();
                         b.put(dst);
                         dst = b;
@@ -712,11 +764,27 @@
                         // fallthrough. There could be some remaining data in dst.
                         // CLOSED will be handled by the caller.
                     case OK:
-                        dst.flip();
-                        final ByteBuffer dest = dst;
+                        final ByteBuffer dest;
+                        if (dst.position() == 0) {
+                            dest = NOTHING; // can happen if handshake is in progress
+                        } else if (dst.position() < dst.capacity() / 2) {
+                            // less than half the buffer was used.
+                            // copy off the bytes to a smaller buffer, and keep
+                            // the writeBuffer for next time.
+                            dst.flip();
+                            dest = Utils.copyAligned(dst);
+                            dst.clear();
+                        } else {
+                            // more than half the buffer was used.
+                            // just send that buffer downstream, and we will
+                            // get a new writeBuffer next time it is needed.
+                            dst.flip();
+                            dest = dst;
+                            writeBuffer = null;
+                        }
                         if (debugw.on())
-                            debugw.log("OK => produced: %d, not wrapped: %d",
-                                       dest.remaining(),  Utils.remaining(src));
+                            debugw.log("OK => produced: %d bytes into %d, not wrapped: %d",
+                                       dest.remaining(),  dest.capacity(), Utils.remaining(src));
                         return new EngineResult(sslResult, dest);
                     case BUFFER_UNDERFLOW:
                         // Shouldn't happen.  Doesn't returns when wrap()
@@ -799,8 +867,12 @@
     private static final int NOT_HANDSHAKING = 0;
     private static final int HANDSHAKING = 1;
 
-    private static final int DOING_TASKS = 4; // bit added to above state
-    private static final ByteBuffer HS_TRIGGER = ByteBuffer.allocate(0);
+    // Bit flags
+    // a thread is currently executing tasks
+    private static final int DOING_TASKS = 4;
+    // a thread wants to execute tasks, while another thread is executing
+    private static final int REQUESTING_TASKS = 8;
+    private static final int TASK_BITS = 12; // Both bits
 
     private static final int READER = 1;
     private static final int WRITER = 2;
@@ -808,7 +880,7 @@
     private static String states(AtomicInteger state) {
         int s = state.get();
         StringBuilder sb = new StringBuilder();
-        int x = s & ~DOING_TASKS;
+        int x = s & ~TASK_BITS;
         switch (x) {
             case NOT_HANDSHAKING:
                 sb.append(" NOT_HANDSHAKING ");
@@ -821,6 +893,8 @@
         }
         if ((s & DOING_TASKS) > 0)
             sb.append("|DOING_TASKS");
+        if ((s & REQUESTING_TASKS) > 0)
+            sb.append("|REQUESTING_TASKS");
         return sb.toString();
     }
 
@@ -833,18 +907,37 @@
     final ConcurrentLinkedQueue<String> stateList =
             debug.on() ? new ConcurrentLinkedQueue<>() : null;
 
+    // Atomically executed to update task bits. Sets either DOING_TASKS or REQUESTING_TASKS
+    // depending on previous value
+    private static final IntBinaryOperator REQUEST_OR_DO_TASKS = (current, ignored) -> {
+        if ((current & DOING_TASKS) == 0)
+            return DOING_TASKS | (current & HANDSHAKING);
+        else
+            return DOING_TASKS | REQUESTING_TASKS | (current & HANDSHAKING);
+    };
+
+    // Atomically executed to update task bits. Sets DOING_TASKS if REQUESTING was set
+    // clears bits if not.
+    private static final IntBinaryOperator FINISH_OR_DO_TASKS = (current, ignored) -> {
+        if ((current & REQUESTING_TASKS) != 0)
+            return DOING_TASKS | (current & HANDSHAKING);
+        // clear both bits
+        return (current & HANDSHAKING);
+    };
+
     private boolean doHandshake(EngineResult r, int caller) {
-        // unconditionally sets the HANDSHAKING bit, while preserving DOING_TASKS
-        handshakeState.getAndAccumulate(HANDSHAKING, (current, update) -> update | (current & DOING_TASKS));
+        // unconditionally sets the HANDSHAKING bit, while preserving task bits
+        handshakeState.getAndAccumulate(0, (current, unused) -> HANDSHAKING | (current & TASK_BITS));
         if (stateList != null && debug.on()) {
             stateList.add(r.handshakeStatus().toString());
             stateList.add(Integer.toString(caller));
         }
         switch (r.handshakeStatus()) {
             case NEED_TASK:
-                int s = handshakeState.getAndUpdate((current) -> current | DOING_TASKS);
-                if ((s & DOING_TASKS) > 0) // someone else was doing tasks
+                int s = handshakeState.accumulateAndGet(0, REQUEST_OR_DO_TASKS);
+                if ((s & REQUESTING_TASKS) > 0) { // someone else is or will do tasks
                     return false;
+                }
 
                 if (debug.on()) debug.log("obtaining and initiating task execution");
                 List<Runnable> tasks = obtainTasks();
@@ -878,20 +971,25 @@
     }
 
     private void executeTasks(List<Runnable> tasks) {
-        if (tasks.isEmpty())
-            return;
         exec.execute(() -> {
             try {
                 List<Runnable> nextTasks = tasks;
+                if (debug.on()) debug.log("#tasks to execute: " + Integer.toString(nextTasks.size()));
                 do {
                     nextTasks.forEach(Runnable::run);
                     if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                         nextTasks = obtainTasks();
                     } else {
+                        int s = handshakeState.accumulateAndGet(0, FINISH_OR_DO_TASKS);
+                        if ((s & DOING_TASKS) != 0) {
+                            if (debug.on()) debug.log("re-running tasks (B)");
+                            nextTasks = obtainTasks();
+                            continue;
+                        }
                         break;
                     }
                 } while (true);
-                handshakeState.getAndUpdate((current) -> current & ~DOING_TASKS);
+                if (debug.on()) debug.log("finished task execution");
                 resumeActivity();
             } catch (Throwable t) {
                 handleError(t);
@@ -997,6 +1095,8 @@
         }
     }
 
+    // The maximum network buffer size negotiated during
+    // the handshake. Usually 16K.
     volatile int packetBufferSize;
     final ByteBuffer getNetBuffer() {
         int netSize = packetBufferSize;
@@ -1006,13 +1106,32 @@
         return ByteBuffer.allocate(netSize);
     }
 
+    // The maximum application buffer size negotiated during
+    // the handshake. Usually close to 16K.
     volatile int applicationBufferSize;
+    // Despite of the maximum applicationBufferSize negotiated
+    // above, TLS records usually have a much smaller payload.
+    // The adaptativeAppBufferSize records the max payload
+    // ever decoded, and we use that as a guess for how big
+    // a buffer we will need for the next payload.
+    // This avoids allocating and zeroing a 16K buffer for
+    // nothing...
+    volatile int adaptiveAppBufferSize;
     final ByteBuffer getAppBuffer() {
         int appSize = applicationBufferSize;
         if (appSize <= 0) {
-            applicationBufferSize = appSize = engine.getSession().getApplicationBufferSize();
+            applicationBufferSize = appSize
+                    = engine.getSession().getApplicationBufferSize();
         }
-        return ByteBuffer.allocate(appSize);
+        int size = adaptiveAppBufferSize;
+        if (size <= 0) {
+            size = 512; // start with 512 this is usually enough for handshaking / headers
+        } else if (size > appSize) {
+            size = appSize;
+        }
+        // will cause a BUFFER_OVERFLOW if not big enough, but
+        // that's OK.
+        return ByteBuffer.allocate(size);
     }
 
     final String dbgString() {
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/SSLTube.java	Thu Jun 21 09:53:50 2018 -0700
@@ -309,7 +309,7 @@
             synchronized (this) {
                 previous = pendingDelegate.getAndSet(delegateWrapper);
                 subscription = readSubscription;
-                handleNow = this.errorRef.get() != null || finished;
+                handleNow = this.errorRef.get() != null || onCompleteReceived;
             }
             if (previous != null) {
                 previous.dropSubscription();
@@ -424,12 +424,20 @@
             // if onError is invoked concurrently with setDelegate.
             synchronized (this) {
                 failed = this.errorRef.get();
-                completed = finished;
+                completed = onCompleteReceived;
                 subscribed = subscriberImpl;
             }
+
             if (failed != null) {
+                if (debug.on())
+                    debug.log("onNewSubscription: subscriberImpl:%s, invoking onError:%s",
+                              subscriberImpl, failed);
                 subscriberImpl.onError(failed);
             } else if (completed) {
+                if (debug.on())
+                    debug.log("onNewSubscription: subscriberImpl:%s, invoking onCompleted",
+                              subscriberImpl);
+                finished = true;
                 subscriberImpl.onComplete();
             }
         }
@@ -490,7 +498,6 @@
         @Override
         public void onComplete() {
             assert !finished && !onCompleteReceived;
-            onCompleteReceived = true;
             DelegateWrapper subscriberImpl;
             synchronized(this) {
                 subscriberImpl = subscribed;
@@ -505,8 +512,10 @@
                 onErrorImpl(new SSLHandshakeException(
                         "Remote host terminated the handshake"));
             } else if (subscriberImpl != null) {
-                finished = true;
+                onCompleteReceived = finished = true;
                 subscriberImpl.onComplete();
+            } else {
+                onCompleteReceived = true;
             }
             // now if we have any pending subscriber, we should complete
             // them immediately as the read scheduler will already be stopped.
@@ -528,12 +537,17 @@
     final class SSLSubscriptionWrapper implements Flow.Subscription {
 
         volatile Flow.Subscription delegate;
+        private volatile boolean cancelled;
 
         void setSubscription(Flow.Subscription sub) {
             long demand = writeDemand.get(); // FIXME: isn't it a racy way of passing the demand?
             delegate = sub;
-            if (debug.on()) debug.log("setSubscription: demand=%d", demand);
-            if (demand > 0)
+            if (debug.on())
+                debug.log("setSubscription: demand=%d, cancelled:%s", demand, cancelled);
+
+            if (cancelled)
+                delegate.cancel();
+            else if (demand > 0)
                 sub.request(demand);
         }
 
@@ -549,7 +563,9 @@
 
         @Override
         public void cancel() {
-            // TODO:  no-op or error?
+            cancelled = true;
+            if (delegate != null)
+                delegate.cancel();
         }
     }
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/SubscriberWrapper.java	Thu Jun 21 09:53:50 2018 -0700
@@ -260,6 +260,8 @@
             try {
                 run1();
             } catch (Throwable t) {
+                if (debug.on())
+                    debug.log("DownstreamPusher threw: " + t);
                 errorCommon(t);
             }
         }
@@ -292,6 +294,7 @@
                 pushScheduler.stop();
                 outputQ.clear();
                 downstreamSubscriber.onError(error);
+                cf.completeExceptionally(error);
                 return;
             }
 
@@ -383,9 +386,8 @@
                 (throwable = new AssertionError("null throwable")) != null;
         if (errorRef.compareAndSet(null, throwable)) {
             if (debug.on()) debug.log("error", throwable);
+            upstreamCompleted = true;
             pushScheduler.runOrSchedule();
-            upstreamCompleted = true;
-            cf.completeExceptionally(throwable);
             return true;
         }
         return false;
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java	Thu Jun 21 09:53:50 2018 -0700
@@ -30,19 +30,23 @@
 import sun.net.www.HeaderParser;
 
 import javax.net.ssl.ExtendedSSLSession;
+import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSession;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.io.UncheckedIOException;
 import java.io.UnsupportedEncodingException;
 import java.lang.System.Logger.Level;
+import java.net.ConnectException;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.net.URLPermission;
 import java.net.http.HttpHeaders;
+import java.net.http.HttpTimeoutException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharacterCodingException;
@@ -58,9 +62,11 @@
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionException;
 import java.util.concurrent.ExecutionException;
 import java.util.function.BiPredicate;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -119,6 +125,8 @@
             "jdk.httpclient.bufsize", DEFAULT_BUFSIZE
     );
 
+    public static final BiPredicate<String,String> ACCEPT_ALL = (x,y) -> true;
+
     private static final Set<String> DISALLOWED_HEADERS_SET;
 
     static {
@@ -131,24 +139,21 @@
         DISALLOWED_HEADERS_SET = Collections.unmodifiableSet(treeSet);
     }
 
-    public static final Predicate<String>
-            ALLOWED_HEADERS = header -> !DISALLOWED_HEADERS_SET.contains(header);
+    public static final BiPredicate<String, String>
+            ALLOWED_HEADERS = (header, unused) -> !DISALLOWED_HEADERS_SET.contains(header);
 
-    public static final BiPredicate<String, List<String>> VALIDATE_USER_HEADER =
-            (name, lv) -> {
-                requireNonNull(name, "header name");
-                requireNonNull(lv, "header values");
+    public static final BiPredicate<String, String> VALIDATE_USER_HEADER =
+            (name, value) -> {
+                assert name != null : "null header name";
+                assert value != null : "null header value";
                 if (!isValidName(name)) {
                     throw newIAE("invalid header name: \"%s\"", name);
                 }
-                if (!Utils.ALLOWED_HEADERS.test(name)) {
+                if (!Utils.ALLOWED_HEADERS.test(name, null)) {
                     throw newIAE("restricted header name: \"%s\"", name);
                 }
-                for (String value : lv) {
-                    requireNonNull(value, "header value");
-                    if (!isValidValue(value)) {
-                        throw newIAE("invalid header value for %s: \"%s\"", name, value);
-                    }
+                if (!isValidValue(value)) {
+                    throw newIAE("invalid header value for %s: \"%s\"", name, value);
                 }
                 return true;
             };
@@ -180,9 +185,20 @@
                                 .collect(Collectors.toUnmodifiableSet());
     }
 
+    public static <T> CompletableFuture<T> wrapForDebug(Logger logger, String name, CompletableFuture<T> cf) {
+        if (logger.on()) {
+            return cf.handle((r,t) -> {
+                logger.log("%s completed %s", name, t == null ? "successfully" : t );
+                return cf;
+            }).thenCompose(Function.identity());
+        } else {
+            return cf;
+        }
+    }
+
     private static final String WSPACES = " \t\r\n";
     private static final boolean isAllowedForProxy(String name,
-                                                   List<String> value,
+                                                   String value,
                                                    Set<String> disabledSchemes,
                                                    Predicate<String> allowedKeys) {
         if (!allowedKeys.test(name)) return false;
@@ -191,21 +207,19 @@
             if (value.isEmpty()) return false;
             for (String scheme : disabledSchemes) {
                 int slen = scheme.length();
-                for (String v : value) {
-                    int vlen = v.length();
-                    if (vlen == slen) {
-                        if (v.equalsIgnoreCase(scheme)) {
+                int vlen = value.length();
+                if (vlen == slen) {
+                    if (value.equalsIgnoreCase(scheme)) {
+                        return false;
+                    }
+                } else if (vlen > slen) {
+                    if (value.substring(0,slen).equalsIgnoreCase(scheme)) {
+                        int c = value.codePointAt(slen);
+                        if (WSPACES.indexOf(c) > -1
+                                || Character.isSpaceChar(c)
+                                || Character.isWhitespace(c)) {
                             return false;
                         }
-                    } else if (vlen > slen) {
-                        if (v.substring(0,slen).equalsIgnoreCase(scheme)) {
-                            int c = v.codePointAt(slen);
-                            if (WSPACES.indexOf(c) > -1
-                                    || Character.isSpaceChar(c)
-                                    || Character.isWhitespace(c)) {
-                                return false;
-                            }
-                        }
                     }
                 }
             }
@@ -213,13 +227,13 @@
         return true;
     }
 
-    public static final BiPredicate<String, List<String>> PROXY_TUNNEL_FILTER =
+    public static final BiPredicate<String, String> PROXY_TUNNEL_FILTER =
             (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_TUNNEL_DISABLED_SCHEMES,
                     IS_PROXY_HEADER);
-    public static final BiPredicate<String, List<String>> PROXY_FILTER =
+    public static final BiPredicate<String, String> PROXY_FILTER =
             (s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_DISABLED_SCHEMES,
                     ALL_HEADERS);
-    public static final BiPredicate<String, List<String>> NO_PROXY_HEADERS_FILTER =
+    public static final BiPredicate<String, String> NO_PROXY_HEADERS_FILTER =
             (n,v) -> Utils.NO_PROXY_HEADER.test(n);
 
 
@@ -256,6 +270,35 @@
         return new IOException(t);
     }
 
+    /**
+     * Adds a more specific exception detail message, based on the given
+     * exception type and the message supplier. This is primarily to present
+     * more descriptive messages in IOExceptions that may be visible to calling
+     * code.
+     *
+     * @return a possibly new exception that has as its detail message, the
+     *         message from the messageSupplier, and the given throwable as its
+     *         cause. Otherwise returns the given throwable
+     */
+    public static Throwable wrapWithExtraDetail(Throwable t,
+                                                Supplier<String> messageSupplier) {
+        if (!(t instanceof IOException))
+            return t;
+
+        String msg = messageSupplier.get();
+        if (msg == null)
+            return t;
+
+        if (t instanceof ConnectionExpiredException) {
+            IOException ioe = new IOException(msg, t.getCause());
+            t = new ConnectionExpiredException(ioe);
+        } else {
+            IOException ioe = new IOException(msg, t);
+            t = ioe;
+        }
+        return t;
+    }
+
     private Utils() { }
 
     /**
@@ -534,6 +577,16 @@
         return dst;
     }
 
+    public static ByteBuffer copyAligned(ByteBuffer src) {
+        int len = src.remaining();
+        int size = ((len + 7) >> 3) << 3;
+        assert size >= len;
+        ByteBuffer dst = ByteBuffer.allocate(size);
+        dst.put(src);
+        dst.flip();
+        return dst;
+    }
+
     public static String dump(Object... objects) {
         return Arrays.toString(objects);
     }
@@ -901,6 +954,20 @@
         return address;
     }
 
+    public static Throwable toConnectException(Throwable e) {
+        if (e == null) return null;
+        e = getCompletionCause(e);
+        if (e instanceof ConnectException) return e;
+        if (e instanceof SecurityException) return e;
+        if (e instanceof SSLException) return e;
+        if (e instanceof Error) return e;
+        if (e instanceof HttpTimeoutException) return e;
+        Throwable cause = e;
+        e = new ConnectException(e.getMessage());
+        e.initCause(cause);
+        return e;
+    }
+
     /**
      * Returns the smallest (closest to zero) positive number {@code m} (which
      * is also a power of 2) such that {@code n <= m}.
--- a/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/frame/SettingsFrame.java	Thu Jun 21 09:53:50 2018 -0700
@@ -110,14 +110,14 @@
         return TYPE;
     }
 
-    public int getParameter(int paramID) {
+    public synchronized int getParameter(int paramID) {
         if (paramID > MAX_PARAM) {
             throw new IllegalArgumentException("illegal parameter");
         }
         return parameters[paramID - 1];
     }
 
-    public SettingsFrame setParameter(int paramID, int value) {
+    public synchronized SettingsFrame setParameter(int paramID, int value) {
         if (paramID > MAX_PARAM) {
             throw new IllegalArgumentException("illegal parameter");
         }
@@ -166,7 +166,7 @@
         // TODO: check these values
         f.setParameter(ENABLE_PUSH, 1);
         f.setParameter(HEADER_TABLE_SIZE, 4 * K);
-        f.setParameter(MAX_CONCURRENT_STREAMS, 35);
+        f.setParameter(MAX_CONCURRENT_STREAMS, 100);
         f.setParameter(INITIAL_WINDOW_SIZE, 64 * K - 1);
         f.setParameter(MAX_FRAME_SIZE, 16 * K);
         return f;
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Decoder.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Decoder.java	Thu Jun 21 09:53:50 2018 -0700
@@ -28,6 +28,7 @@
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
 
 import static jdk.internal.net.http.hpack.HPACK.Logger.Level.EXTRA;
@@ -66,7 +67,8 @@
     private final Logger logger;
     private static final AtomicLong DECODERS_IDS = new AtomicLong();
 
-    private static final State[] states = new State[256];
+    /* An immutable list of states */
+    private static final List<State> states;
 
     static {
         // To be able to do a quick lookup, each of 256 possibilities are mapped
@@ -78,21 +80,23 @@
         // I do it mainly for better debugging (to not go each time step by step
         // through if...else tree). As for performance win for the decoding, I
         // believe is negligible.
-        for (int i = 0; i < states.length; i++) {
+        State[] s = new State[256];
+        for (int i = 0; i < s.length; i++) {
             if ((i & 0b1000_0000) == 0b1000_0000) {
-                states[i] = State.INDEXED;
+                s[i] = State.INDEXED;
             } else if ((i & 0b1100_0000) == 0b0100_0000) {
-                states[i] = State.LITERAL_WITH_INDEXING;
+                s[i] = State.LITERAL_WITH_INDEXING;
             } else if ((i & 0b1110_0000) == 0b0010_0000) {
-                states[i] = State.SIZE_UPDATE;
+                s[i] = State.SIZE_UPDATE;
             } else if ((i & 0b1111_0000) == 0b0001_0000) {
-                states[i] = State.LITERAL_NEVER_INDEXED;
+                s[i] = State.LITERAL_NEVER_INDEXED;
             } else if ((i & 0b1111_0000) == 0b0000_0000) {
-                states[i] = State.LITERAL;
+                s[i] = State.LITERAL;
             } else {
                 throw new InternalError(String.valueOf(i));
             }
         }
+        states = List.of(s);
     }
 
     private final long id;
@@ -278,7 +282,7 @@
 
     private void resumeReady(ByteBuffer input) {
         int b = input.get(input.position()) & 0xff; // absolute read
-        State s = states[b];
+        State s = states.get(b);
         if (logger.isLoggable(EXTRA)) {
             logger.log(EXTRA, () -> format("next binary representation %s (first byte 0x%02x)",
                                            s, b));
@@ -388,15 +392,17 @@
         try {
             if (firstValueIndex) {
                 if (logger.isLoggable(NORMAL)) {
-                    logger.log(NORMAL, () -> format("literal without indexing ('%s', '%s')",
-                                                    intValue, value));
+                    logger.log(NORMAL, () -> format(
+                            "literal without indexing (%s, '%s', huffman=%b)",
+                            intValue, value, valueHuffmanEncoded));
                 }
                 SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue);
                 action.onLiteral(intValue, f.name, value, valueHuffmanEncoded);
             } else {
                 if (logger.isLoggable(NORMAL)) {
-                    logger.log(NORMAL, () -> format("literal without indexing ('%s', '%s')",
-                                                    name, value));
+                    logger.log(NORMAL, () -> format(
+                            "literal without indexing ('%s', huffman=%b, '%s', huffman=%b)",
+                            name, nameHuffmanEncoded, value, valueHuffmanEncoded));
                 }
                 action.onLiteral(name, nameHuffmanEncoded, value, valueHuffmanEncoded);
             }
@@ -445,8 +451,9 @@
             String v = value.toString();
             if (firstValueIndex) {
                 if (logger.isLoggable(NORMAL)) {
-                    logger.log(NORMAL, () -> format("literal with incremental indexing ('%s', '%s')",
-                                                    intValue, value));
+                    logger.log(NORMAL, () -> format(
+                            "literal with incremental indexing (%s, '%s', huffman=%b)",
+                            intValue, value, valueHuffmanEncoded));
                 }
                 SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue);
                 n = f.name;
@@ -454,8 +461,9 @@
             } else {
                 n = name.toString();
                 if (logger.isLoggable(NORMAL)) {
-                    logger.log(NORMAL, () -> format("literal with incremental indexing ('%s', '%s')",
-                                                    n, value));
+                    logger.log(NORMAL, () -> format(
+                            "literal with incremental indexing ('%s', huffman=%b, '%s', huffman=%b)",
+                            n, nameHuffmanEncoded, value, valueHuffmanEncoded));
                 }
                 action.onLiteralWithIndexing(n, nameHuffmanEncoded, v, valueHuffmanEncoded);
             }
@@ -496,15 +504,17 @@
         try {
             if (firstValueIndex) {
                 if (logger.isLoggable(NORMAL)) {
-                    logger.log(NORMAL, () -> format("literal never indexed ('%s', '%s')",
-                                                    intValue, value));
+                    logger.log(NORMAL, () -> format(
+                            "literal never indexed (%s, '%s', huffman=%b)",
+                            intValue, value, valueHuffmanEncoded));
                 }
                 SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue);
                 action.onLiteralNeverIndexed(intValue, f.name, value, valueHuffmanEncoded);
             } else {
                 if (logger.isLoggable(NORMAL)) {
-                    logger.log(NORMAL, () -> format("literal never indexed ('%s', '%s')",
-                                                    name, value));
+                    logger.log(NORMAL, () -> format(
+                            "literal never indexed ('%s', huffman=%b, '%s', huffman=%b)",
+                            name, nameHuffmanEncoded, value, valueHuffmanEncoded));
                 }
                 action.onLiteralNeverIndexed(name, nameHuffmanEncoded, value, valueHuffmanEncoded);
             }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Encoder.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Encoder.java	Thu Jun 21 09:53:50 2018 -0700
@@ -105,8 +105,8 @@
 
     private static final AtomicLong ENCODERS_IDS = new AtomicLong();
 
-    // TODO: enum: no huffman/smart huffman/always huffman
-    private static final boolean DEFAULT_HUFFMAN = true;
+    /* Used to calculate the number of bytes required for Huffman encoding */
+    private final QuickHuffman.Writer huffmanWriter = new QuickHuffman.Writer();
 
     private final Logger logger;
     private final long id;
@@ -241,21 +241,30 @@
         int index = t.indexOf(name, value);
         if (index > 0) {
             indexed(index);
-        } else if (index < 0) {
-            if (sensitive) {
-                literalNeverIndexed(-index, value, DEFAULT_HUFFMAN);
+        } else {
+            boolean huffmanValue = isHuffmanBetterFor(value);
+            if (index < 0) {
+                if (sensitive) {
+                    literalNeverIndexed(-index, value, huffmanValue);
+                } else {
+                    literal(-index, value, huffmanValue);
+                }
             } else {
-                literal(-index, value, DEFAULT_HUFFMAN);
-            }
-        } else {
-            if (sensitive) {
-                literalNeverIndexed(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN);
-            } else {
-                literal(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN);
+                boolean huffmanName = isHuffmanBetterFor(name);
+                if (sensitive) {
+                    literalNeverIndexed(name, huffmanName, value, huffmanValue);
+                } else {
+                    literal(name, huffmanName, value, huffmanValue);
+                }
             }
         }
     }
 
+    private boolean isHuffmanBetterFor(CharSequence value) {
+        // prefer Huffman encoding only if it is strictly smaller than Latin-1
+        return huffmanWriter.lengthOf(value) < value.length();
+    }
+
     /**
      * Sets a maximum capacity of the header table.
      *
@@ -299,7 +308,7 @@
         if (calculated < 0 || calculated > capacity) {
             throw new IllegalArgumentException(
                     format("0 <= calculated <= capacity: calculated=%s, capacity=%s",
-                            calculated, capacity));
+                           calculated, capacity));
         }
         capacityUpdate = true;
         // maxCapacity needs to be updated unconditionally, so the encoder
@@ -416,8 +425,9 @@
                                  boolean useHuffman)
             throws IndexOutOfBoundsException {
         if (logger.isLoggable(EXTRA)) {
-            logger.log(EXTRA, () -> format("literal without indexing ('%s', '%s')",
-                                           index, value));
+            logger.log(EXTRA, () -> format(
+                    "literal without indexing (%s, '%s', huffman=%b)",
+                    index, value, useHuffman));
         }
         checkEncoding();
         encoding = true;
@@ -428,10 +438,12 @@
     protected final void literal(CharSequence name,
                                  boolean nameHuffman,
                                  CharSequence value,
-                                 boolean valueHuffman) {
+                                 boolean valueHuffman)
+    {
         if (logger.isLoggable(EXTRA)) {
-            logger.log(EXTRA, () -> format("literal without indexing ('%s', '%s')",
-                                           name, value));
+            logger.log(EXTRA, () -> format(
+                    "literal without indexing ('%s', huffman=%b, '%s', huffman=%b)",
+                    name, nameHuffman, value, valueHuffman));
         }
         checkEncoding();
         encoding = true;
@@ -442,10 +454,12 @@
     protected final void literalNeverIndexed(int index,
                                              CharSequence value,
                                              boolean valueHuffman)
-            throws IndexOutOfBoundsException {
+            throws IndexOutOfBoundsException
+    {
         if (logger.isLoggable(EXTRA)) {
-            logger.log(EXTRA, () -> format("literal never indexed ('%s', '%s')",
-                                           index, value));
+            logger.log(EXTRA, () -> format(
+                    "literal never indexed (%s, '%s', huffman=%b)",
+                    index, value, valueHuffman));
         }
         checkEncoding();
         encoding = true;
@@ -458,8 +472,9 @@
                                              CharSequence value,
                                              boolean valueHuffman) {
         if (logger.isLoggable(EXTRA)) {
-            logger.log(EXTRA, () -> format("literal never indexed ('%s', '%s')",
-                                           name, value));
+            logger.log(EXTRA, () -> format(
+                    "literal never indexed ('%s', huffman=%b, '%s', huffman=%b)",
+                    name, nameHuffman, value, valueHuffman));
         }
         checkEncoding();
         encoding = true;
@@ -472,8 +487,9 @@
                                              boolean valueHuffman)
             throws IndexOutOfBoundsException {
         if (logger.isLoggable(EXTRA)) {
-            logger.log(EXTRA, () -> format("literal with incremental indexing ('%s', '%s')",
-                                           index, value));
+            logger.log(EXTRA, () -> format(
+                    "literal with incremental indexing (%s, '%s', huffman=%b)",
+                    index, value, valueHuffman));
         }
         checkEncoding();
         encoding = true;
@@ -485,9 +501,10 @@
                                              boolean nameHuffman,
                                              CharSequence value,
                                              boolean valueHuffman) {
-        if (logger.isLoggable(EXTRA)) { // TODO: include huffman info?
-            logger.log(EXTRA, () -> format("literal with incremental indexing ('%s', '%s')",
-                                           name, value));
+        if (logger.isLoggable(EXTRA)) {
+            logger.log(EXTRA, () -> format(
+                    "literal with incremental indexing ('%s', huffman=%b, '%s', huffman=%b)",
+                    name, nameHuffman, value, valueHuffman));
         }
         checkEncoding();
         encoding = true;
@@ -506,7 +523,7 @@
         if (capacity > this.maxCapacity) {
             throw new IllegalArgumentException(
                     format("capacity <= maxCapacity: capacity=%s, maxCapacity=%s",
-                            capacity, maxCapacity));
+                           capacity, maxCapacity));
         }
         writer = sizeUpdateWriter.maxHeaderTableSize(capacity);
     }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java	Thu Jun 21 09:53:50 2018 -0700
@@ -27,6 +27,7 @@
 import jdk.internal.net.http.common.Utils;
 import jdk.internal.net.http.hpack.HPACK.Logger.Level;
 
+import java.nio.ByteBuffer;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Map;
@@ -171,4 +172,124 @@
         }
 
     }
+
+    // -- low-level utilities --
+
+    @FunctionalInterface
+    interface BufferUpdateConsumer {
+        void accept(long data, int len);
+    }
+
+    @SuppressWarnings("fallthrough")
+    public static int read(ByteBuffer source,
+                           long buffer,
+                           int bufferLen,
+                           BufferUpdateConsumer consumer)
+    {
+        // read as much as possible (up to 8 bytes)
+        int nBytes = Math.min((64 - bufferLen) >> 3, source.remaining());
+        switch (nBytes) {
+            case 0:
+                break;
+            case 3:
+                buffer |= ((source.get() & 0x00000000000000ffL) << (56 - bufferLen));
+                bufferLen += 8;
+            case 2:
+                buffer |= ((source.get() & 0x00000000000000ffL) << (56 - bufferLen));
+                bufferLen += 8;
+            case 1:
+                buffer |= ((source.get() & 0x00000000000000ffL) << (56 - bufferLen));
+                bufferLen += 8;
+                consumer.accept(buffer, bufferLen);
+                break;
+            case 7:
+                buffer |= ((source.get() & 0x00000000000000ffL) << (56 - bufferLen));
+                bufferLen += 8;
+            case 6:
+                buffer |= ((source.get() & 0x00000000000000ffL) << (56 - bufferLen));
+                bufferLen += 8;
+            case 5:
+                buffer |= ((source.get() & 0x00000000000000ffL) << (56 - bufferLen));
+                bufferLen += 8;
+            case 4:
+                buffer |= ((source.getInt() & 0x00000000ffffffffL) << (32 - bufferLen));
+                bufferLen += 32;
+                consumer.accept(buffer, bufferLen);
+                break;
+            case 8:
+                buffer = source.getLong();
+                bufferLen = 64;
+                consumer.accept(buffer, bufferLen);
+                break;
+            default:
+                throw new InternalError(String.valueOf(nBytes));
+        }
+        return nBytes;
+    }
+
+    // The number of bytes that can be written at once
+    // (calculating in bytes, not bits, since
+    //  destination.remaining() * 8 might overflow)
+    @SuppressWarnings("fallthrough")
+    public static int write(long buffer,
+                            int bufferLen,
+                            BufferUpdateConsumer consumer,
+                            ByteBuffer destination)
+    {
+        int nBytes = Math.min(bufferLen >> 3, destination.remaining());
+        switch (nBytes) {
+            case 0:
+                break;
+            case 3:
+                destination.put((byte) (buffer >>> 56));
+                buffer <<= 8;
+                bufferLen -= 8;
+            case 2:
+                destination.put((byte) (buffer >>> 56));
+                buffer <<= 8;
+                bufferLen -= 8;
+            case 1:
+                destination.put((byte) (buffer >>> 56));
+                buffer <<= 8;
+                bufferLen -= 8;
+                consumer.accept(buffer, bufferLen);
+                break;
+            case 7:
+                destination.put((byte) (buffer >>> 56));
+                buffer <<= 8;
+                bufferLen -= 8;
+            case 6:
+                destination.put((byte) (buffer >>> 56));
+                buffer <<= 8;
+                bufferLen -= 8;
+            case 5:
+                destination.put((byte) (buffer >>> 56));
+                buffer <<= 8;
+                bufferLen -= 8;
+            case 4:
+                destination.putInt((int) (buffer >>> 32));
+                buffer <<= 32;
+                bufferLen -= 32;
+                consumer.accept(buffer, bufferLen);
+                break;
+            case 8:
+                destination.putLong(buffer);
+                buffer = 0;
+                bufferLen = 0;
+                consumer.accept(buffer, bufferLen);
+                break;
+            default:
+                throw new InternalError(String.valueOf(nBytes));
+        }
+        return nBytes;
+    }
+
+    /*
+     * Returns the number of bytes the given number of bits constitute.
+     */
+    static int bytesForBits(int n) {
+        assert (n / 8 + (n % 8 != 0 ? 1 : 0)) == (n + 7) / 8
+                && (n + 7) / 8 == ((n + 7) >> 3) : n;
+        return (n + 7) >> 3;
+    }
 }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HeaderTable.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HeaderTable.java	Thu Jun 21 09:53:50 2018 -0700
@@ -28,7 +28,6 @@
 
 import java.util.Deque;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.Map;
 
@@ -104,16 +103,24 @@
     // Long.MAX_VALUE :-)
     //
 
-    private static final Map<String, LinkedHashMap<String, Integer>> staticIndexes;
+    /* An immutable map of static header fields' indexes */
+    private static final Map<String, Map<String, Integer>> staticIndexes;
 
     static {
-        staticIndexes = new HashMap<>(STATIC_TABLE_LENGTH); // TODO: Map.of
+        Map<String, Map<String, Integer>> map
+                = new HashMap<>(STATIC_TABLE_LENGTH);
         for (int i = 1; i <= STATIC_TABLE_LENGTH; i++) {
-            HeaderField f = staticTable[i];
-            Map<String, Integer> values = staticIndexes
-                    .computeIfAbsent(f.name, k -> new LinkedHashMap<>());
+            HeaderField f = staticTable.get(i);
+            Map<String, Integer> values
+                    = map.computeIfAbsent(f.name, k -> new HashMap<>());
             values.put(f.value, i);
         }
+        // create an immutable deep copy
+        Map<String, Map<String, Integer>> copy = new HashMap<>(map.size());
+        for (Map.Entry<String, Map<String, Integer>> e : map.entrySet()) {
+            copy.put(e.getKey(), Map.copyOf(e.getValue()));
+        }
+        staticIndexes = Map.copyOf(copy);
     }
 
     //                name  ->    (value ->    [index])
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/ISO_8859_1.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/ISO_8859_1.java	Thu Jun 21 09:53:50 2018 -0700
@@ -46,29 +46,58 @@
 
     public static final class Reader {
 
+        private final HPACK.BufferUpdateConsumer UPDATER =
+                (buf, bufLen) -> {
+                    buffer = buf;
+                    bufferLen = bufLen;
+                };
+
+        private long buffer;
+        private int bufferLen;
+
         public void read(ByteBuffer source, Appendable destination)
-                throws IOException {
-            for (int i = 0, len = source.remaining(); i < len; i++) {
-                char c = (char) (source.get() & 0xff);
-                try {
-                    destination.append(c);
-                } catch (IOException e) {
-                    throw new IOException(
-                            "Error appending to the destination", e);
+                throws IOException
+        {
+            while (true) {
+                int nBytes = HPACK.read(source, buffer, bufferLen, UPDATER);
+                if (nBytes == 0) {
+                    return;
+                }
+                assert bufferLen % 8 == 0 : bufferLen;
+                while (bufferLen > 0) {
+                    char c = (char) (buffer >>> 56);
+                    try {
+                        destination.append(c);
+                    } catch (IOException e) {
+                        throw new IOException(
+                                "Error appending to the destination", e);
+                    }
+                    buffer <<= 8;
+                    bufferLen -= 8;
                 }
             }
         }
 
         public Reader reset() {
+            buffer = 0;
+            bufferLen = 0;
             return this;
         }
     }
 
     public static final class Writer {
 
+        private final HPACK.BufferUpdateConsumer UPDATER =
+                (buf, bufLen) -> {
+                    buffer = buf;
+                    bufferLen = bufLen;
+                };
+
         private CharSequence source;
         private int pos;
         private int end;
+        private long buffer;
+        private int bufferLen;
 
         public Writer configure(CharSequence source, int start, int end) {
             this.source = source;
@@ -78,25 +107,39 @@
         }
 
         public boolean write(ByteBuffer destination) {
-            for (; pos < end; pos++) {
-                char c = source.charAt(pos);
-                if (c > '\u00FF') {
-                    throw new IllegalArgumentException(
-                            "Illegal ISO-8859-1 char: " + (int) c);
+            while (true) {
+                while (true) { // stuff codes into long
+                    if (pos >= end) {
+                        break;
+                    }
+                    char c = source.charAt(pos);
+                    if (c > 255) {
+                        throw new IllegalArgumentException(Integer.toString((int) c));
+                    }
+                    if (bufferLen <= 56) {
+                        buffer |= (((long) c) << (56 - bufferLen)); // append
+                        bufferLen += 8;
+                        pos++;
+                    } else {
+                        break;
+                    }
                 }
-                if (destination.hasRemaining()) {
-                    destination.put((byte) c);
-                } else {
+                if (bufferLen == 0) {
+                    return true;
+                }
+                int nBytes = HPACK.write(buffer, bufferLen, UPDATER, destination);
+                if (nBytes == 0) {
                     return false;
                 }
             }
-            return true;
         }
 
         public Writer reset() {
             source = null;
             pos = -1;
             end = -1;
+            buffer = 0;
+            bufferLen = 0;
             return this;
         }
     }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/QuickHuffman.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/QuickHuffman.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,19 +25,21 @@
 
 package jdk.internal.net.http.hpack;
 
+import jdk.internal.net.http.hpack.HPACK.BufferUpdateConsumer;
+
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Objects;
 
+import static jdk.internal.net.http.hpack.HPACK.bytesForBits;
+
 public final class QuickHuffman {
 
     /*
-     * Huffman codes for encoding.
-     *
-     * EOS will never be matched, since there is no symbol for it, thus no need
-     * to store it in the array. Thus, the length of the array is 256, not 257.
-     * Code information for each character is encoded as follows:
+     * Mapping of characters to their code information. Code information
+     * consists of a code value and a code length. Both components are packed in
+     * a single long as follows:
      *
      *     MSB                             LSB
      *     +----------------+----------------+
@@ -46,9 +48,14 @@
      *     |<----- 32 ----->|<----- 32 ----->|
      *     |<------------- 64 -------------->|
      *
-     * The leftmost 32 bits hold the code value. This value is aligned left
-     * (or MSB). The rightmost 32 bits hold the length of the code value.
-     * This length is aligned right (or LSB).
+     * The leftmost 32 bits hold the code value. This value is aligned left (or
+     * MSB). The rightmost 32 bits hold the code length. This length is aligned
+     * right (or LSB). Such structure is possible thanks to codes being up to 30
+     * bits long and their lengths being up to 5 bits long (length = 5..30).
+     * This allows both components to fit into long and, thus, better locality.
+     *
+     * Input strings never contain EOS. Thus there's no need to provide EOS
+     * mapping. Hence, the length of the array is 256, not 257.
      */
     private static final long[] codes = new long[256];
 
@@ -62,16 +69,19 @@
 
     private static final int EOS_LENGTH = 30;
     private static final int EOS_LSB = 0x3fffffff;
-    private static final long EOS_MSB = EOS_LSB << (64 - EOS_LENGTH);
+    // EOS_LSB is casted to long before the shift, to allow long shift (6 bits)
+    // instead of int shift (5 bits):
+    private static final long EOS_MSB = ((long) EOS_LSB) << (64 - EOS_LENGTH);
 
     /*
-     * Huffman codes for decoding.
+     * Huffman trie.
      *
-     * Root node contains 257 descendant nodes, including EOS.
+     * The root node leads to 257 descendant leaf nodes, of which 256 nodes
+     * correspond to characters and 1 node correspond to EOS.
      */
-    private static final Node root;
+    private static final Node root = buildTrie();
 
-    static {
+    private static Node buildTrie() {
         TemporaryNode tmpRoot = new TemporaryNode();
         addChar(tmpRoot,   0, 0x1ff8,     13);
         addChar(tmpRoot,   1, 0x7fffd8,   23);
@@ -333,8 +343,8 @@
 
         // The difference in performance can always be checked by not using
         // the immutable trie:
-        //     root = tmpRoot;
-        root = ImmutableNode.copyOf(tmpRoot);
+        //     return tmpRoot;
+        return ImmutableNode.copyOf(tmpRoot);
     }
 
     private QuickHuffman() { }
@@ -605,6 +615,12 @@
 
     static final class Reader implements Huffman.Reader {
 
+        private final BufferUpdateConsumer UPDATER =
+                (buf, bufLen) -> {
+                    buffer = buf;
+                    bufferLen = bufLen;
+                };
+
         private Node curr = root;  // current position in the trie
         private long buffer;       // bits left from the previous match (aligned to the left, or MSB)
         private int bufferLen;     // number of bits in the buffer
@@ -616,53 +632,9 @@
                          Appendable destination,
                          boolean isLast) throws IOException
         {
-            read(source, destination, true, isLast);
-        }
-
-        @Override
-        public void reset() {
-            curr = root;
-            len = 0;
-            buffer = 0;
-            bufferLen = 0;
-            done = false;
-        }
-
-        @SuppressWarnings("fallthrough")
-        void read(ByteBuffer source,
-                  Appendable destination,
-                  boolean reportEOS, /* reportEOS is exposed for tests */
-                  boolean isLast) throws IOException
-        {
             while (!done) {
-                // read as much as possible (up to 8 bytes)
                 int remaining = source.remaining();
-                int nBytes = Math.min((64 - bufferLen) >> 3, remaining);
-                switch (nBytes) {
-                    case 0:
-                        break;
-                    case 3:
-                        readByte(source);
-                    case 2:
-                        readByte(source);
-                    case 1:
-                        readByte(source);
-                        break;
-                    case 7:
-                        readByte(source);
-                    case 6:
-                        readByte(source);
-                    case 5:
-                        readByte(source);
-                    case 4:
-                        readInt(source);
-                        break;
-                    case 8:
-                        readLong(source);
-                        break;
-                    default:
-                        throw new InternalError(String.valueOf(nBytes));
-                }
+                int nBytes = HPACK.read(source, buffer, bufferLen, UPDATER);
                 // write as much as possible
                 while (true) {
                     if (bufferLen < 8) {
@@ -671,7 +643,7 @@
                         } else if (!isLast) { // exit the method to accept more input
                             return;
                         } else if (bufferLen > 0) { // no more data is expected, pad
-                            // (this padding may be done more than once)
+                                                    // (this padding may be done more than once)
                             buffer |= ((0xff00000000000000L >>> bufferLen)
                                     & 0xff00000000000000L);
                             // do not update bufferLen, since all those ones are
@@ -692,7 +664,7 @@
                             throw new IOException(
                                     "Not a EOS prefix padding or unexpected end of data");
                         }
-                        if (reportEOS && node.isEOSPath()) {
+                        if (node.isEOSPath()) {
                             throw new IOException("Encountered EOS");
                         }
                         destination.append(node.getSymbol());
@@ -715,27 +687,24 @@
             }
         }
 
-        private void readLong(ByteBuffer source) {
-            buffer = source.getLong();
-            bufferLen = 64;
-        }
-
-        private void readInt(ByteBuffer source) {
-            long b;
-            b = source.getInt() & 0x00000000ffffffffL;
-            buffer |= (b << (32 - bufferLen));
-            bufferLen += 32;
-        }
-
-        private void readByte(ByteBuffer source) {
-            long b = source.get() & 0x00000000000000ffL;
-            buffer |= (b << (56 - bufferLen));
-            bufferLen += 8;
+        @Override
+        public void reset() {
+            curr = root;
+            len = 0;
+            buffer = 0;
+            bufferLen = 0;
+            done = false;
         }
     }
 
     static final class Writer implements Huffman.Writer {
 
+        private final BufferUpdateConsumer UPDATER =
+                (buf, bufLen) -> {
+                    buffer = buf;
+                    bufferLen = bufLen;
+                };
+
         private CharSequence source;
         private boolean padded;
         private int pos;
@@ -752,43 +721,44 @@
             return this;
         }
 
-        @SuppressWarnings("fallthrough")
         @Override
         public boolean write(ByteBuffer destination) {
             while (true) {
-                while (bufferLen < 32 && pos < end) {
-                    char c = source.charAt(pos++);
-                    buffer |= (codeValueOf(c) >>> bufferLen); // append
-                    bufferLen += codeLengthOf(c);
+                while (true) { // stuff codes into long
+                    if (pos >= end) {
+                        break;
+                    }
+                    char c = source.charAt(pos);
+                    if (c > 255) {
+                        throw new IllegalArgumentException("char=" + ((int) c));
+                    }
+                    long len = codeLengthOf(c);
+                    if (bufferLen + len <= 64) {
+                        buffer |= (codeValueOf(c) >>> bufferLen); // append
+                        bufferLen += len;
+                        pos++;
+                    } else {
+                        break;
+                    }
                 }
                 if (bufferLen == 0) {
                     return true;
                 }
-                if (pos >= end && !padded) { // no more chars, pad
+                if (pos >= end && !padded) { // no more input chars are expected, pad
                     padded = true;
-                    buffer |= (EOS_MSB >>> bufferLen);
-                    bufferLen = bytesForBits(bufferLen) << 3;
+                    // A long shift to 64 will result in the same long, not
+                    // necessarily 0L. In which case padding will be performed
+                    // incorrectly. If bufferLen is equal to 64, the shift (and
+                    // padding) in not performed.
+                    // (see https://docs.oracle.com/javase/specs/jls/se10/html/jls-15.html#jls-15.19)
+                    if (bufferLen != 64) {
+                        buffer |= (EOS_MSB >>> bufferLen);
+                        bufferLen = bytesForBits(bufferLen) << 3;
+                    }
                 }
-                // The number of bytes that can be written at once
-                // (calculating in bytes, not bits, since
-                //  destination.remaining() * 8 might overflow)
-
-                int nBytes = Math.min(bytesForBits(bufferLen), destination.remaining()); // ceil?
-                switch (nBytes) {
-                    case 0:
-                        return false;
-                    case 1:
-                    case 2:
-                    case 3:
-                        destination.put((byte) (buffer >>> 56));
-                        buffer <<= 8;
-                        bufferLen -= 8;
-                        break;
-                    default:
-                        destination.putInt((int) (buffer >>> 32));
-                        buffer <<= 32;
-                        bufferLen -= 32;
-                        break;
+                int nBytes = HPACK.write(buffer, bufferLen, UPDATER, destination);
+                if (nBytes == 0) {
+                    return false;
                 }
             }
         }
@@ -814,13 +784,4 @@
             return bytesForBits(len);
         }
     }
-
-    /*
-     * Returns the number of bytes the given number of bits constitute.
-     */
-    private static int bytesForBits(int n) {
-        assert (n / 8 + (n % 8 != 0 ? 1 : 0)) == (n + 7) / 8
-                && (n + 7) / 8 == ((n + 7) >> 3) : n;
-        return (n + 7) >> 3;
-    }
 }
--- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/SimpleHeaderTable.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/SimpleHeaderTable.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,6 +26,7 @@
 
 import jdk.internal.net.http.hpack.HPACK.Logger;
 
+import java.util.List;
 import java.util.NoSuchElementException;
 
 import static jdk.internal.net.http.common.Utils.pow2Size;
@@ -41,8 +42,9 @@
  */
 class SimpleHeaderTable {
 
-    protected static final HeaderField[] staticTable = {
-            null, // To make index 1-based, instead of 0-based
+    /* An immutable list of static header fields */
+    protected static final List<HeaderField> staticTable = List.of(
+            new HeaderField(""), // A dummy to make the list index 1-based, instead of 0-based
             new HeaderField(":authority"),
             new HeaderField(":method", "GET"),
             new HeaderField(":method", "POST"),
@@ -103,10 +105,9 @@
             new HeaderField("user-agent"),
             new HeaderField("vary"),
             new HeaderField("via"),
-            new HeaderField("www-authenticate")
-    };
+            new HeaderField("www-authenticate"));
 
-    protected static final int STATIC_TABLE_LENGTH = staticTable.length - 1;
+    protected static final int STATIC_TABLE_LENGTH = staticTable.size() - 1;
     protected static final int ENTRY_SIZE = 32;
 
     private final Logger logger;
@@ -134,7 +135,7 @@
     HeaderField get(int index) {
         checkIndex(index);
         if (index <= STATIC_TABLE_LENGTH) {
-            return staticTable[index];
+            return staticTable.get(index);
         } else {
             return buffer.get(index - STATIC_TABLE_LENGTH - 1);
         }
@@ -263,23 +264,6 @@
         public String toString() {
             return value.isEmpty() ? name : name + ": " + value;
         }
-
-        @Override // TODO: remove since used only for testing
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            HeaderField that = (HeaderField) o;
-            return name.equals(that.name) && value.equals(that.value);
-        }
-
-        @Override // TODO: remove since used only for testing
-        public int hashCode() {
-            return 31 * name.hashCode() + value.hashCode();
-        }
     }
 
     private final CircularBuffer<HeaderField> buffer = new CircularBuffer<>(0);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java	Thu Jun 21 09:53:50 2018 -0700
@@ -32,6 +32,9 @@
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
 import java.net.http.WebSocketHandshakeException;
+
+import jdk.internal.net.http.HttpRequestBuilderImpl;
+import jdk.internal.net.http.HttpRequestImpl;
 import jdk.internal.net.http.common.MinimalFuture;
 import jdk.internal.net.http.common.Pair;
 import jdk.internal.net.http.common.Utils;
@@ -104,7 +107,7 @@
         }
     }
 
-    private final HttpRequest request;
+    private final HttpRequestImpl request;
     private final Collection<String> subprotocols;
     private final String nonce;
 
@@ -114,7 +117,7 @@
         checkPermissions(b, proxy);
         this.client = b.getClient();
         URI httpURI = createRequestURI(b.getUri());
-        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(httpURI);
+        HttpRequestBuilderImpl requestBuilder = new HttpRequestBuilderImpl(httpURI);
         Duration connectTimeout = b.getConnectTimeout();
         if (connectTimeout != null) {
             requestBuilder.timeout(connectTimeout);
@@ -127,7 +130,7 @@
         }
         this.subprotocols = createRequestSubprotocols(b.getSubprotocols());
         if (!this.subprotocols.isEmpty()) {
-            String p = this.subprotocols.stream().collect(Collectors.joining(", "));
+            String p = String.join(", ", this.subprotocols);
             requestBuilder.header(HEADER_PROTOCOL, p);
         }
         requestBuilder.header(HEADER_VERSION, VERSION);
@@ -137,12 +140,12 @@
         // to upgrade from HTTP/2 to WebSocket (as of August 2016):
         //
         //     https://tools.ietf.org/html/draft-hirano-httpbis-websocket-over-http2-00
-        this.request = requestBuilder.version(Version.HTTP_1_1).GET().build();
-        WebSocketRequest r = (WebSocketRequest) this.request;
-        r.isWebSocket(true);
-        r.setSystemHeader(HEADER_UPGRADE, "websocket");
-        r.setSystemHeader(HEADER_CONNECTION, "Upgrade");
-        r.setProxy(proxy);
+        requestBuilder.version(Version.HTTP_1_1).GET();
+        request = requestBuilder.buildForWebSocket();
+        request.isWebSocket(true);
+        request.setSystemHeader(HEADER_UPGRADE, "websocket");
+        request.setSystemHeader(HEADER_CONNECTION, "Upgrade");
+        request.setProxy(proxy);
     }
 
     private static Collection<String> createRequestSubprotocols(
--- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/WebSocketImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/WebSocketImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -34,7 +34,6 @@
 import jdk.internal.net.http.websocket.OpeningHandshake.Result;
 
 import java.io.IOException;
-import java.lang.System.Logger.Level;
 import java.lang.ref.Reference;
 import java.net.ProtocolException;
 import java.net.URI;
@@ -88,7 +87,7 @@
         PING,
         PONG,
         CLOSE,
-        ERROR;
+        ERROR
     }
 
     private final AtomicReference<ByteBuffer> lastAutomaticPong = new AtomicReference<>();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -655,9 +655,8 @@
                 return make.Block(0, stats.toList());
             } else {
                 //non-void to non-void conversion:
-                // return (TYPE)BODY;
-                JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
-                return make.at(retExpr).Block(0, List.of(make.Return(retExpr)));
+                // return BODY;
+                return make.at(expr).Block(0, List.of(make.Return(expr)));
             }
         } finally {
             make.at(prevPos);
@@ -692,11 +691,6 @@
                     VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
                     JCVariableDecl varDef = make.VarDef(loc, tree.expr);
                     result = make.Block(0, List.of(varDef, make.Return(null)));
-                } else if (!isTarget_void || !isLambda_void) {
-                    //non-void to non-void conversion:
-                    // return (TYPE)RET-EXPR;
-                    tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
-                    result = tree;
                 } else {
                     result = tree;
                 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jun 21 09:53:50 2018 -0700
@@ -3842,7 +3842,7 @@
 
         @Override
         JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
-            return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.var.type", name);
+            return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.var.type");
         }
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Jun 21 09:53:50 2018 -0700
@@ -476,11 +476,11 @@
         result = tree;
     }
 
-    JCTree currentMethod = null;
+    Type returnType = null;
     public void visitMethodDef(JCMethodDecl tree) {
-        JCTree previousMethod = currentMethod;
+        Type prevRetType = returnType;
         try {
-            currentMethod = tree;
+            returnType = erasure(tree.type).getReturnType();
             tree.restype = translate(tree.restype, null);
             tree.typarams = List.nil();
             tree.params = translateVarDefs(tree.params);
@@ -490,7 +490,7 @@
             tree.type = erasure(tree.type);
             result = tree;
         } finally {
-            currentMethod = previousMethod;
+            returnType = prevRetType;
         }
     }
 
@@ -533,11 +533,11 @@
     }
 
     public void visitLambda(JCLambda tree) {
-        JCTree prevMethod = currentMethod;
+        Type prevRetType = returnType;
         try {
-            currentMethod = null;
+            returnType = erasure(tree.getDescriptorType(types)).getReturnType();
             tree.params = translate(tree.params);
-            tree.body = translate(tree.body, tree.body.type==null? null : erasure(tree.body.type));
+            tree.body = translate(tree.body, tree.body.type == null || returnType.hasTag(VOID) ? null : returnType);
             if (!tree.type.isIntersection()) {
                 tree.type = erasure(tree.type);
             } else {
@@ -546,7 +546,7 @@
             result = tree;
         }
         finally {
-            currentMethod = prevMethod;
+            returnType = prevRetType;
         }
     }
 
@@ -601,7 +601,8 @@
     }
 
     public void visitReturn(JCReturn tree) {
-        tree.expr = translate(tree.expr, currentMethod != null ? types.erasure(currentMethod.type).getReturnType() : null);
+        if (!returnType.hasTag(VOID))
+            tree.expr = translate(tree.expr, returnType);
         result = tree;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Jun 21 09:53:50 2018 -0700
@@ -751,7 +751,7 @@
     public JCExpression unannotatedType(boolean allowVar) {
         JCExpression result = term(TYPE);
 
-        if (!allowVar && isRestrictedLocalVarTypeName(result)) {
+        if (!allowVar && isRestrictedLocalVarTypeName(result, true)) {
             syntaxError(result.pos, Errors.VarNotAllowedHere);
         }
 
@@ -1688,7 +1688,7 @@
             LambdaClassifier lambdaClassifier = new LambdaClassifier();
             for (JCVariableDecl param: params) {
                 if (param.vartype != null &&
-                        isRestrictedLocalVarTypeName(param.vartype) &&
+                        isRestrictedLocalVarTypeName(param.vartype, false) &&
                         param.vartype.hasTag(TYPEARRAY)) {
                     log.error(DiagnosticFlag.SYNTAX, param.pos, Errors.VarNotAllowedArray);
                 }
@@ -1701,7 +1701,7 @@
                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidLambdaParameterDeclaration(lambdaClassifier.diagFragment));
             }
             for (JCVariableDecl param: params) {
-                if (param.vartype != null && isRestrictedLocalVarTypeName(param.vartype)) {
+                if (param.vartype != null && isRestrictedLocalVarTypeName(param.vartype, true)) {
                     param.startPos = TreeInfo.getStartPos(param.vartype);
                     param.vartype = null;
                 }
@@ -1738,7 +1738,7 @@
 
         void addParameter(JCVariableDecl param) {
             if (param.vartype != null && param.name != names.empty) {
-                if (isRestrictedLocalVarTypeName(param.vartype)) {
+                if (isRestrictedLocalVarTypeName(param.vartype, false)) {
                     reduce(LambdaParameterKind.VAR);
                 } else {
                     reduce(LambdaParameterKind.EXPLICIT);
@@ -3021,13 +3021,9 @@
                                                                      T vdefs,
                                                                      boolean localDecl)
     {
-        JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl);
-        boolean implicit = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && head.vartype == null;
+        JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl, false);
         vdefs.append(head);
         while (token.kind == COMMA) {
-            if (implicit) {
-                reportSyntaxError(pos, Errors.VarNotAllowedCompound);
-            }
             // All but last of multiple declarators subsume a comma
             storeEnd((JCTree)vdefs.last(), token.endPos);
             nextToken();
@@ -3040,7 +3036,7 @@
      *  ConstantDeclarator = Ident ConstantDeclaratorRest
      */
     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, Comment dc, boolean localDecl) {
-        return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc, localDecl);
+        return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc, localDecl, true);
     }
 
     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
@@ -3050,7 +3046,7 @@
      *  @param dc       The documentation comment for the variable declarations, or null.
      */
     JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
-                                  boolean reqInit, Comment dc, boolean localDecl) {
+                                  boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
         type = bracketsOpt(type);
         JCExpression init = null;
         if (token.kind == EQ) {
@@ -3060,10 +3056,13 @@
         else if (reqInit) syntaxError(token.pos, Errors.Expected(EQ));
         JCTree elemType = TreeInfo.innermostType(type, true);
         int startPos = Position.NOPOS;
-        if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && elemType.hasTag(IDENT)) {
+        if (elemType.hasTag(IDENT)) {
             Name typeName = ((JCIdent)elemType).name;
-            if (isRestrictedLocalVarTypeName(typeName)) {
-                if (type.hasTag(TYPEARRAY)) {
+            if (isRestrictedLocalVarTypeName(typeName, pos, !compound && localDecl)) {
+                if (compound) {
+                    //error - 'var' in compound local var decl
+                   reportSyntaxError(pos, Errors.VarNotAllowedCompound);
+                } else if (type.hasTag(TYPEARRAY)) {
                     //error - 'var' and arrays
                     reportSyntaxError(pos, Errors.VarNotAllowedArray);
                 } else {
@@ -3082,19 +3081,26 @@
         return result;
     }
 
-    boolean isRestrictedLocalVarTypeName(JCExpression e) {
+    boolean isRestrictedLocalVarTypeName(JCExpression e, boolean shouldWarn) {
         switch (e.getTag()) {
             case IDENT:
-                return isRestrictedLocalVarTypeName(((JCIdent)e).name);
+                return isRestrictedLocalVarTypeName(((JCIdent)e).name, e.pos, shouldWarn);
             case TYPEARRAY:
-                return isRestrictedLocalVarTypeName(((JCArrayTypeTree)e).elemtype);
+                return isRestrictedLocalVarTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
             default:
                 return false;
         }
     }
 
-    boolean isRestrictedLocalVarTypeName(Name name) {
-        return Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && name == names.var;
+    boolean isRestrictedLocalVarTypeName(Name name, int pos, boolean shouldWarn) {
+        if (name == names.var) {
+            if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
+                return true;
+            } else if (shouldWarn) {
+                log.warning(pos, Warnings.VarNotAllowed);
+            }
+        }
+        return false;
     }
 
     /** VariableDeclaratorId = Ident BracketsOpt
@@ -3179,12 +3185,12 @@
         if (token.kind == FINAL || token.kind == MONKEYS_AT) {
             JCModifiers mods = optFinal(Flags.FINAL);
             JCExpression t = parseType(true);
-            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null, true);
+            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null, true, false);
         }
         JCExpression t = term(EXPR | TYPE);
         if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
             JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL));
-            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null, true);
+            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null, true, false);
         } else {
             checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES);
             if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
@@ -3485,12 +3491,8 @@
     Name typeName() {
         int pos = token.pos;
         Name name = ident();
-        if (name == names.var) {
-            if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
-                reportSyntaxError(pos, Errors.VarNotAllowed(name));
-            } else {
-                log.warning(pos, Warnings.VarNotAllowed);
-            }
+        if (isRestrictedLocalVarTypeName(name, pos, true)) {
+            reportSyntaxError(pos, Errors.VarNotAllowed);
         }
         return name;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Jun 21 09:53:50 2018 -0700
@@ -1216,17 +1216,15 @@
 compiler.err.undef.label=\
     undefined label: {0}
 
-# 0: name (type)
 compiler.err.illegal.ref.to.var.type=\
-    illegal reference to restricted type ''{0}''
-
-# 0: name
+    illegal reference to restricted type ''var''
+
 compiler.err.var.not.allowed=\
-    ''{0}'' not allowed here\n\
-    as of release 10, ''{0}'' is a restricted local variable type and cannot be used for type declarations
+    ''var'' not allowed here\n\
+    as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations
 
 compiler.warn.var.not.allowed=\
-    as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations
+    as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations or as the element type of an array
 
 # 0: name (variable), 1: message segment
 compiler.err.cant.infer.local.var.type=\
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/LinkerServicesImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/LinkerServicesImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2015 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2016 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2016 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2015 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2016 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2015 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AccessibleMembersLookup.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AccessibleMembersLookup.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ApplicableOverloadedMethods.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ApplicableOverloadedMethods.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanIntrospector.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanIntrospector.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassString.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassString.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/FacetIntrospector.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/FacetIntrospector.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MaximallySpecific.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MaximallySpecific.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SimpleDynamicMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SimpleDynamicMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SingleDynamicMethod.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SingleDynamicMethod.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassIntrospector.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassIntrospector.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.beans;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/package-info.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/package-info.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /**
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2015 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2014 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/package-info.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/package-info.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /**
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2015 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.linker.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/package-info.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/package-info.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2015 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /**
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /**
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 package jdk.dynalink.support;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/package-info.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/package-info.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,52 +33,29 @@
 /*
    Copyright 2009-2013 Attila Szegedi
 
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+   * Neither the name of the copyright holder nor the names of
+     contributors may be used to endorse or promote products derived from
+     this software without specific prior written permission.
 
-       Redistribution and use in source and binary forms, with or without
-       modification, are permitted provided that the following conditions are
-       met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the copyright holder nor the names of
-         contributors may be used to endorse or promote products derived from
-         this software without specific prior written permission.
-
-       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
-       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /**
--- a/src/jdk.dynalink/share/legal/dynalink.md	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.dynalink/share/legal/dynalink.md	Thu Jun 21 09:53:50 2018 -0700
@@ -3,6 +3,26 @@
 ### Dynalink License
 <pre>
 
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
 Copyright (c) 2009-2013, Attila Szegedi
 
 All rights reserved.Redistribution and use in source and binary forms, with or
--- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -227,8 +227,8 @@
             contentLen = -1;
         }
 
-        if (isHeadRequest()) {
-            /* HEAD requests should not set a content length by passing it
+        if (isHeadRequest() || rCode == 304) {
+            /* HEAD requests or 304 responses should not set a content length by passing it
              * through this API, but should instead manually set the required
              * headers.*/
             if (contentLen >= 0) {
@@ -239,7 +239,7 @@
             }
             noContentToSend = true;
             contentLen = 0;
-        } else { /* not a HEAD request */
+        } else { /* not a HEAD request or 304 response */
             if (contentLen == 0) {
                 if (http10) {
                     o.setWrappedStream (new UndefLengthOutputStream (this, ros));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Jun 21 09:53:50 2018 -0700
@@ -559,6 +559,8 @@
 
     public final boolean tlabStats = getFlag("TLABStats", Boolean.class);
 
+    public final boolean useFastTLABRefill = versioned.useFastTLABRefill;
+
     // FIXME This is only temporary until the GC code is changed.
     public final boolean inlineContiguousAllocationSupported = getFieldValue("CompilerToVM::Data::_supports_inline_contig_alloc", Boolean.class);
     public final long heapEndAddress = getFieldValue("CompilerToVM::Data::_heap_end_addr", Long.class, "HeapWord**");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java	Thu Jun 21 09:53:50 2018 -0700
@@ -84,4 +84,7 @@
     // JDK-8015774
     final long codeCacheLowBound = getFieldValue("CodeCache::_low_bound", Long.class, "address");
     final long codeCacheHighBound = getFieldValue("CodeCache::_high_bound", Long.class, "address");
+
+    // JDK-8205105
+    boolean useFastTLABRefill = false;
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Thu Jun 21 09:53:50 2018 -0700
@@ -1022,4 +1022,9 @@
     public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength");
 
     public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement");
+
+    @Fold
+    public static boolean useFastTLABRefill(@InjectedParameter GraalHotSpotVMConfig config) {
+        return config.useFastTLABRefill;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java	Thu Jun 21 09:53:50 2018 -0700
@@ -35,6 +35,7 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useCMSIncrementalMode;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useFastTLABRefill;
 import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH;
 import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.formatArray;
 import static org.graalvm.compiler.hotspot.stubs.NewInstanceStub.refillAllocate;
@@ -122,7 +123,8 @@
         // check that array length is small enough for fast path.
         Word thread = registerAsWord(threadRegister);
         boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported();
-        if (inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG) && length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
+        if (useFastTLABRefill(INJECTED_VMCONFIG) && inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG) && length >= 0 &&
+                        length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
             Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options));
             if (memory.notEqual(0)) {
                 if (logging(options)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java	Thu Jun 21 09:53:50 2018 -0700
@@ -54,6 +54,7 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabSlowAllocationsOffset;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabStats;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useCMSIncrementalMode;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useFastTLABRefill;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useG1GC;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useTLAB;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize;
@@ -148,7 +149,7 @@
          */
         Word thread = registerAsWord(threadRegister);
         boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported();
-        if (!forceSlowPath(options) && inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG)) {
+        if (useFastTLABRefill(INJECTED_VMCONFIG) && !forceSlowPath(options) && inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG)) {
             if (isInstanceKlassFullyInitialized(hub)) {
                 int sizeInBytes = readLayoutHelper(hub);
                 Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Thu Jun 21 09:53:50 2018 -0700
@@ -164,12 +164,12 @@
      * @param te TypeElement whose members will be added to the indexmap.
      */
     protected void putMembersInIndexMap(TypeElement te) {
-        adjustIndexMap(utils.getAnnotationFields(te));
-        adjustIndexMap(utils.getFields(te));
         VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+        adjustIndexMap(vmt.getMembers(ANNOTATION_TYPE_FIELDS));
+        adjustIndexMap(vmt.getMembers(FIELDS));
         adjustIndexMap(vmt.getMembers(METHODS));
-        adjustIndexMap(utils.getConstructors(te));
-        adjustIndexMap(utils.getEnumConstants(te));
+        adjustIndexMap(vmt.getMembers(CONSTRUCTORS));
+        adjustIndexMap(vmt.getMembers(ENUM_CONSTANTS));
     }
 
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java	Thu Jun 21 09:53:50 2018 -0700
@@ -676,7 +676,6 @@
                         addMember(e, Kind.METHODS);
                         break;
                     case CONSTRUCTOR:
-                        if (!utils.isEnum(te))
                             addMember(e, Kind.CONSTRUCTORS);
                         break;
                     case ENUM_CONSTANT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/ProblemList-cds-mode.txt	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#############################################################################
+#
+# Additional list of quarantined tests when CDS mode enabled.
+#
+#############################################################################
+
+serviceability/sa/TestInstanceKlassSize.java                    8204308   generic-all
+serviceability/sa/TestInstanceKlassSizeForInterface.java        8204308   generic-all
--- a/test/hotspot/jtreg/ProblemList.txt	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/ProblemList.txt	Thu Jun 21 09:53:50 2018 -0700
@@ -49,7 +49,8 @@
 compiler/tiered/LevelTransitionTest.java 8067651 generic-all
 compiler/types/correctness/CorrectnessTest.java 8066173 generic-all
 compiler/types/correctness/OffTest.java 8066173 generic-all
-compiler/c2/Test8007294.java 8192992 generic-all
+
+compiler/c2/Test6852078.java 8194310 generic-all
 
 applications/ctw/modules/java_desktop.java 8189604 windows-all
 applications/ctw/modules/java_desktop_2.java 8189604,8204842 generic-all
@@ -87,14 +88,6 @@
 
 #############################################################################
 
-###########################################################################
-#
-# Java EE Module Removal
-#
-
-compiler/c2/Test8007294.java                                                   8194310    generic-all  Java EE Module Removal
-compiler/c2/Test6852078.java                                                   8194310    generic-all  Java EE Module Removal
-
 #############################################################################
 
 # :vmTestbase_*
@@ -130,12 +123,14 @@
 
 vmTestbase/nsk/jvmti/ClearBreakpoint/clrbrk001/TestDescription.java 8016181 generic-all
 vmTestbase/nsk/jvmti/FieldModification/fieldmod001/TestDescription.java 8016181 generic-all
+vmTestbase/nsk/jvmti/RedefineClasses/StressRedefineWithoutBytecodeCorruption/TestDescription.java 8202896 linux-x64
 vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted001/TestDescription.java 7013634 generic-all
 vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java 6606767 generic-all
 vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java 7013634,6606767 generic-all
 vmTestbase/nsk/jvmti/ThreadStart/threadstart001/TestDescription.java 8016181 generic-all
 vmTestbase/nsk/jvmti/ThreadStart/threadstart003/TestDescription.java 8034084 generic-all
 vmTestbase/nsk/jvmti/scenarios/extension/EX03/ex03t001/TestDescription.java 8173658 generic-all
+vmTestbase/nsk/jvmti/scenarios/hotswap/HS102/hs102t002/TestDescription.java 8204506,8203350 generic-all
 vmTestbase/nsk/jvmti/scenarios/hotswap/HS204/hs204t001/hs204t001.java 6813266 generic-all
 vmTestbase/nsk/jvmti/scenarios/sampling/SP06/sp06t003/TestDescription.java 8051349 generic-all
 vmTestbase/nsk/jvmti/AttachOnDemand/attach034/TestDescription.java 8042145 generic-all
--- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java	Thu Jun 21 09:53:50 2018 -0700
@@ -76,7 +76,7 @@
         OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest(
                 test,
                 CommandLineOptionTest.prepareBooleanFlag("UseRTMForStackLocks",
-                        inflateMonitor),
+                        !inflateMonitor),
                 CommandLineOptionTest.prepareBooleanFlag(
                         "UseRTMXendForLockBusy",
                         useXend),
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java	Thu Jun 21 09:53:50 2018 -0700
@@ -166,9 +166,10 @@
                            APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
 
             String MATCH_PATTERN = ".class.load. javax.annotation.processing.FilerException source:.*bootAppend.jar*";
-            OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
-            out.shouldHaveExitValue(0)
-                       .shouldNotMatch(MATCH_PATTERN);
+            CDSTestUtils.run(opts)
+                .assertNormalExit(out -> {
+                    out.shouldNotMatch(MATCH_PATTERN);
+                });
         }
     }
 
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/ArrayStoreException/ArrayStoreExceptionTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/ArrayStoreException/ArrayStoreExceptionTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -63,18 +63,6 @@
         }
     }
 
-    static native void doNativeArrayStore2(Object src, Object dst, int index);
-
-    static void testNativeASMessages2(Object array, Object elem, int index, String message)
-        throws Exception {
-        try {
-            doNativeArrayStore2(array, elem, index);
-            Asserts.fail("Expected ArrayStoreException not thrown");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            Asserts.assertEquals(e.getMessage(), message);
-        }
-    }
-
     public static void main(String[] args) throws Exception {
         try {
             boolean[]    za1 = new boolean[3];
@@ -193,8 +181,6 @@
             testNativeASMessages(ia4, "This is not a date", 2,
                                  "type mismatch: can not store java.lang.String to int[2][][]");
 
-            testNativeASMessages2("This is not an array", "This is not a date", 2, "2");
-
         } catch (java.lang.RuntimeException e) {
             throw e;
         } catch (Exception e) {
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/ArrayStoreException/libArrayStoreExceptionTest.c	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/ArrayStoreException/libArrayStoreExceptionTest.c	Thu Jun 21 09:53:50 2018 -0700
@@ -30,8 +30,3 @@
   (*env)->SetObjectArrayElement(env, array, index, element);
 }
 
-JNIEXPORT void JNICALL
-  Java_ArrayStoreExceptionTest_doNativeArrayStore2(JNIEnv *env, jclass klass,
-                                                   jobject array, jobject element, jint index) {
-  (*env)->SetObjectArrayElement(env, (jobjectArray)array, index, element);
-}
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t003/hs203t003.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t003/hs203t003.java	Thu Jun 21 09:53:50 2018 -0700
@@ -77,29 +77,32 @@
     }
 
 
-    public boolean  agentMethod() {
+    public boolean agentMethod() {
         boolean passed = false;
         MyThread mt = new MyThread();
-                try {
+        try {
             mt.start();
             // check if we can can pop the thread.
-            // we can not do redefine / pop frame on run method.
-            while(!MyThread.resume.get());
-                        Thread.sleep(10000);
+            // we can not do redefine/pop frame on run method.
+            while (!MyThread.resume.get());
             // sleep for some few secs to get redefined.
-            popThreadFrame(mt);
-            // pop the frame.
-            resumeThread(mt);
-            // resume the thread.
+            while (!isRedefined()) {
+                if (!agentStatus()) {
+                    System.out.println("Failed to redefine class");
+                    return passed;
+                }
+                Thread.sleep(100);
+            }
+            popThreadFrame(mt); // pop the frame.
+            resumeThread(mt);   // resume the thread.
             mt.join();
             // wait till the other thread completes its execution.
-            System.out.println(" Thread state after poping / redefining = "+mt.threadState);
+            System.out.println("Thread state after popping/redefining = "
+                               + mt.threadState);
         } catch(Exception ie) {
             ie.printStackTrace();
         }
-        if ( ( mt.threadState < 1000 ) &&
-                ( redefineAttempted() && isRedefined())  &&
-                agentStatus() ) {
+        if ((mt.threadState < 1000) && agentStatus()) {
             passed = true;
         }
         return passed;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP05/sp05t003/sp05t003.c	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP05/sp05t003/sp05t003.c	Thu Jun 21 09:53:50 2018 -0700
@@ -383,7 +383,6 @@
     for (i = 0; i < THREADS_COUNT; i++) {
         if (NSK_CPP_STUB3(IsSameObject, jni, threadsList[i], thread)) {
                 NSK_DISPLAY0("SUCCESS: expected THREAD_START event\n");
-            eventsStart++;
 
             /* suspend thread */
             NSK_DISPLAY3("  suspend starting thread #%d (%s): %p\n",
@@ -394,6 +393,7 @@
                 nsk_jvmti_setFailStatus();
                 return;
             }
+            eventsStart++;
 
             break;
         }
@@ -418,7 +418,6 @@
     for (i = 0; i < THREADS_COUNT; i++) {
         if (NSK_CPP_STUB3(IsSameObject, jni, threadsList[i], thread)) {
                 NSK_DISPLAY0("SUCCESS: expected THREAD_END event\n");
-            eventsEnd++;
 
             /* suspend thread */
             NSK_DISPLAY3("  suspend finishing thread #%d (%s): %p\n",
@@ -429,6 +428,7 @@
                 nsk_jvmti_setFailStatus();
                 return;
             }
+            eventsEnd++;
 
             break;
         }
--- a/test/jdk/java/net/httpclient/AbstractNoBody.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/AbstractNoBody.java	Thu Jun 21 09:53:50 2018 -0700
@@ -57,7 +57,7 @@
     String https2URI_chunk;
 
     static final String SIMPLE_STRING = "Hello world. Goodbye world";
-    static final int ITERATION_COUNT = 10;
+    static final int ITERATION_COUNT = 3;
     // a shared executor helps reduce the amount of threads created by the test
     static final Executor executor = Executors.newFixedThreadPool(ITERATION_COUNT * 2);
     static final ExecutorService serverExecutor = Executors.newFixedThreadPool(ITERATION_COUNT * 4);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/AbstractThrowingPublishers.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublisher;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandler;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Flow;
+import java.util.concurrent.SubmissionPublisher;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.String.format;
+import static java.lang.System.out;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public abstract class AbstractThrowingPublishers implements HttpServerAdapters {
+
+    SSLContext sslContext;
+    HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
+    HttpTestServer httpsTestServer;   // HTTPS/1.1
+    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
+    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
+    String httpURI_fixed;
+    String httpURI_chunk;
+    String httpsURI_fixed;
+    String httpsURI_chunk;
+    String http2URI_fixed;
+    String http2URI_chunk;
+    String https2URI_fixed;
+    String https2URI_chunk;
+
+    static final int ITERATION_COUNT = 1;
+    // a shared executor helps reduce the amount of threads created by the test
+    static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
+    static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
+    static volatile boolean tasksFailed;
+    static final AtomicLong serverCount = new AtomicLong();
+    static final AtomicLong clientCount = new AtomicLong();
+    static final long start = System.nanoTime();
+    public static String now() {
+        long now = System.nanoTime() - start;
+        long secs = now / 1000_000_000;
+        long mill = (now % 1000_000_000) / 1000_000;
+        long nan = now % 1000_000;
+        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
+    }
+
+    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
+    private volatile HttpClient sharedClient;
+
+    static class TestExecutor implements Executor {
+        final AtomicLong tasks = new AtomicLong();
+        Executor executor;
+        TestExecutor(Executor executor) {
+            this.executor = executor;
+        }
+
+        @Override
+        public void execute(Runnable command) {
+            long id = tasks.incrementAndGet();
+            executor.execute(() -> {
+                try {
+                    command.run();
+                } catch (Throwable t) {
+                    tasksFailed = true;
+                    System.out.printf(now() + "Task %s failed: %s%n", id, t);
+                    System.err.printf(now() + "Task %s failed: %s%n", id, t);
+                    FAILURES.putIfAbsent("Task " + id, t);
+                    throw t;
+                }
+            });
+        }
+    }
+
+    @AfterClass
+    static final void printFailedTests() {
+        out.println("\n=========================");
+        try {
+            out.printf("%n%sCreated %d servers and %d clients%n",
+                    now(), serverCount.get(), clientCount.get());
+            if (FAILURES.isEmpty()) return;
+            out.println("Failed tests: ");
+            FAILURES.entrySet().forEach((e) -> {
+                out.printf("\t%s: %s%n", e.getKey(), e.getValue());
+                e.getValue().printStackTrace(out);
+            });
+            if (tasksFailed) {
+                System.out.println("WARNING: Some tasks failed");
+            }
+        } finally {
+            out.println("\n=========================\n");
+        }
+    }
+
+    private String[] uris() {
+        return new String[] {
+                httpURI_fixed,
+                httpURI_chunk,
+                httpsURI_fixed,
+                httpsURI_chunk,
+                http2URI_fixed,
+                http2URI_chunk,
+                https2URI_fixed,
+                https2URI_chunk,
+        };
+    }
+
+    @DataProvider(name = "sanity")
+    public Object[][] sanity() {
+        String[] uris = uris();
+        Object[][] result = new Object[uris.length * 2][];
+        //Object[][] result = new Object[uris.length][];
+        int i = 0;
+        for (boolean sameClient : List.of(false, true)) {
+            //if (!sameClient) continue;
+            for (String uri: uris()) {
+                result[i++] = new Object[] {uri + "/sanity", sameClient};
+            }
+        }
+        assert i == uris.length * 2;
+        // assert i == uris.length ;
+        return result;
+    }
+
+    enum Where {
+        BEFORE_SUBSCRIBE, BEFORE_REQUEST, BEFORE_NEXT_REQUEST, BEFORE_CANCEL,
+        AFTER_SUBSCRIBE, AFTER_REQUEST, AFTER_NEXT_REQUEST, AFTER_CANCEL;
+        public Consumer<Where> select(Consumer<Where> consumer) {
+            return new Consumer<Where>() {
+                @Override
+                public void accept(Where where) {
+                    if (Where.this == where) {
+                        consumer.accept(where);
+                    }
+                }
+            };
+        }
+    }
+
+    private Object[][] variants(List<Thrower> throwers, Set<Where> whereValues) {
+        String[] uris = uris();
+        Object[][] result = new Object[uris.length * 2 * throwers.size()][];
+        //Object[][] result = new Object[(uris.length/2) * 2 * 2][];
+        int i = 0;
+        for (Thrower thrower : throwers) {
+            for (boolean sameClient : List.of(false, true)) {
+                for (String uri : uris()) {
+                    // if (uri.contains("http2") || uri.contains("https2")) continue;
+                    // if (!sameClient) continue;
+                    result[i++] = new Object[]{uri, sameClient, thrower, whereValues};
+                }
+            }
+        }
+        assert i == uris.length * 2 * throwers.size();
+        //assert Stream.of(result).filter(o -> o != null).count() == result.length;
+        return result;
+    }
+
+    @DataProvider(name = "subscribeProvider")
+    public Object[][] subscribeProvider() {
+        return  variants(List.of(
+                new UncheckedCustomExceptionThrower(),
+                new UncheckedIOExceptionThrower()),
+                EnumSet.of(Where.BEFORE_SUBSCRIBE, Where.AFTER_SUBSCRIBE));
+    }
+
+    @DataProvider(name = "requestProvider")
+    public Object[][] requestProvider() {
+        return  variants(List.of(
+                new UncheckedCustomExceptionThrower(),
+                new UncheckedIOExceptionThrower()),
+                EnumSet.of(Where.BEFORE_REQUEST, Where.AFTER_REQUEST));
+    }
+
+    @DataProvider(name = "nextRequestProvider")
+    public Object[][] nextRequestProvider() {
+        return  variants(List.of(
+                new UncheckedCustomExceptionThrower(),
+                new UncheckedIOExceptionThrower()),
+                EnumSet.of(Where.BEFORE_NEXT_REQUEST, Where.AFTER_NEXT_REQUEST));
+    }
+
+    @DataProvider(name = "beforeCancelProviderIO")
+    public Object[][] beforeCancelProviderIO() {
+        return  variants(List.of(
+                new UncheckedIOExceptionThrower()),
+                EnumSet.of(Where.BEFORE_CANCEL));
+    }
+
+    @DataProvider(name = "afterCancelProviderIO")
+    public Object[][] afterCancelProviderIO() {
+        return  variants(List.of(
+                new UncheckedIOExceptionThrower()),
+                EnumSet.of(Where.AFTER_CANCEL));
+    }
+
+    @DataProvider(name = "beforeCancelProviderCustom")
+    public Object[][] beforeCancelProviderCustom() {
+        return  variants(List.of(
+                new UncheckedCustomExceptionThrower()),
+                EnumSet.of(Where.BEFORE_CANCEL));
+    }
+
+    @DataProvider(name = "afterCancelProviderCustom")
+    public Object[][] afterCancelProvider() {
+        return  variants(List.of(
+                new UncheckedCustomExceptionThrower()),
+                EnumSet.of(Where.AFTER_CANCEL));
+    }
+
+    private HttpClient makeNewClient() {
+        clientCount.incrementAndGet();
+        return TRACKER.track(HttpClient.newBuilder()
+                .proxy(HttpClient.Builder.NO_PROXY)
+                .executor(executor)
+                .sslContext(sslContext)
+                .build());
+    }
+
+    HttpClient newHttpClient(boolean share) {
+        if (!share) return makeNewClient();
+        HttpClient shared = sharedClient;
+        if (shared != null) return shared;
+        synchronized (this) {
+            shared = sharedClient;
+            if (shared == null) {
+                shared = sharedClient = makeNewClient();
+            }
+            return shared;
+        }
+    }
+
+    final String BODY = "Some string | that ? can | be split ? several | ways.";
+
+    //@Test(dataProvider = "sanity")
+    protected void testSanityImpl(String uri, boolean sameClient)
+            throws Exception {
+        HttpClient client = null;
+        out.printf("%n%s testSanity(%s, %b)%n", now(), uri, sameClient);
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient(sameClient);
+
+            SubmissionPublisher<ByteBuffer> publisher
+                    = new SubmissionPublisher<>(executor,10);
+            ThrowingBodyPublisher bodyPublisher = new ThrowingBodyPublisher((w) -> {},
+                    BodyPublishers.fromPublisher(publisher));
+            CompletableFuture<Void> subscribedCF = bodyPublisher.subscribedCF();
+            subscribedCF.whenComplete((r,t) -> System.out.println(now() + " subscribe completed " + t))
+                    .thenAcceptAsync((v) -> {
+                                Stream.of(BODY.split("\\|"))
+                                        .forEachOrdered(s -> {
+                                                System.out.println("submitting \"" + s +"\"");
+                                                publisher.submit(ByteBuffer.wrap(s.getBytes(StandardCharsets.UTF_8)));
+                                        });
+                                System.out.println("publishing done");
+                                publisher.close();
+                            },
+                    executor);
+
+            HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
+                    .POST(bodyPublisher)
+                    .build();
+            BodyHandler<String> handler = BodyHandlers.ofString();
+            CompletableFuture<HttpResponse<String>> response = client.sendAsync(req, handler);
+
+            String body = response.join().body();
+            assertEquals(body, Stream.of(BODY.split("\\|")).collect(Collectors.joining()));
+        }
+    }
+
+    // @Test(dataProvider = "variants")
+    protected void testThrowingAsStringImpl(String uri,
+                                     boolean sameClient,
+                                     Thrower thrower,
+                                     Set<Where> whereValues)
+            throws Exception
+    {
+        String test = format("testThrowingAsString(%s, %b, %s, %s)",
+                             uri, sameClient, thrower, whereValues);
+        List<byte[]> bytes = Stream.of(BODY.split("|"))
+                .map(s -> s.getBytes(UTF_8))
+                .collect(Collectors.toList());
+        testThrowing(test, uri, sameClient, () -> BodyPublishers.ofByteArrays(bytes),
+                this::shouldNotThrowInCancel, thrower,false, whereValues);
+    }
+
+    private <T,U> void testThrowing(String name, String uri, boolean sameClient,
+                                    Supplier<BodyPublisher> publishers,
+                                    Finisher finisher, Thrower thrower,
+                                    boolean async, Set<Where> whereValues)
+            throws Exception
+    {
+        out.printf("%n%s%s%n", now(), name);
+        try {
+            testThrowing(uri, sameClient, publishers, finisher, thrower, async, whereValues);
+        } catch (Error | Exception x) {
+            FAILURES.putIfAbsent(name, x);
+            throw x;
+        }
+    }
+
+    private void testThrowing(String uri, boolean sameClient,
+                                    Supplier<BodyPublisher> publishers,
+                                    Finisher finisher, Thrower thrower,
+                                    boolean async, Set<Where> whereValues)
+            throws Exception
+    {
+        HttpClient client = null;
+        for (Where where : whereValues) {
+            //if (where == Where.ON_SUBSCRIBE) continue;
+            //if (where == Where.ON_ERROR) continue;
+            if (!sameClient || client == null)
+                client = newHttpClient(sameClient);
+
+            ThrowingBodyPublisher bodyPublisher =
+                    new ThrowingBodyPublisher(where.select(thrower), publishers.get());
+            HttpRequest req = HttpRequest.
+                    newBuilder(URI.create(uri))
+                    .header("X-expect-exception", "true")
+                    .POST(bodyPublisher)
+                    .build();
+            BodyHandler<String> handler = BodyHandlers.ofString();
+            System.out.println("try throwing in " + where);
+            HttpResponse<String> response = null;
+            if (async) {
+                try {
+                    response = client.sendAsync(req, handler).join();
+                } catch (Error | Exception x) {
+                    Throwable cause = findCause(where, x, thrower);
+                    if (cause == null) throw causeNotFound(where, x);
+                    System.out.println(now() + "Got expected exception: " + cause);
+                }
+            } else {
+                try {
+                    response = client.send(req, handler);
+                } catch (Error | Exception t) {
+                    // synchronous send will rethrow exceptions
+                    Throwable throwable = t.getCause();
+                    assert throwable != null;
+
+                    if (thrower.test(where, throwable)) {
+                        System.out.println(now() + "Got expected exception: " + throwable);
+                    } else throw causeNotFound(where, t);
+                }
+            }
+            if (response != null) {
+                finisher.finish(where, response, thrower);
+            }
+        }
+    }
+
+    // can be used to reduce the surface of the test when diagnosing
+    // some failure
+    Set<Where> whereValues() {
+        //return EnumSet.of(Where.BEFORE_CANCEL, Where.AFTER_CANCEL);
+        return EnumSet.allOf(Where.class);
+    }
+
+    interface Thrower extends Consumer<Where>, BiPredicate<Where,Throwable> {
+
+    }
+
+    interface Finisher<T,U> {
+        U finish(Where w, HttpResponse<T> resp, Thrower thrower) throws IOException;
+    }
+
+    final <T,U> U shouldNotThrowInCancel(Where w, HttpResponse<T> resp, Thrower thrower) {
+        switch (w) {
+            case BEFORE_CANCEL: return null;
+            case AFTER_CANCEL: return null;
+            default: break;
+        }
+        return shouldHaveThrown(w, resp, thrower);
+    }
+
+
+    final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
+        String msg = "Expected exception not thrown in " + w
+                + "\n\tReceived: " + resp
+                + "\n\tWith body: " + resp.body();
+        System.out.println(msg);
+        throw new RuntimeException(msg);
+    }
+
+
+    private static Throwable findCause(Where w,
+                                       Throwable x,
+                                       BiPredicate<Where, Throwable> filter) {
+        while (x != null && !filter.test(w,x)) x = x.getCause();
+        return x;
+    }
+
+    static AssertionError causeNotFound(Where w, Throwable t) {
+        return new AssertionError("Expected exception not found in " + w, t);
+    }
+
+    static boolean isConnectionClosedLocally(Throwable t) {
+        if (t instanceof CompletionException) t = t.getCause();
+        if (t instanceof ExecutionException) t = t.getCause();
+        if (t instanceof IOException) {
+            String msg = t.getMessage();
+            return msg == null ? false
+                    : msg.contains("connection closed locally");
+        }
+        return false;
+    }
+
+    static final class UncheckedCustomExceptionThrower implements Thrower {
+        @Override
+        public void accept(Where where) {
+            out.println(now() + "Throwing in " + where);
+            throw new UncheckedCustomException(where.name());
+        }
+
+        @Override
+        public boolean test(Where w, Throwable throwable) {
+            switch (w) {
+                case AFTER_REQUEST:
+                case BEFORE_NEXT_REQUEST:
+                case AFTER_NEXT_REQUEST:
+                    if (isConnectionClosedLocally(throwable)) return true;
+                    break;
+                default:
+                    break;
+            }
+            return UncheckedCustomException.class.isInstance(throwable);
+        }
+
+        @Override
+        public String toString() {
+            return "UncheckedCustomExceptionThrower";
+        }
+    }
+
+    static final class UncheckedIOExceptionThrower implements Thrower {
+        @Override
+        public void accept(Where where) {
+            out.println(now() + "Throwing in " + where);
+            throw new UncheckedIOException(new CustomIOException(where.name()));
+        }
+
+        @Override
+        public boolean test(Where w, Throwable throwable) {
+            switch (w) {
+                case AFTER_REQUEST:
+                case BEFORE_NEXT_REQUEST:
+                case AFTER_NEXT_REQUEST:
+                    if (isConnectionClosedLocally(throwable)) return true;
+                    break;
+                default:
+                    break;
+            }
+            return UncheckedIOException.class.isInstance(throwable)
+                    && CustomIOException.class.isInstance(throwable.getCause());
+        }
+
+        @Override
+        public String toString() {
+            return "UncheckedIOExceptionThrower";
+        }
+    }
+
+    static final class UncheckedCustomException extends RuntimeException {
+        UncheckedCustomException(String message) {
+            super(message);
+        }
+        UncheckedCustomException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    static final class CustomIOException extends IOException {
+        CustomIOException(String message) {
+            super(message);
+        }
+        CustomIOException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+
+    static final class ThrowingBodyPublisher implements BodyPublisher {
+        private final BodyPublisher publisher;
+        private final CompletableFuture<Void> subscribedCF = new CompletableFuture<>();
+        final Consumer<Where> throwing;
+        ThrowingBodyPublisher(Consumer<Where> throwing, BodyPublisher publisher) {
+            this.throwing = throwing;
+            this.publisher = publisher;
+        }
+
+        @Override
+        public long contentLength() {
+            return publisher.contentLength();
+        }
+
+        @Override
+        public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
+            try {
+                throwing.accept(Where.BEFORE_SUBSCRIBE);
+                publisher.subscribe(new SubscriberWrapper(subscriber));
+                subscribedCF.complete(null);
+                throwing.accept(Where.AFTER_SUBSCRIBE);
+            } catch (Throwable t) {
+                subscribedCF.completeExceptionally(t);
+                throw t;
+            }
+        }
+
+        CompletableFuture<Void> subscribedCF() {
+            return subscribedCF;
+        }
+
+        class SubscriptionWrapper implements Flow.Subscription {
+            final Flow.Subscription subscription;
+            final AtomicLong requestCount = new AtomicLong();
+            SubscriptionWrapper(Flow.Subscription subscription) {
+                this.subscription = subscription;
+            }
+            @Override
+            public void request(long n) {
+                long count = requestCount.incrementAndGet();
+                System.out.printf("%s request-%d(%d)%n", now(), count, n);
+                if (count > 1) throwing.accept(Where.BEFORE_NEXT_REQUEST);
+                throwing.accept(Where.BEFORE_REQUEST);
+                subscription.request(n);
+                throwing.accept(Where.AFTER_REQUEST);
+                if (count > 1) throwing.accept(Where.AFTER_NEXT_REQUEST);
+            }
+
+            @Override
+            public void cancel() {
+                throwing.accept(Where.BEFORE_CANCEL);
+                subscription.cancel();
+                throwing.accept(Where.AFTER_CANCEL);
+            }
+        }
+
+        class SubscriberWrapper implements Flow.Subscriber<ByteBuffer> {
+            final Flow.Subscriber<? super ByteBuffer> subscriber;
+            SubscriberWrapper(Flow.Subscriber<? super ByteBuffer> subscriber) {
+                this.subscriber = subscriber;
+            }
+            @Override
+            public void onSubscribe(Flow.Subscription subscription) {
+                subscriber.onSubscribe(new SubscriptionWrapper(subscription));
+            }
+            @Override
+            public void onNext(ByteBuffer item) {
+                subscriber.onNext(item);
+            }
+            @Override
+            public void onComplete() {
+                subscriber.onComplete();
+            }
+
+            @Override
+            public void onError(Throwable throwable) {
+                subscriber.onError(throwable);
+            }
+        }
+    }
+
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+
+        // HTTP/1.1
+        HttpTestHandler h1_fixedLengthHandler = new HTTP_FixedLengthHandler();
+        HttpTestHandler h1_chunkHandler = new HTTP_ChunkedHandler();
+        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
+        httpTestServer.addHandler(h1_fixedLengthHandler, "/http1/fixed");
+        httpTestServer.addHandler(h1_chunkHandler, "/http1/chunk");
+        httpURI_fixed = "http://" + httpTestServer.serverAuthority() + "/http1/fixed/x";
+        httpURI_chunk = "http://" + httpTestServer.serverAuthority() + "/http1/chunk/x";
+
+        HttpsServer httpsServer = HttpsServer.create(sa, 0);
+        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
+        httpsTestServer = HttpTestServer.of(httpsServer);
+        httpsTestServer.addHandler(h1_fixedLengthHandler, "/https1/fixed");
+        httpsTestServer.addHandler(h1_chunkHandler, "/https1/chunk");
+        httpsURI_fixed = "https://" + httpsTestServer.serverAuthority() + "/https1/fixed/x";
+        httpsURI_chunk = "https://" + httpsTestServer.serverAuthority() + "/https1/chunk/x";
+
+        // HTTP/2
+        HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
+        HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
+
+        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
+        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
+        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
+        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
+        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
+
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
+        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
+        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
+        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
+        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
+
+        serverCount.addAndGet(4);
+        httpTestServer.start();
+        httpsTestServer.start();
+        http2TestServer.start();
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        String sharedClientName =
+                sharedClient == null ? null : sharedClient.toString();
+        sharedClient = null;
+        Thread.sleep(100);
+        AssertionError fail = TRACKER.check(500);
+        try {
+            httpTestServer.stop();
+            httpsTestServer.stop();
+            http2TestServer.stop();
+            https2TestServer.stop();
+        } finally {
+            if (fail != null) {
+                if (sharedClientName != null) {
+                    System.err.println("Shared client name is: " + sharedClientName);
+                }
+                throw fail;
+            }
+        }
+    }
+
+    static class HTTP_FixedLengthHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
+            byte[] resp;
+            try (InputStream is = t.getRequestBody()) {
+                resp = is.readAllBytes();
+            }
+            t.sendResponseHeaders(200, resp.length);  //fixed content length
+            try (OutputStream os = t.getResponseBody()) {
+                os.write(resp);
+            }
+        }
+    }
+
+    static class HTTP_ChunkedHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
+            byte[] resp;
+            try (InputStream is = t.getRequestBody()) {
+                resp = is.readAllBytes();
+            }
+            t.sendResponseHeaders(200, -1); // chunked/variable
+            try (OutputStream os = t.getResponseBody()) {
+                os.write(resp);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/AbstractThrowingPushPromises.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,776 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true AbstractThrowingPushPromises
+ */
+
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.net.ssl.SSLContext;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandler;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.net.http.HttpResponse.BodySubscriber;
+import java.net.http.HttpResponse.PushPromiseHandler;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Flow;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.System.out;
+import static java.lang.System.err;
+import static java.lang.String.format;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public abstract class AbstractThrowingPushPromises implements HttpServerAdapters {
+
+    SSLContext sslContext;
+    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
+    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
+    String http2URI_fixed;
+    String http2URI_chunk;
+    String https2URI_fixed;
+    String https2URI_chunk;
+
+    static final int ITERATION_COUNT = 1;
+    // a shared executor helps reduce the amount of threads created by the test
+    static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
+    static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
+    static volatile boolean tasksFailed;
+    static final AtomicLong serverCount = new AtomicLong();
+    static final AtomicLong clientCount = new AtomicLong();
+    static final long start = System.nanoTime();
+    public static String now() {
+        long now = System.nanoTime() - start;
+        long secs = now / 1000_000_000;
+        long mill = (now % 1000_000_000) / 1000_000;
+        long nan = now % 1000_000;
+        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
+    }
+
+    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
+    private volatile HttpClient sharedClient;
+
+    static class TestExecutor implements Executor {
+        final AtomicLong tasks = new AtomicLong();
+        Executor executor;
+        TestExecutor(Executor executor) {
+            this.executor = executor;
+        }
+
+        @Override
+        public void execute(Runnable command) {
+            long id = tasks.incrementAndGet();
+            executor.execute(() -> {
+                try {
+                    command.run();
+                } catch (Throwable t) {
+                    tasksFailed = true;
+                    out.printf(now() + "Task %s failed: %s%n", id, t);
+                    err.printf(now() + "Task %s failed: %s%n", id, t);
+                    FAILURES.putIfAbsent("Task " + id, t);
+                    throw t;
+                }
+            });
+        }
+    }
+
+    @AfterClass
+    static final void printFailedTests() {
+        out.println("\n=========================");
+        try {
+            out.printf("%n%sCreated %d servers and %d clients%n",
+                    now(), serverCount.get(), clientCount.get());
+            if (FAILURES.isEmpty()) return;
+            out.println("Failed tests: ");
+            FAILURES.entrySet().forEach((e) -> {
+                out.printf("\t%s: %s%n", e.getKey(), e.getValue());
+                e.getValue().printStackTrace(out);
+                e.getValue().printStackTrace();
+            });
+            if (tasksFailed) {
+                out.println("WARNING: Some tasks failed");
+            }
+        } finally {
+            out.println("\n=========================\n");
+        }
+    }
+
+    private String[] uris() {
+        return new String[] {
+                http2URI_fixed,
+                http2URI_chunk,
+                https2URI_fixed,
+                https2URI_chunk,
+        };
+    }
+
+    @DataProvider(name = "sanity")
+    public Object[][] sanity() {
+        String[] uris = uris();
+        Object[][] result = new Object[uris.length * 2][];
+
+        int i = 0;
+        for (boolean sameClient : List.of(false, true)) {
+            for (String uri: uris()) {
+                result[i++] = new Object[] {uri, sameClient};
+            }
+        }
+        assert i == uris.length * 2;
+        return result;
+    }
+
+    enum Where {
+        BODY_HANDLER, ON_SUBSCRIBE, ON_NEXT, ON_COMPLETE, ON_ERROR, GET_BODY, BODY_CF,
+        BEFORE_ACCEPTING, AFTER_ACCEPTING;
+        public Consumer<Where> select(Consumer<Where> consumer) {
+            return new Consumer<Where>() {
+                @Override
+                public void accept(Where where) {
+                    if (Where.this == where) {
+                        consumer.accept(where);
+                    }
+                }
+            };
+        }
+    }
+
+    private Object[][] variants(List<Thrower> throwers) {
+        String[] uris = uris();
+        Object[][] result = new Object[uris.length * 2 * throwers.size()][];
+        int i = 0;
+        for (Thrower thrower : throwers) {
+            for (boolean sameClient : List.of(false, true)) {
+                for (String uri : uris()) {
+                    result[i++] = new Object[]{uri, sameClient, thrower};
+                }
+            }
+        }
+        assert i == uris.length * 2 * throwers.size();
+        return result;
+    }
+
+    @DataProvider(name = "ioVariants")
+    public Object[][] ioVariants() {
+        return variants(List.of(
+                new UncheckedIOExceptionThrower()));
+    }
+
+    @DataProvider(name = "customVariants")
+    public Object[][] customVariants() {
+        return variants(List.of(
+                new UncheckedCustomExceptionThrower()));
+    }
+
+    private HttpClient makeNewClient() {
+        clientCount.incrementAndGet();
+        return TRACKER.track(HttpClient.newBuilder()
+                .proxy(HttpClient.Builder.NO_PROXY)
+                .executor(executor)
+                .sslContext(sslContext)
+                .build());
+    }
+
+    HttpClient newHttpClient(boolean share) {
+        if (!share) return makeNewClient();
+        HttpClient shared = sharedClient;
+        if (shared != null) return shared;
+        synchronized (this) {
+            shared = sharedClient;
+            if (shared == null) {
+                shared = sharedClient = makeNewClient();
+            }
+            return shared;
+        }
+    }
+
+    // @Test(dataProvider = "sanity")
+    protected void testSanityImpl(String uri, boolean sameClient)
+            throws Exception {
+        HttpClient client = null;
+        out.printf("%ntestNoThrows(%s, %b)%n", uri, sameClient);
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient(sameClient);
+
+            HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
+                    .build();
+            BodyHandler<Stream<String>> handler =
+                    new ThrowingBodyHandler((w) -> {},
+                                            BodyHandlers.ofLines());
+            Map<HttpRequest, CompletableFuture<HttpResponse<Stream<String>>>> pushPromises =
+                    new ConcurrentHashMap<>();
+            PushPromiseHandler<Stream<String>> pushHandler = new PushPromiseHandler<>() {
+                @Override
+                public void applyPushPromise(HttpRequest initiatingRequest,
+                                             HttpRequest pushPromiseRequest,
+                                             Function<BodyHandler<Stream<String>>,
+                                                     CompletableFuture<HttpResponse<Stream<String>>>>
+                                                     acceptor) {
+                    pushPromises.putIfAbsent(pushPromiseRequest, acceptor.apply(handler));
+                }
+            };
+            HttpResponse<Stream<String>> response =
+                    client.sendAsync(req, BodyHandlers.ofLines(), pushHandler).get();
+            String body = response.body().collect(Collectors.joining("|"));
+            assertEquals(URI.create(body).getPath(), URI.create(uri).getPath());
+            for (HttpRequest promised : pushPromises.keySet()) {
+                out.printf("%s Received promise: %s%n\tresponse: %s%n",
+                        now(), promised, pushPromises.get(promised).get());
+                String promisedBody = pushPromises.get(promised).get().body()
+                        .collect(Collectors.joining("|"));
+                assertEquals(promisedBody, promised.uri().toASCIIString());
+            }
+            assertEquals(3, pushPromises.size());
+        }
+    }
+
+    // @Test(dataProvider = "variants")
+    protected void testThrowingAsStringImpl(String uri,
+                                     boolean sameClient,
+                                     Thrower thrower)
+            throws Exception
+    {
+        String test = format("testThrowingAsString(%s, %b, %s)",
+                             uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofString,
+                this::checkAsString, thrower);
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsLinesImpl(String uri,
+                                    boolean sameClient,
+                                    Thrower thrower)
+            throws Exception
+    {
+        String test =  format("testThrowingAsLines(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
+                this::checkAsLines, thrower);
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsInputStreamImpl(String uri,
+                                          boolean sameClient,
+                                          Thrower thrower)
+            throws Exception
+    {
+        String test = format("testThrowingAsInputStream(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
+                this::checkAsInputStream,  thrower);
+    }
+
+    private <T,U> void testThrowing(String name, String uri, boolean sameClient,
+                                    Supplier<BodyHandler<T>> handlers,
+                                    Finisher finisher, Thrower thrower)
+            throws Exception
+    {
+        out.printf("%n%s%s%n", now(), name);
+        try {
+            testThrowing(uri, sameClient, handlers, finisher, thrower);
+        } catch (Error | Exception x) {
+            FAILURES.putIfAbsent(name, x);
+            throw x;
+        }
+    }
+
+    private <T,U> void testThrowing(String uri, boolean sameClient,
+                                    Supplier<BodyHandler<T>> handlers,
+                                    Finisher finisher, Thrower thrower)
+            throws Exception
+    {
+        HttpClient client = null;
+        for (Where where : Where.values()) {
+            if (where == Where.ON_ERROR) continue;
+            if (!sameClient || client == null)
+                client = newHttpClient(sameClient);
+
+            HttpRequest req = HttpRequest.
+                    newBuilder(URI.create(uri))
+                    .build();
+            ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<T>>> promiseMap =
+                    new ConcurrentHashMap<>();
+            Supplier<BodyHandler<T>> throwing = () ->
+                    new ThrowingBodyHandler(where.select(thrower), handlers.get());
+            PushPromiseHandler<T> pushHandler = new ThrowingPromiseHandler<>(
+                    where.select(thrower),
+                    PushPromiseHandler.of((r) -> throwing.get(), promiseMap));
+            out.println("try throwing in " + where);
+            HttpResponse<T> response = null;
+            try {
+                response = client.sendAsync(req, handlers.get(), pushHandler).join();
+            } catch (Error | Exception x) {
+                throw x;
+            }
+            if (response != null) {
+                finisher.finish(where, req.uri(), response, thrower, promiseMap);
+            }
+        }
+    }
+
+    interface Thrower extends Consumer<Where>, Predicate<Throwable> {
+
+    }
+
+    interface Finisher<T,U> {
+        U finish(Where w, URI requestURI, HttpResponse<T> resp, Thrower thrower,
+                 Map<HttpRequest, CompletableFuture<HttpResponse<T>>> promises);
+    }
+
+    final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
+        String msg = "Expected exception not thrown in " + w
+                + "\n\tReceived: " + resp
+                + "\n\tWith body: " + resp.body();
+        System.out.println(msg);
+        throw new RuntimeException(msg);
+    }
+
+    final List<String> checkAsString(Where w, URI reqURI,
+                                    HttpResponse<String> resp,
+                                    Thrower thrower,
+                                    Map<HttpRequest, CompletableFuture<HttpResponse<String>>> promises) {
+        Function<HttpResponse<String>, List<String>> extractor =
+                (r) -> List.of(r.body());
+        return check(w, reqURI, resp, thrower, promises, extractor);
+    }
+
+    final List<String> checkAsLines(Where w, URI reqURI,
+                                    HttpResponse<Stream<String>> resp,
+                                    Thrower thrower,
+                                    Map<HttpRequest, CompletableFuture<HttpResponse<Stream<String>>>> promises) {
+        Function<HttpResponse<Stream<String>>, List<String>> extractor =
+                (r) -> r.body().collect(Collectors.toList());
+        return check(w, reqURI, resp, thrower, promises, extractor);
+    }
+
+    final List<String> checkAsInputStream(Where w, URI reqURI,
+                                          HttpResponse<InputStream> resp,
+                                          Thrower thrower,
+                                          Map<HttpRequest, CompletableFuture<HttpResponse<InputStream>>> promises)
+    {
+        Function<HttpResponse<InputStream>, List<String>> extractor = (r) -> {
+            List<String> result;
+            try (InputStream is = r.body()) {
+                result = new BufferedReader(new InputStreamReader(is))
+                        .lines().collect(Collectors.toList());
+            } catch (Throwable t) {
+                throw new CompletionException(t);
+            }
+            return result;
+        };
+        return check(w, reqURI, resp, thrower, promises, extractor);
+    }
+
+    private final <T> List<String> check(Where w, URI reqURI,
+                                 HttpResponse<T> resp,
+                                 Thrower thrower,
+                                 Map<HttpRequest, CompletableFuture<HttpResponse<T>>> promises,
+                                 Function<HttpResponse<T>, List<String>> extractor)
+    {
+        List<String> result = extractor.apply(resp);
+        for (HttpRequest req : promises.keySet()) {
+            switch (w) {
+                case BEFORE_ACCEPTING:
+                    throw new RuntimeException("No push promise should have been received" +
+                            " for " + reqURI + " in " + w + ": got " + promises.keySet());
+                default:
+                    break;
+            }
+            HttpResponse<T> presp;
+            try {
+                presp = promises.get(req).join();
+            } catch (Error | Exception x) {
+                Throwable cause = findCause(x, thrower);
+                if (cause != null) {
+                    out.println(now() + "Got expected exception in "
+                            + w + ": " + cause);
+                    continue;
+                }
+                throw x;
+            }
+            switch (w) {
+                case BEFORE_ACCEPTING:
+                case AFTER_ACCEPTING:
+                case BODY_HANDLER:
+                case GET_BODY:
+                case BODY_CF:
+                    return shouldHaveThrown(w, presp, thrower);
+                default:
+                    break;
+            }
+            List<String> presult = null;
+            try {
+                presult = extractor.apply(presp);
+            } catch (Error | Exception x) {
+                Throwable cause = findCause(x, thrower);
+                if (cause != null) {
+                    out.println(now() + "Got expected exception for "
+                            + req + " in " + w + ": " + cause);
+                    continue;
+                }
+                throw x;
+            }
+            throw new RuntimeException("Expected exception not thrown for "
+                    + req + " in " + w);
+        }
+        final int expectedCount;
+        switch (w) {
+            case BEFORE_ACCEPTING:
+                expectedCount = 0;
+                break;
+            default:
+                expectedCount = 3;
+        }
+        assertEquals(promises.size(), expectedCount,
+                "bad promise count for " + reqURI + " with " + w);
+        assertEquals(result, List.of(reqURI.toASCIIString()));
+        return result;
+    }
+
+    private static Throwable findCause(Throwable x,
+                                       Predicate<Throwable> filter) {
+        while (x != null && !filter.test(x)) x = x.getCause();
+        return x;
+    }
+
+    static final class UncheckedCustomExceptionThrower implements Thrower {
+        @Override
+        public void accept(Where where) {
+            out.println(now() + "Throwing in " + where);
+            throw new UncheckedCustomException(where.name());
+        }
+
+        @Override
+        public boolean test(Throwable throwable) {
+            return UncheckedCustomException.class.isInstance(throwable);
+        }
+
+        @Override
+        public String toString() {
+            return "UncheckedCustomExceptionThrower";
+        }
+    }
+
+    static final class UncheckedIOExceptionThrower implements Thrower {
+        @Override
+        public void accept(Where where) {
+            out.println(now() + "Throwing in " + where);
+            throw new UncheckedIOException(new CustomIOException(where.name()));
+        }
+
+        @Override
+        public boolean test(Throwable throwable) {
+            return UncheckedIOException.class.isInstance(throwable)
+                    && CustomIOException.class.isInstance(throwable.getCause());
+        }
+
+        @Override
+        public String toString() {
+            return "UncheckedIOExceptionThrower";
+        }
+    }
+
+    static final class UncheckedCustomException extends RuntimeException {
+        UncheckedCustomException(String message) {
+            super(message);
+        }
+        UncheckedCustomException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    static final class CustomIOException extends IOException {
+        CustomIOException(String message) {
+            super(message);
+        }
+        CustomIOException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    static final class ThrowingPromiseHandler<T> implements PushPromiseHandler<T> {
+        final Consumer<Where> throwing;
+        final PushPromiseHandler<T> pushHandler;
+        ThrowingPromiseHandler(Consumer<Where> throwing, PushPromiseHandler<T> pushHandler) {
+            this.throwing = throwing;
+            this.pushHandler = pushHandler;
+        }
+
+        @Override
+        public void applyPushPromise(HttpRequest initiatingRequest,
+                                     HttpRequest pushPromiseRequest,
+                                     Function<BodyHandler<T>,
+                                             CompletableFuture<HttpResponse<T>>> acceptor) {
+            throwing.accept(Where.BEFORE_ACCEPTING);
+            pushHandler.applyPushPromise(initiatingRequest, pushPromiseRequest, acceptor);
+            throwing.accept(Where.AFTER_ACCEPTING);
+        }
+    }
+
+    static final class ThrowingBodyHandler<T> implements BodyHandler<T> {
+        final Consumer<Where> throwing;
+        final BodyHandler<T> bodyHandler;
+        ThrowingBodyHandler(Consumer<Where> throwing, BodyHandler<T> bodyHandler) {
+            this.throwing = throwing;
+            this.bodyHandler = bodyHandler;
+        }
+        @Override
+        public BodySubscriber<T> apply(HttpResponse.ResponseInfo rinfo) {
+            throwing.accept(Where.BODY_HANDLER);
+            BodySubscriber<T> subscriber = bodyHandler.apply(rinfo);
+            return new ThrowingBodySubscriber(throwing, subscriber);
+        }
+    }
+
+    static final class ThrowingBodySubscriber<T> implements BodySubscriber<T> {
+        private final BodySubscriber<T> subscriber;
+        volatile boolean onSubscribeCalled;
+        final Consumer<Where> throwing;
+        ThrowingBodySubscriber(Consumer<Where> throwing, BodySubscriber<T> subscriber) {
+            this.throwing = throwing;
+            this.subscriber = subscriber;
+        }
+
+        @Override
+        public void onSubscribe(Flow.Subscription subscription) {
+            //out.println("onSubscribe ");
+            onSubscribeCalled = true;
+            throwing.accept(Where.ON_SUBSCRIBE);
+            subscriber.onSubscribe(subscription);
+        }
+
+        @Override
+        public void onNext(List<ByteBuffer> item) {
+           // out.println("onNext " + item);
+            assertTrue(onSubscribeCalled);
+            throwing.accept(Where.ON_NEXT);
+            subscriber.onNext(item);
+        }
+
+        @Override
+        public void onError(Throwable throwable) {
+            //out.println("onError");
+            assertTrue(onSubscribeCalled);
+            throwing.accept(Where.ON_ERROR);
+            subscriber.onError(throwable);
+        }
+
+        @Override
+        public void onComplete() {
+            //out.println("onComplete");
+            assertTrue(onSubscribeCalled, "onComplete called before onSubscribe");
+            throwing.accept(Where.ON_COMPLETE);
+            subscriber.onComplete();
+        }
+
+        @Override
+        public CompletionStage<T> getBody() {
+            throwing.accept(Where.GET_BODY);
+            try {
+                throwing.accept(Where.BODY_CF);
+            } catch (Throwable t) {
+                return CompletableFuture.failedFuture(t);
+            }
+            return subscriber.getBody();
+        }
+    }
+
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+
+        // HTTP/2
+        HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
+        HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
+
+        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
+        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
+        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
+        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
+        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
+
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
+        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
+        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
+        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
+        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
+
+        serverCount.addAndGet(2);
+        http2TestServer.start();
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        String sharedClientName =
+                sharedClient == null ? null : sharedClient.toString();
+        sharedClient = null;
+        Thread.sleep(100);
+        AssertionError fail = TRACKER.check(500);
+        try {
+            http2TestServer.stop();
+            https2TestServer.stop();
+        } finally {
+            if (fail != null) {
+                if (sharedClientName != null) {
+                    System.err.println("Shared client name is: " + sharedClientName);
+                }
+                throw fail;
+            }
+        }
+    }
+
+    static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
+    private static void pushPromiseFor(HttpTestExchange t,
+                                       URI requestURI,
+                                       String pushPath,
+                                       boolean fixed)
+        throws IOException
+    {
+        try {
+            URI promise = new URI(requestURI.getScheme(),
+                    requestURI.getAuthority(),
+                    pushPath, null, null);
+            byte[] promiseBytes = promise.toASCIIString().getBytes(UTF_8);
+            out.printf("TestServer: %s Pushing promise: %s%n", now(), promise);
+            err.printf("TestServer: %s Pushing promise: %s%n", now(), promise);
+            HttpHeaders headers;
+            if (fixed) {
+                String length = String.valueOf(promiseBytes.length);
+                headers = HttpHeaders.of(Map.of("Content-Length", List.of(length)),
+                                         ACCEPT_ALL);
+            } else {
+                headers = HttpHeaders.of(Map.of(), ACCEPT_ALL); // empty
+            }
+            t.serverPush(promise, headers, promiseBytes);
+        } catch (URISyntaxException x) {
+            throw new IOException(x.getMessage(), x);
+        }
+    }
+
+    static class HTTP_FixedLengthHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
+            try (InputStream is = t.getRequestBody()) {
+                is.readAllBytes();
+            }
+            URI requestURI = t.getRequestURI();
+            for (int i = 1; i<2; i++) {
+                String path = requestURI.getPath() + "/before/promise-" + i;
+                pushPromiseFor(t, requestURI, path, true);
+            }
+            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
+            t.sendResponseHeaders(200, resp.length);  //fixed content length
+            try (OutputStream os = t.getResponseBody()) {
+                int bytes = resp.length/3;
+                for (int i = 0; i<2; i++) {
+                    String path = requestURI.getPath() + "/after/promise-" + (i + 2);
+                    os.write(resp, i * bytes, bytes);
+                    os.flush();
+                    pushPromiseFor(t, requestURI, path, true);
+                }
+                os.write(resp, 2*bytes, resp.length - 2*bytes);
+            }
+        }
+
+    }
+
+    static class HTTP_ChunkedHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
+            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
+            try (InputStream is = t.getRequestBody()) {
+                is.readAllBytes();
+            }
+            URI requestURI = t.getRequestURI();
+            for (int i = 1; i<2; i++) {
+                String path = requestURI.getPath() + "/before/promise-" + i;
+                pushPromiseFor(t, requestURI, path, false);
+            }
+            t.sendResponseHeaders(200, -1); // chunked/variable
+            try (OutputStream os = t.getResponseBody()) {
+                int bytes = resp.length/3;
+                for (int i = 0; i<2; i++) {
+                    String path = requestURI.getPath() + "/after/promise-" + (i + 2);
+                    os.write(resp, i * bytes, bytes);
+                    os.flush();
+                    pushPromiseFor(t, requestURI, path, false);
+                }
+                os.write(resp, 2*bytes, resp.length - 2*bytes);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/AbstractThrowingSubscribers.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,733 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.net.ssl.SSLContext;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandler;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.net.http.HttpResponse.BodySubscriber;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Flow;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.System.out;
+import static java.lang.String.format;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public abstract class AbstractThrowingSubscribers implements HttpServerAdapters {
+
+    SSLContext sslContext;
+    HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
+    HttpTestServer httpsTestServer;   // HTTPS/1.1
+    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
+    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
+    String httpURI_fixed;
+    String httpURI_chunk;
+    String httpsURI_fixed;
+    String httpsURI_chunk;
+    String http2URI_fixed;
+    String http2URI_chunk;
+    String https2URI_fixed;
+    String https2URI_chunk;
+
+    static final int ITERATION_COUNT = 1;
+    // a shared executor helps reduce the amount of threads created by the test
+    static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
+    static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
+    static volatile boolean tasksFailed;
+    static final AtomicLong serverCount = new AtomicLong();
+    static final AtomicLong clientCount = new AtomicLong();
+    static final long start = System.nanoTime();
+    public static String now() {
+        long now = System.nanoTime() - start;
+        long secs = now / 1000_000_000;
+        long mill = (now % 1000_000_000) / 1000_000;
+        long nan = now % 1000_000;
+        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
+    }
+
+    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
+    private volatile HttpClient sharedClient;
+
+    static class TestExecutor implements Executor {
+        final AtomicLong tasks = new AtomicLong();
+        Executor executor;
+        TestExecutor(Executor executor) {
+            this.executor = executor;
+        }
+
+        @Override
+        public void execute(Runnable command) {
+            long id = tasks.incrementAndGet();
+            executor.execute(() -> {
+                try {
+                    command.run();
+                } catch (Throwable t) {
+                    tasksFailed = true;
+                    System.out.printf(now() + "Task %s failed: %s%n", id, t);
+                    System.err.printf(now() + "Task %s failed: %s%n", id, t);
+                    FAILURES.putIfAbsent("Task " + id, t);
+                    throw t;
+                }
+            });
+        }
+    }
+
+    @AfterClass
+    static final void printFailedTests() {
+        out.println("\n=========================");
+        try {
+            out.printf("%n%sCreated %d servers and %d clients%n",
+                    now(), serverCount.get(), clientCount.get());
+            if (FAILURES.isEmpty()) return;
+            out.println("Failed tests: ");
+            FAILURES.entrySet().forEach((e) -> {
+                out.printf("\t%s: %s%n", e.getKey(), e.getValue());
+                e.getValue().printStackTrace(out);
+                e.getValue().printStackTrace();
+            });
+            if (tasksFailed) {
+                System.out.println("WARNING: Some tasks failed");
+            }
+        } finally {
+            out.println("\n=========================\n");
+        }
+    }
+
+    private String[] uris() {
+        return new String[] {
+                httpURI_fixed,
+                httpURI_chunk,
+                httpsURI_fixed,
+                httpsURI_chunk,
+                http2URI_fixed,
+                http2URI_chunk,
+                https2URI_fixed,
+                https2URI_chunk,
+        };
+    }
+
+    static AtomicLong URICOUNT = new AtomicLong();
+
+    @DataProvider(name = "sanity")
+    public Object[][] sanity() {
+        String[] uris = uris();
+        Object[][] result = new Object[uris.length * 2][];
+        int i = 0;
+        for (boolean sameClient : List.of(false, true)) {
+            for (String uri: uris()) {
+                result[i++] = new Object[] {uri, sameClient};
+            }
+        }
+        assert i == uris.length * 2;
+        return result;
+    }
+
+    @DataProvider(name = "variants")
+    public Object[][] variants() {
+        String[] uris = uris();
+        Object[][] result = new Object[uris.length * 2 * 2][];
+        int i = 0;
+        for (Thrower thrower : List.of(
+                new UncheckedIOExceptionThrower(),
+                new UncheckedCustomExceptionThrower())) {
+            for (boolean sameClient : List.of(false, true)) {
+                for (String uri : uris()) {
+                    result[i++] = new Object[]{uri, sameClient, thrower};
+                }
+            }
+        }
+        assert i == uris.length * 2 * 2;
+        return result;
+    }
+
+    private HttpClient makeNewClient() {
+        clientCount.incrementAndGet();
+        HttpClient client =  HttpClient.newBuilder()
+                .proxy(HttpClient.Builder.NO_PROXY)
+                .executor(executor)
+                .sslContext(sslContext)
+                .build();
+        return TRACKER.track(client);
+    }
+
+    HttpClient newHttpClient(boolean share) {
+        if (!share) return makeNewClient();
+        HttpClient shared = sharedClient;
+        if (shared != null) return shared;
+        synchronized (this) {
+            shared = sharedClient;
+            if (shared == null) {
+                shared = sharedClient = makeNewClient();
+            }
+            return shared;
+        }
+    }
+
+    enum SubscriberType {
+        INLINE,  // In line subscribers complete their CF on ON_COMPLETE
+                 // e.g. BodySubscribers::ofString
+        OFFLINE; // Off line subscribers complete their CF immediately
+                 // but require the client to pull the data after the
+                 // CF completes (e.g. BodySubscribers::ofInputStream)
+    }
+
+    static EnumSet<Where> excludes(SubscriberType type) {
+        EnumSet<Where> set = EnumSet.noneOf(Where.class);
+
+        if (type == SubscriberType.OFFLINE) {
+            // Throwing on onSubscribe needs some more work
+            // for the case of InputStream, where the body has already
+            // completed by the time the subscriber is subscribed.
+            // The only way we have at that point to relay the exception
+            // is to call onError on the subscriber, but should we if
+            // Subscriber::onSubscribed has thrown an exception and
+            // not completed normally?
+            set.add(Where.ON_SUBSCRIBE);
+        }
+
+        // Don't know how to make the stack reliably cause onError
+        // to be called without closing the connection.
+        // And how do we get the exception if onError throws anyway?
+        set.add(Where.ON_ERROR);
+
+        return set;
+    }
+
+    //@Test(dataProvider = "sanity")
+    protected void testSanityImpl(String uri, boolean sameClient)
+            throws Exception {
+        HttpClient client = null;
+        String uri2 = uri + "-" + URICOUNT.incrementAndGet() + "/sanity";
+        out.printf("%ntestSanity(%s, %b)%n", uri2, sameClient);
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient(sameClient);
+
+            HttpRequest req = HttpRequest.newBuilder(URI.create(uri2))
+                    .build();
+            BodyHandler<String> handler =
+                    new ThrowingBodyHandler((w) -> {},
+                                            BodyHandlers.ofString());
+            HttpResponse<String> response = client.send(req, handler);
+            String body = response.body();
+            assertEquals(URI.create(body).getPath(), URI.create(uri2).getPath());
+        }
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsStringImpl(String uri,
+                                     boolean sameClient,
+                                     Thrower thrower)
+            throws Exception
+    {
+        uri = uri + "-" + URICOUNT.incrementAndGet();
+        String test = format("testThrowingAsString(%s, %b, %s)",
+                             uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofString,
+                this::shouldHaveThrown, thrower,false,
+                excludes(SubscriberType.INLINE));
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsLinesImpl(String uri,
+                                    boolean sameClient,
+                                    Thrower thrower)
+            throws Exception
+    {
+        uri = uri + "-" + URICOUNT.incrementAndGet();
+        String test =  format("testThrowingAsLines(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
+                this::checkAsLines, thrower,false,
+                excludes(SubscriberType.OFFLINE));
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsInputStreamImpl(String uri,
+                                          boolean sameClient,
+                                          Thrower thrower)
+            throws Exception
+    {
+        uri = uri + "-" + URICOUNT.incrementAndGet();
+        String test = format("testThrowingAsInputStream(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
+                this::checkAsInputStream,  thrower,false,
+                excludes(SubscriberType.OFFLINE));
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsStringAsyncImpl(String uri,
+                                          boolean sameClient,
+                                          Thrower thrower)
+            throws Exception
+    {
+        uri = uri + "-" + URICOUNT.incrementAndGet();
+        String test = format("testThrowingAsStringAsync(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofString,
+                     this::shouldHaveThrown, thrower, true,
+                excludes(SubscriberType.INLINE));
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsLinesAsyncImpl(String uri,
+                                         boolean sameClient,
+                                         Thrower thrower)
+            throws Exception
+    {
+        uri = uri + "-" + URICOUNT.incrementAndGet();
+        String test = format("testThrowingAsLinesAsync(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
+                this::checkAsLines, thrower,true,
+                excludes(SubscriberType.OFFLINE));
+    }
+
+    //@Test(dataProvider = "variants")
+    protected void testThrowingAsInputStreamAsyncImpl(String uri,
+                                               boolean sameClient,
+                                               Thrower thrower)
+            throws Exception
+    {
+        uri = uri + "-" + URICOUNT.incrementAndGet();
+        String test = format("testThrowingAsInputStreamAsync(%s, %b, %s)",
+                uri, sameClient, thrower);
+        testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
+                this::checkAsInputStream, thrower,true,
+                excludes(SubscriberType.OFFLINE));
+    }
+
+    private <T,U> void testThrowing(String name, String uri, boolean sameClient,
+                                    Supplier<BodyHandler<T>> handlers,
+                                    Finisher finisher, Thrower thrower,
+                                    boolean async, EnumSet<Where> excludes)
+            throws Exception
+    {
+        out.printf("%n%s%s%n", now(), name);
+        try {
+            testThrowing(uri, sameClient, handlers, finisher, thrower, async, excludes);
+        } catch (Error | Exception x) {
+            FAILURES.putIfAbsent(name, x);
+            throw x;
+        }
+    }
+
+    private <T,U> void testThrowing(String uri, boolean sameClient,
+                                    Supplier<BodyHandler<T>> handlers,
+                                    Finisher finisher, Thrower thrower,
+                                    boolean async,
+                                    EnumSet<Where> excludes)
+            throws Exception
+    {
+        HttpClient client = null;
+        for (Where where : EnumSet.complementOf(excludes)) {
+
+            if (!sameClient || client == null)
+                client = newHttpClient(sameClient);
+            String uri2 = uri + "-" + where;
+            HttpRequest req = HttpRequest.
+                    newBuilder(URI.create(uri2))
+                    .build();
+            BodyHandler<T> handler =
+                    new ThrowingBodyHandler(where.select(thrower), handlers.get());
+            System.out.println("try throwing in " + where);
+            HttpResponse<T> response = null;
+            if (async) {
+                try {
+                    response = client.sendAsync(req, handler).join();
+                } catch (Error | Exception x) {
+                    Throwable cause = findCause(x, thrower);
+                    if (cause == null) throw causeNotFound(where, x);
+                    System.out.println(now() + "Got expected exception: " + cause);
+                }
+            } else {
+                try {
+                    response = client.send(req, handler);
+                } catch (Error | Exception t) {
+                    // synchronous send will rethrow exceptions
+                    Throwable throwable = t.getCause();
+                    assert throwable != null;
+
+                    if (thrower.test(throwable)) {
+                        System.out.println(now() + "Got expected exception: " + throwable);
+                    } else throw causeNotFound(where, t);
+                }
+            }
+            if (response != null) {
+                finisher.finish(where, response, thrower);
+            }
+        }
+    }
+
+    enum Where {
+        BODY_HANDLER, ON_SUBSCRIBE, ON_NEXT, ON_COMPLETE, ON_ERROR, GET_BODY, BODY_CF;
+        public Consumer<Where> select(Consumer<Where> consumer) {
+            return new Consumer<Where>() {
+                @Override
+                public void accept(Where where) {
+                    if (Where.this == where) {
+                        consumer.accept(where);
+                    }
+                }
+            };
+        }
+    }
+
+    static AssertionError causeNotFound(Where w, Throwable t) {
+        return new AssertionError("Expected exception not found in " + w, t);
+    }
+
+    interface Thrower extends Consumer<Where>, Predicate<Throwable> {
+
+    }
+
+    interface Finisher<T,U> {
+        U finish(Where w, HttpResponse<T> resp, Thrower thrower) throws IOException;
+    }
+
+    final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
+        String msg = "Expected exception not thrown in " + w
+                + "\n\tReceived: " + resp
+                + "\n\tWith body: " + resp.body();
+        System.out.println(msg);
+        throw new RuntimeException(msg);
+    }
+
+    final List<String> checkAsLines(Where w, HttpResponse<Stream<String>> resp, Thrower thrower) {
+        switch(w) {
+            case BODY_HANDLER: return shouldHaveThrown(w, resp, thrower);
+            case GET_BODY: return shouldHaveThrown(w, resp, thrower);
+            case BODY_CF: return shouldHaveThrown(w, resp, thrower);
+            default: break;
+        }
+        List<String> result = null;
+        try {
+            result = resp.body().collect(Collectors.toList());
+        } catch (Error | Exception x) {
+            Throwable cause = findCause(x, thrower);
+            if (cause != null) {
+                out.println(now() + "Got expected exception in " + w + ": " + cause);
+                return result;
+            }
+            throw causeNotFound(w, x);
+        }
+        return shouldHaveThrown(w, resp, thrower);
+    }
+
+    final List<String> checkAsInputStream(Where w, HttpResponse<InputStream> resp,
+                                    Thrower thrower)
+            throws IOException
+    {
+        switch(w) {
+            case BODY_HANDLER: return shouldHaveThrown(w, resp, thrower);
+            case GET_BODY: return shouldHaveThrown(w, resp, thrower);
+            case BODY_CF: return shouldHaveThrown(w, resp, thrower);
+            default: break;
+        }
+        List<String> result = null;
+        try (InputStreamReader r1 = new InputStreamReader(resp.body(), UTF_8);
+             BufferedReader r = new BufferedReader(r1)) {
+            try {
+                result = r.lines().collect(Collectors.toList());
+            } catch (Error | Exception x) {
+                Throwable cause = findCause(x, thrower);
+                if (cause != null) {
+                    out.println(now() + "Got expected exception in " + w + ": " + cause);
+                    return result;
+                }
+                throw causeNotFound(w, x);
+            }
+        }
+        return shouldHaveThrown(w, resp, thrower);
+    }
+
+    private static Throwable findCause(Throwable x,
+                                       Predicate<Throwable> filter) {
+        while (x != null && !filter.test(x)) x = x.getCause();
+        return x;
+    }
+
+    static final class UncheckedCustomExceptionThrower implements Thrower {
+        @Override
+        public void accept(Where where) {
+            out.println(now() + "Throwing in " + where);
+            throw new UncheckedCustomException(where.name());
+        }
+
+        @Override
+        public boolean test(Throwable throwable) {
+            return UncheckedCustomException.class.isInstance(throwable);
+        }
+
+        @Override
+        public String toString() {
+            return "UncheckedCustomExceptionThrower";
+        }
+    }
+
+    static final class UncheckedIOExceptionThrower implements Thrower {
+        @Override
+        public void accept(Where where) {
+            out.println(now() + "Throwing in " + where);
+            throw new UncheckedIOException(new CustomIOException(where.name()));
+        }
+
+        @Override
+        public boolean test(Throwable throwable) {
+            return UncheckedIOException.class.isInstance(throwable)
+                    && CustomIOException.class.isInstance(throwable.getCause());
+        }
+
+        @Override
+        public String toString() {
+            return "UncheckedIOExceptionThrower";
+        }
+    }
+
+    static final class UncheckedCustomException extends RuntimeException {
+        UncheckedCustomException(String message) {
+            super(message);
+        }
+        UncheckedCustomException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    static final class CustomIOException extends IOException {
+        CustomIOException(String message) {
+            super(message);
+        }
+        CustomIOException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    static final class ThrowingBodyHandler<T> implements BodyHandler<T> {
+        final Consumer<Where> throwing;
+        final BodyHandler<T> bodyHandler;
+        ThrowingBodyHandler(Consumer<Where> throwing, BodyHandler<T> bodyHandler) {
+            this.throwing = throwing;
+            this.bodyHandler = bodyHandler;
+        }
+        @Override
+        public BodySubscriber<T> apply(HttpResponse.ResponseInfo rinfo) {
+            throwing.accept(Where.BODY_HANDLER);
+            BodySubscriber<T> subscriber = bodyHandler.apply(rinfo);
+            return new ThrowingBodySubscriber(throwing, subscriber);
+        }
+    }
+
+    static final class ThrowingBodySubscriber<T> implements BodySubscriber<T> {
+        private final BodySubscriber<T> subscriber;
+        volatile boolean onSubscribeCalled;
+        final Consumer<Where> throwing;
+        ThrowingBodySubscriber(Consumer<Where> throwing, BodySubscriber<T> subscriber) {
+            this.throwing = throwing;
+            this.subscriber = subscriber;
+        }
+
+        @Override
+        public void onSubscribe(Flow.Subscription subscription) {
+            //out.println("onSubscribe ");
+            onSubscribeCalled = true;
+            throwing.accept(Where.ON_SUBSCRIBE);
+            subscriber.onSubscribe(subscription);
+        }
+
+        @Override
+        public void onNext(List<ByteBuffer> item) {
+           // out.println("onNext " + item);
+            assertTrue(onSubscribeCalled);
+            throwing.accept(Where.ON_NEXT);
+            subscriber.onNext(item);
+        }
+
+        @Override
+        public void onError(Throwable throwable) {
+            //out.println("onError");
+            assertTrue(onSubscribeCalled);
+            throwing.accept(Where.ON_ERROR);
+            subscriber.onError(throwable);
+        }
+
+        @Override
+        public void onComplete() {
+            //out.println("onComplete");
+            assertTrue(onSubscribeCalled, "onComplete called before onSubscribe");
+            throwing.accept(Where.ON_COMPLETE);
+            subscriber.onComplete();
+        }
+
+        @Override
+        public CompletionStage<T> getBody() {
+            throwing.accept(Where.GET_BODY);
+            try {
+                throwing.accept(Where.BODY_CF);
+            } catch (Throwable t) {
+                return CompletableFuture.failedFuture(t);
+            }
+            return subscriber.getBody();
+        }
+    }
+
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+
+        // HTTP/1.1
+        HttpTestHandler h1_fixedLengthHandler = new HTTP_FixedLengthHandler();
+        HttpTestHandler h1_chunkHandler = new HTTP_ChunkedHandler();
+        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
+        httpTestServer.addHandler(h1_fixedLengthHandler, "/http1/fixed");
+        httpTestServer.addHandler(h1_chunkHandler, "/http1/chunk");
+        httpURI_fixed = "http://" + httpTestServer.serverAuthority() + "/http1/fixed/x";
+        httpURI_chunk = "http://" + httpTestServer.serverAuthority() + "/http1/chunk/x";
+
+        HttpsServer httpsServer = HttpsServer.create(sa, 0);
+        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
+        httpsTestServer = HttpTestServer.of(httpsServer);
+        httpsTestServer.addHandler(h1_fixedLengthHandler, "/https1/fixed");
+        httpsTestServer.addHandler(h1_chunkHandler, "/https1/chunk");
+        httpsURI_fixed = "https://" + httpsTestServer.serverAuthority() + "/https1/fixed/x";
+        httpsURI_chunk = "https://" + httpsTestServer.serverAuthority() + "/https1/chunk/x";
+
+        // HTTP/2
+        HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
+        HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
+
+        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
+        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
+        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
+        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
+        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
+
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
+        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
+        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
+        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
+        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
+
+        serverCount.addAndGet(4);
+        httpTestServer.start();
+        httpsTestServer.start();
+        http2TestServer.start();
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        String sharedClientName =
+                sharedClient == null ? null : sharedClient.toString();
+        sharedClient = null;
+        Thread.sleep(100);
+        AssertionError fail = TRACKER.check(500);
+        try {
+            httpTestServer.stop();
+            httpsTestServer.stop();
+            http2TestServer.stop();
+            https2TestServer.stop();
+        } finally {
+            if (fail != null) {
+                if (sharedClientName != null) {
+                    System.err.println("Shared client name is: " + sharedClientName);
+                }
+                throw fail;
+            }
+        }
+    }
+
+    static class HTTP_FixedLengthHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
+            try (InputStream is = t.getRequestBody()) {
+                is.readAllBytes();
+            }
+            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
+            t.sendResponseHeaders(200, resp.length);  //fixed content length
+            try (OutputStream os = t.getResponseBody()) {
+                os.write(resp);
+            }
+        }
+    }
+
+    static class HTTP_ChunkedHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
+            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
+            try (InputStream is = t.getRequestBody()) {
+                is.readAllBytes();
+            }
+            t.sendResponseHeaders(200, -1); // chunked/variable
+            try (OutputStream os = t.getResponseBody()) {
+                os.write(resp);
+            }
+        }
+    }
+
+}
--- a/test/jdk/java/net/httpclient/AsFileDownloadTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/AsFileDownloadTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -53,6 +53,7 @@
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
 import java.net.http.HttpRequest.BodyPublishers;
 import java.net.http.HttpResponse;
@@ -63,9 +64,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.util.Locale;
+import java.util.Map;
 import javax.net.ssl.SSLContext;
 import jdk.testlibrary.SimpleSSLContext;
 import jdk.test.lib.util.FileUtils;
@@ -188,6 +188,10 @@
         assertEquals(response.headers().firstValue("Content-Disposition").get(),
                      contentDispositionValue);
         assertEquals(fileContents, "May the luck of the Irish be with you!");
+
+        // additional checks unrelated to file download
+        caseInsensitivityOfHeaders(request.headers());
+        caseInsensitivityOfHeaders(response.headers());
     }
 
     // --- Negative
@@ -299,7 +303,7 @@
         http2TestServer.addHandler(new Http2FileDispoHandler(), "/http2/afdt");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/afdt";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2FileDispoHandler(), "/https2/afdt");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/afdt";
 
@@ -372,4 +376,30 @@
             }
         }
     }
+
+    // ---
+
+    // Asserts case-insensitivity of headers (nothing to do with file
+    // download, just convenient as we have a couple of header instances. )
+    static void caseInsensitivityOfHeaders(HttpHeaders headers) {
+        try {
+            for (Map.Entry<String, List<String>> entry : headers.map().entrySet()) {
+                String headerName = entry.getKey();
+                List<String> headerValue = entry.getValue();
+
+                for (String name : List.of(headerName.toUpperCase(Locale.ROOT),
+                                           headerName.toLowerCase(Locale.ROOT))) {
+                    assertTrue(headers.firstValue(name).isPresent());
+                    assertEquals(headers.firstValue(name).get(), headerValue.get(0));
+                    assertEquals(headers.allValues(name).size(), headerValue.size());
+                    assertEquals(headers.allValues(name), headerValue);
+                    assertEquals(headers.map().get(name).size(), headerValue.size());
+                    assertEquals(headers.map().get(name), headerValue);
+                }
+            }
+        } catch (Throwable t) {
+            System.out.println("failure in caseInsensitivityOfHeaders with:" + headers);
+            throw t;
+        }
+    }
 }
--- a/test/jdk/java/net/httpclient/BasicRedirectTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/BasicRedirectTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -228,7 +228,7 @@
         http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
         http2TestServer.addHandler(new BasicHttpRedirectHandler(), "/http2/same/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/same/redirect";
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(new BasicHttpRedirectHandler(), "/https2/same/");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/same/redirect";
 
--- a/test/jdk/java/net/httpclient/BodyProcessorInputStreamTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/BodyProcessorInputStreamTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -41,7 +41,7 @@
  * @test
  * @bug 8187503
  * @summary An example on how to read a response body with InputStream.
- * @run main/manual -Dtest.debug=true BodyProcessorInputStreamTest
+ * @run main/othervm/manual -Dtest.debug=true BodyProcessorInputStreamTest
  * @author daniel fuchs
  */
 public class BodyProcessorInputStreamTest {
--- a/test/jdk/java/net/httpclient/ConcurrentResponses.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/ConcurrentResponses.java	Thu Jun 21 09:53:50 2018 -0700
@@ -35,7 +35,9 @@
  * @library /lib/testlibrary http2/server
  * @build Http2TestServer
  * @build jdk.testlibrary.SimpleSSLContext
- * @run testng/othervm -Djdk.internal.httpclient.debug=true ConcurrentResponses
+ * @run testng/othervm
+ *      -Djdk.httpclient.HttpClient.log=headers,errors,channel
+ *      ConcurrentResponses
  */
 
 import java.io.IOException;
@@ -280,7 +282,7 @@
         http2TestServer.addHandler(new Http2VariableHandler(), "/http2/variable");
         http2VariableURI = "http://" + http2TestServer.serverAuthority() + "/http2/variable";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2FixedHandler(), "/https2/fixed");
         https2FixedURI = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
         https2TestServer.addHandler(new Http2VariableHandler(), "/https2/variable");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ConnectExceptionTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Expect ConnectException for all non-security related connect errors
+ * @bug 8204864
+ * @run testng/othervm ConnectExceptionTest
+ * @run testng/othervm/java.security.policy=noPermissions.policy ConnectExceptionTest
+ */
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.lang.System.out;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+public class ConnectExceptionTest {
+
+    static final ProxySelector INVALID_PROXY = new ProxySelector() {
+        final List<Proxy> proxy = List.of(new Proxy(Proxy.Type.HTTP,
+                InetSocketAddress.createUnresolved("proxy.invalid", 8080)));
+        @Override public List<Proxy> select(URI uri) { return proxy; }
+        @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { }
+        @Override public String toString() { return "INVALID_PROXY"; }
+    };
+
+    static final ProxySelector NO_PROXY = new ProxySelector() {
+        @Override public List<Proxy> select(URI uri) { return List.of(Proxy.NO_PROXY); }
+        @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { }
+        @Override public String toString() { return "NO_PROXY"; }
+    };
+
+    @DataProvider(name = "uris")
+    public Object[][] uris() {
+        return new Object[][]{
+            { "http://test.invalid/",  NO_PROXY       },
+            { "https://test.invalid/", NO_PROXY       },
+            { "http://test.invalid/",  INVALID_PROXY  },
+            { "https://test.invalid/", INVALID_PROXY  },
+        };
+    }
+
+    @Test(dataProvider = "uris")
+    void testSynchronousGET(String uriString, ProxySelector proxy) throws Exception {
+        out.printf("%n---%ntestSynchronousGET starting uri:%s, proxy:%s%n", uriString, proxy);
+        HttpClient client = HttpClient.newBuilder().proxy(proxy).build();
+
+        URI uri = URI.create(uriString);
+        HttpRequest request = HttpRequest.newBuilder(uri).build();
+        try {
+            HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
+            fail("UNEXPECTED response: " + response + ", body:" + response.body());
+        } catch (ConnectException ioe) {
+            out.println("Caught expected: " + ioe);
+            //ioe.printStackTrace(out);
+        } catch (SecurityException expectedIfSMIsSet) {
+            out.println("Caught expected: " + expectedIfSMIsSet);
+            assertTrue(System.getSecurityManager() != null);
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testSynchronousPOST(String uriString, ProxySelector proxy) throws Exception {
+        out.printf("%n---%ntestSynchronousPOST starting uri:%s, proxy:%s%n", uriString, proxy);
+        HttpClient client = HttpClient.newBuilder().proxy(proxy).build();
+
+        URI uri = URI.create(uriString);
+        HttpRequest request = HttpRequest.newBuilder(uri)
+                .POST(BodyPublishers.ofString("Does not matter"))
+                .build();
+        try {
+            HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
+            fail("UNEXPECTED response: " + response + ", body:" + response.body());
+        } catch (ConnectException ioe) {
+            out.println("Caught expected: " + ioe);
+            //ioe.printStackTrace(out);
+        } catch (SecurityException expectedIfSMIsSet) {
+            out.println("Caught expected: " + expectedIfSMIsSet);
+            assertTrue(System.getSecurityManager() != null);
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testAsynchronousGET(String uriString, ProxySelector proxy) throws Exception {
+        out.printf("%n---%ntestAsynchronousGET starting uri:%s, proxy:%s%n", uriString, proxy);
+        HttpClient client = HttpClient.newBuilder().proxy(proxy).build();
+
+        URI uri = URI.create(uriString);
+        HttpRequest request = HttpRequest.newBuilder(uri).build();
+        try {
+            HttpResponse<String> response = client.sendAsync(request, BodyHandlers.ofString()).get();
+            fail("UNEXPECTED response: " + response + ", body:" + response.body());
+        } catch (ExecutionException ee) {
+            Throwable t = ee.getCause();
+            if (t instanceof ConnectException) {
+                out.println("Caught expected: " + t);
+            } else if (t instanceof SecurityException) {
+                out.println("Caught expected: " + t);
+                assertTrue(System.getSecurityManager() != null);
+            } else {
+                t.printStackTrace(out);
+                fail("Unexpected exception: " + t);
+            }
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testAsynchronousPOST(String uriString, ProxySelector proxy) throws Exception {
+        out.printf("%n---%ntestAsynchronousPOST starting uri:%s, proxy:%s%n", uriString, proxy);
+        HttpClient client = HttpClient.newBuilder().proxy(proxy).build();
+
+        URI uri = URI.create(uriString);
+        HttpRequest request = HttpRequest.newBuilder(uri)
+                .POST(BodyPublishers.ofString("Does not matter"))
+                .build();
+        try {
+            HttpResponse<String> response = client.sendAsync(request, BodyHandlers.ofString()).get();
+            fail("UNEXPECTED response: " + response + ", body:" + response.body());
+        } catch (ExecutionException ee) {
+            Throwable t = ee.getCause();
+            if (t instanceof ConnectException) {
+                out.println("Caught expected: " + t);
+            } else if (t instanceof SecurityException) {
+                out.println("Caught expected: " + t);
+                assertTrue(System.getSecurityManager() != null);
+            } else {
+                t.printStackTrace(out);
+                fail("Unexpected exception: " + t);
+            }
+        }
+    }
+}
--- a/test/jdk/java/net/httpclient/CookieHeaderTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/CookieHeaderTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -205,7 +205,7 @@
         http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
         http2TestServer.addHandler(new CookieValidationHandler(), "/http2/cookie/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/cookie/retry";
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(new CookieValidationHandler(), "/https2/cookie/");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/cookie/retry";
 
--- a/test/jdk/java/net/httpclient/CustomRequestPublisher.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/CustomRequestPublisher.java	Thu Jun 21 09:53:50 2018 -0700
@@ -340,7 +340,7 @@
         http2TestServer.addHandler(new Http2EchoHandler(), "/http2/echo");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/echo";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/echo";
 
--- a/test/jdk/java/net/httpclient/CustomResponseSubscriber.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/CustomResponseSubscriber.java	Thu Jun 21 09:53:50 2018 -0700
@@ -217,7 +217,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
--- a/test/jdk/java/net/httpclient/DependentActionsTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/DependentActionsTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -27,7 +27,7 @@
  *          completes are executed either asynchronously in an executor when the
  *          CF later completes, or in the user thread that joins.
  * @library /lib/testlibrary http2/server
- * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters ThrowingPublishers
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters DependentActionsTest
  * @modules java.base/sun.net.www.http
  *          java.net.http/jdk.internal.net.http.common
  *          java.net.http/jdk.internal.net.http.frame
@@ -82,12 +82,14 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static java.lang.System.out;
 import static java.lang.String.format;
+import static java.util.stream.Collectors.toList;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
@@ -374,13 +376,13 @@
     }
 
     final List<String> extractStream(HttpResponse<Stream<String>> resp) {
-        return resp.body().collect(Collectors.toList());
+        return resp.body().collect(toList());
     }
 
     final List<String> extractInputStream(HttpResponse<InputStream> resp) {
         try (InputStream is = resp.body()) {
             return new BufferedReader(new InputStreamReader(is))
-                    .lines().collect(Collectors.toList());
+                    .lines().collect(toList());
         } catch (IOException x) {
             throw new CompletionException(x);
         }
@@ -399,43 +401,27 @@
                 .findFirst();
     }
 
+    static final Predicate<StackFrame> DAT = sfe ->
+            sfe.getClassName().startsWith("DependentActionsTest");
+    static final Predicate<StackFrame> JUC = sfe ->
+            sfe.getClassName().startsWith("java.util.concurrent");
+    static final Predicate<StackFrame> JLT = sfe ->
+            sfe.getClassName().startsWith("java.lang.Thread");
+    static final Predicate<StackFrame> NotDATorJUCorJLT = Predicate.not(DAT.or(JUC).or(JLT));
+
+
     <T> void checkThreadAndStack(Thread thread,
                                  AtomicReference<RuntimeException> failed,
                                  T result,
                                  Throwable error) {
-        if (Thread.currentThread() == thread) {
-            //failed.set(new RuntimeException("Dependant action was executed in " + thread));
-            List<StackFrame> httpStack = WALKER.walk(s -> s.filter(f -> f.getDeclaringClass()
-                    .getModule().equals(HttpClient.class.getModule()))
-                    .collect(Collectors.toList()));
-            if (!httpStack.isEmpty()) {
-                System.out.println("Found unexpected trace: ");
-                httpStack.forEach(f -> System.out.printf("\t%s%n", f));
-                failed.set(new RuntimeException("Dependant action has unexpected frame in " +
-                        Thread.currentThread() + ": " + httpStack.get(0)));
+        //failed.set(new RuntimeException("Dependant action was executed in " + thread));
+        List<StackFrame> otherFrames = WALKER.walk(s -> s.filter(NotDATorJUCorJLT).collect(toList()));
+        if (!otherFrames.isEmpty()) {
+            System.out.println("Found unexpected trace: ");
+            otherFrames.forEach(f -> System.out.printf("\t%s%n", f));
+            failed.set(new RuntimeException("Dependant action has unexpected frame in " +
+                       Thread.currentThread() + ": " + otherFrames.get(0)));
 
-            }
-            return;
-        } else if (System.getSecurityManager() != null) {
-            Optional<StackFrame> sf = WALKER.walk(s -> findFrame(s, "PrivilegedRunnable"));
-            if (!sf.isPresent()) {
-                failed.set(new RuntimeException("Dependant action does not have expected frame in "
-                        + Thread.currentThread()));
-                return;
-            } else {
-                System.out.println("Found expected frame: " + sf.get());
-            }
-        } else {
-            List<StackFrame> httpStack = WALKER.walk(s -> s.filter(f -> f.getDeclaringClass()
-                    .getModule().equals(HttpClient.class.getModule()))
-                    .collect(Collectors.toList()));
-            if (!httpStack.isEmpty()) {
-                System.out.println("Found unexpected trace: ");
-                httpStack.forEach(f -> System.out.printf("\t%s%n", f));
-                failed.set(new RuntimeException("Dependant action has unexpected frame in " +
-                        Thread.currentThread() + ": " + httpStack.get(0)));
-
-            }
         }
     }
 
@@ -620,7 +606,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
--- a/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/DependentPromiseActionsTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -27,7 +27,7 @@
  *          completes are executed either asynchronously in an executor when the
  *          CF later completes, or in the user thread that joins.
  * @library /lib/testlibrary http2/server
- * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters ThrowingPublishers
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters DependentPromiseActionsTest
  * @modules java.base/sun.net.www.http
  *          java.net.http/jdk.internal.net.http.common
  *          java.net.http/jdk.internal.net.http.frame
@@ -40,7 +40,6 @@
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.lang.StackWalker.StackFrame;
-import jdk.internal.net.http.common.HttpHeadersImpl;
 import jdk.testlibrary.SimpleSSLContext;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.AfterClass;
@@ -79,6 +78,7 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiPredicate;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Supplier;
@@ -672,7 +672,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/y";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/y";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/y";
@@ -690,8 +690,13 @@
         https2TestServer.stop();
     }
 
-    private static void pushPromiseFor(HttpTestExchange t, URI requestURI, String pushPath, boolean fixed)
-            throws IOException
+    static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
+    private static void pushPromiseFor(HttpTestExchange t,
+                                       URI requestURI,
+                                       String pushPath,
+                                       boolean fixed)
+        throws IOException
     {
         try {
             URI promise = new URI(requestURI.getScheme(),
@@ -700,9 +705,13 @@
             byte[] promiseBytes = promise.toASCIIString().getBytes(UTF_8);
             out.printf("TestServer: %s Pushing promise: %s%n", now(), promise);
             err.printf("TestServer: %s Pushing promise: %s%n", now(), promise);
-            HttpTestHeaders headers =  HttpTestHeaders.of(new HttpHeadersImpl());
+            HttpHeaders headers;
             if (fixed) {
-                headers.addHeader("Content-length", String.valueOf(promiseBytes.length));
+                String length = String.valueOf(promiseBytes.length);
+                headers = HttpHeaders.of(Map.of("Content-Length", List.of(length)),
+                                         ACCEPT_ALL);
+            } else {
+                headers = HttpHeaders.of(Map.of(), ACCEPT_ALL); // empty
             }
             t.serverPush(promise, headers, promiseBytes);
         } catch (URISyntaxException x) {
--- a/test/jdk/java/net/httpclient/DigestEchoServer.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/DigestEchoServer.java	Thu Jun 21 09:53:50 2018 -0700
@@ -170,7 +170,7 @@
         }
     }
 
-    private static String toString(HttpTestHeaders headers) {
+    private static String toString(HttpTestRequestHeaders headers) {
         return headers.entrySet().stream()
                 .map((e) -> e.getKey() + ": " + e.getValue())
                 .collect(Collectors.joining("\n"));
@@ -847,9 +847,9 @@
         }
 
         public static String computeDigest(boolean isRequest,
-                                            String reqMethod,
-                                            char[] password,
-                                            DigestResponse params)
+                                           String reqMethod,
+                                           char[] password,
+                                           DigestResponse params)
             throws NoSuchAlgorithmException
         {
 
@@ -970,11 +970,13 @@
 
         @Override
         protected void requestAuthentication(HttpTestExchange he)
-            throws IOException {
-            he.getResponseHeaders().addHeader(getAuthenticate(),
-                 "Basic realm=\"" + auth.getRealm() + "\"");
-            System.out.println(type + ": Requesting Basic Authentication "
-                 + he.getResponseHeaders().firstValue(getAuthenticate()));
+            throws IOException
+        {
+            String headerName = getAuthenticate();
+            String headerValue = "Basic realm=\"" + auth.getRealm() + "\"";
+            he.getResponseHeaders().addHeader(headerName, headerValue);
+            System.out.println(type + ": Requesting Basic Authentication, "
+                               + headerName + " : "+ headerValue);
         }
 
         @Override
@@ -1061,14 +1063,13 @@
             } else {
                 throw new InternalError(String.valueOf(v));
             }
-            he.getResponseHeaders().addHeader(getAuthenticate(),
-                 "Digest realm=\"" + auth.getRealm() + "\","
-                 + separator + "qop=\"auth\","
-                 + separator + "nonce=\"" + ns +"\"");
-            System.out.println(type + ": Requesting Digest Authentication "
-                 + he.getResponseHeaders()
-                    .firstValue(getAuthenticate())
-                    .orElse("null"));
+            String headerName = getAuthenticate();
+            String headerValue = "Digest realm=\"" + auth.getRealm() + "\","
+                    + separator + "qop=\"auth\","
+                    + separator + "nonce=\"" + ns +"\"";
+            he.getResponseHeaders().addHeader(headerName, headerValue);
+            System.out.println(type + ": Requesting Digest Authentication, "
+                               + headerName + " : " + headerValue);
         }
 
         @Override
--- a/test/jdk/java/net/httpclient/EncodedCharsInURI.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/EncodedCharsInURI.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,7 +33,8 @@
  *          java.net.http/jdk.internal.net.http.frame
  *          java.net.http/jdk.internal.net.http.hpack
  * @run testng/othervm
- *        -Djdk.httpclient.HttpClient.log=headers EncodedCharsInURI
+ *        -Djdk.internal.httpclient.debug=true
+ *        -Djdk.httpclient.HttpClient.log=headers,errors EncodedCharsInURI
  */
 //*        -Djdk.internal.httpclient.debug=true
 
@@ -48,21 +49,14 @@
 import org.testng.annotations.Test;
 
 import javax.net.ServerSocketFactory;
-import javax.net.SocketFactory;
 import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLServerSocketFactory;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Writer;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
-import java.net.SocketAddress;
 import java.net.URI;
 import java.net.http.HttpClient;
 import java.net.http.HttpRequest;
@@ -71,8 +65,6 @@
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandler;
 import java.net.http.HttpResponse.BodyHandlers;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.List;
 import java.util.Locale;
 import java.util.StringTokenizer;
@@ -87,6 +79,7 @@
 import static java.lang.String.format;
 import static java.lang.System.in;
 import static java.lang.System.out;
+import static java.nio.charset.StandardCharsets.US_ASCII;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.net.http.HttpClient.Builder.NO_PROXY;
 import static org.testng.Assert.assertEquals;
@@ -292,7 +285,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
@@ -402,9 +395,6 @@
                     Socket targetConnection = null;
                     InputStream  ccis = clientConnection.getInputStream();
                     OutputStream ccos = clientConnection.getOutputStream();
-                    Writer w = new OutputStreamWriter(
-                            clientConnection.getOutputStream(), "UTF-8");
-                    PrintWriter pw = new PrintWriter(w);
                     System.out.println(now() + getName() + ": Reading request line");
                     String requestLine = readLine(ccis);
                     System.out.println(now() + getName() + ": Request line: " + requestLine);
@@ -459,11 +449,13 @@
                     // Then send the 200 OK response to the client
                     System.out.println(now() + getName() + ": Sending "
                             + response);
-                    pw.print(response);
-                    pw.flush();
+                    ccos.write(response.toString().getBytes(UTF_8));
+                    ccos.flush();
+                    System.out.println(now() + getName() + ": sent response headers");
                     ccos.write(b);
                     ccos.flush();
                     ccos.close();
+                    System.out.println(now() + getName() + ": sent " + b.length + " body bytes");
                     connections.remove(clientConnection);
                     clientConnection.close();
                 }
--- a/test/jdk/java/net/httpclient/EscapedOctetsInURI.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/EscapedOctetsInURI.java	Thu Jun 21 09:53:50 2018 -0700
@@ -201,7 +201,7 @@
         http2TestServer.addHandler(new HttpASCIIUriStringHandler(), "/http2");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new HttpASCIIUriStringHandler(), "/https2");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2";
 
--- a/test/jdk/java/net/httpclient/FlowAdapterPublisherTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/FlowAdapterPublisherTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -359,7 +359,7 @@
         http2TestServer.addHandler(new Http2EchoHandler(), "/http2/echo");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/echo";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/echo";
 
--- a/test/jdk/java/net/httpclient/FlowAdapterSubscriberTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/FlowAdapterSubscriberTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -534,7 +534,7 @@
         http2TestServer.addHandler(new Http2EchoHandler(), "/http2/echo");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/echo";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/echo";
 
--- a/test/jdk/java/net/httpclient/HandshakeFailureTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/HandshakeFailureTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -23,6 +23,7 @@
 
 import javax.net.ServerSocketFactory;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLSocket;
 import java.io.DataInputStream;
@@ -45,7 +46,7 @@
 
 /**
  * @test
- * @run main/othervm HandshakeFailureTest
+ * @run main/othervm -Djdk.internal.httpclient.debug=true HandshakeFailureTest
  * @summary Verify SSLHandshakeException is received when the handshake fails,
  * either because the server closes ( EOF ) the connection during handshaking
  * or no cipher suite ( or similar ) can be negotiated.
@@ -80,9 +81,17 @@
         }
     }
 
+    static HttpClient getClient() {
+        SSLParameters params = new SSLParameters();
+        params.setProtocols(new String[] {"TLSv1.2"});
+        return HttpClient.newBuilder()
+                .sslParameters(params)
+                .build();
+    }
+
     void testSyncSameClient(URI uri, Version version) throws Exception {
         out.printf("%n--- testSyncSameClient %s ---%n", version);
-        HttpClient client = HttpClient.newHttpClient();
+        HttpClient client = getClient();
         for (int i = 0; i < TIMES; i++) {
             out.printf("iteration %d%n", i);
             HttpRequest request = HttpRequest.newBuilder(uri)
@@ -92,8 +101,9 @@
                 HttpResponse<Void> response = client.send(request, discarding());
                 String msg = String.format("UNEXPECTED response=%s%n", response);
                 throw new RuntimeException(msg);
-            } catch (SSLHandshakeException expected) {
+            } catch (IOException expected) {
                 out.printf("Client: caught expected exception: %s%n", expected);
+                checkExceptionOrCause(SSLHandshakeException.class, expected);
             }
         }
     }
@@ -103,7 +113,7 @@
         for (int i = 0; i < TIMES; i++) {
             out.printf("iteration %d%n", i);
             // a new client each time
-            HttpClient client = HttpClient.newHttpClient();
+            HttpClient client = getClient();
             HttpRequest request = HttpRequest.newBuilder(uri)
                                              .version(version)
                                              .build();
@@ -111,15 +121,16 @@
                 HttpResponse<Void> response = client.send(request, discarding());
                 String msg = String.format("UNEXPECTED response=%s%n", response);
                 throw new RuntimeException(msg);
-            } catch (SSLHandshakeException expected) {
+            } catch (IOException expected) {
                 out.printf("Client: caught expected exception: %s%n", expected);
+                checkExceptionOrCause(SSLHandshakeException.class, expected);
             }
         }
     }
 
     void testAsyncSameClient(URI uri, Version version) throws Exception {
         out.printf("%n--- testAsyncSameClient %s ---%n", version);
-        HttpClient client = HttpClient.newHttpClient();
+        HttpClient client = getClient();
         for (int i = 0; i < TIMES; i++) {
             out.printf("iteration %d%n", i);
             HttpRequest request = HttpRequest.newBuilder(uri)
@@ -132,12 +143,9 @@
                 String msg = String.format("UNEXPECTED response=%s%n", response);
                 throw new RuntimeException(msg);
             } catch (CompletionException ce) {
-                if (ce.getCause() instanceof SSLHandshakeException) {
-                    out.printf("Client: caught expected exception: %s%n", ce.getCause());
-                } else {
-                    out.printf("Client: caught UNEXPECTED exception: %s%n", ce.getCause());
-                    throw ce;
-                }
+                Throwable expected = ce.getCause();
+                out.printf("Client: caught expected exception: %s%n", expected);
+                checkExceptionOrCause(SSLHandshakeException.class, expected);
             }
         }
     }
@@ -147,7 +155,7 @@
         for (int i = 0; i < TIMES; i++) {
             out.printf("iteration %d%n", i);
             // a new client each time
-            HttpClient client = HttpClient.newHttpClient();
+            HttpClient client = getClient();
             HttpRequest request = HttpRequest.newBuilder(uri)
                                              .version(version)
                                              .build();
@@ -158,16 +166,26 @@
                 String msg = String.format("UNEXPECTED response=%s%n", response);
                 throw new RuntimeException(msg);
             } catch (CompletionException ce) {
-                if (ce.getCause() instanceof SSLHandshakeException) {
-                    out.printf("Client: caught expected exception: %s%n", ce.getCause());
-                } else {
-                    out.printf("Client: caught UNEXPECTED exception: %s%n", ce.getCause());
-                    throw ce;
-                }
+                ce.printStackTrace(out);
+                Throwable expected = ce.getCause();
+                out.printf("Client: caught expected exception: %s%n", expected);
+                checkExceptionOrCause(SSLHandshakeException.class, expected);
             }
         }
     }
 
+    static void checkExceptionOrCause(Class<? extends Throwable> clazz, Throwable t) {
+        final Throwable original = t;
+        do {
+            if (clazz.isInstance(t)) {
+                System.out.println("Found expected exception/cause: " + t);
+                return; // found
+            }
+        } while ((t = t.getCause()) != null);
+        original.printStackTrace(System.out);
+        throw new RuntimeException("Expected " + clazz + "in " + original);
+    }
+
     /** Common supertype for PlainServer and SSLServer. */
     static abstract class AbstractServer extends Thread implements AutoCloseable {
         protected final ServerSocket ss;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/HeadTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8203433
+ * @summary (httpclient) Add tests for HEAD and 304 responses.
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ *          java.logging
+ *          jdk.httpserver
+ * @library /lib/testlibrary /test/lib http2/server
+ * @build Http2TestServer
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm
+ *       -Djdk.httpclient.HttpClient.log=trace,headers,requests
+ *       HeadTest
+ */
+
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpClient.Redirect;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.System.out;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class HeadTest implements HttpServerAdapters {
+
+    SSLContext sslContext;
+    HttpTestServer httpTestServer;        // HTTP/1.1
+    HttpTestServer httpsTestServer;       // HTTPS/1.1
+    HttpTestServer http2TestServer;       // HTTP/2 ( h2c )
+    HttpTestServer https2TestServer;      // HTTP/2 ( h2  )
+    String httpURI;
+    String httpsURI;
+    String http2URI;
+    String https2URI;
+
+    static final String MESSAGE = "Basic HeadTest message body";
+    static final int ITERATIONS = 3;
+    static final String CONTENT_LEN = "300";
+
+    /*
+     * NOT_MODIFIED status code results from a conditional GET where
+     * the server does not (must not) return a response body because
+     * the condition specified in the request disallows it
+     */
+    static final int HTTP_NOT_MODIFIED = 304;
+    static final int HTTP_OK = 200;
+
+
+    @DataProvider(name = "positive")
+    public Object[][] positive() {
+        return new Object[][] {
+                { httpURI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_1_1  },
+                { httpsURI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_1_1  },
+                { httpURI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
+                { httpsURI, "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
+                { httpURI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_1_1  },
+                { httpsURI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_1_1  },
+                { httpURI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
+                { httpsURI, "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
+                { httpURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_1_1  },
+                { httpsURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_1_1  },
+                { httpURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
+                { httpsURI + "transfer/", "GET", HTTP_NOT_MODIFIED, HttpClient.Version.HTTP_2  },
+                { httpURI + "transfer/", "HEAD", HTTP_OK, HttpClient.Version.HTTP_1_1  },
+                { httpsURI + "transfer/", "HEAD", HTTP_OK, HttpClient.Version.HTTP_1_1  },
+                { httpURI + "transfer/", "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  },
+                { httpsURI + "transfer/", "HEAD", HTTP_OK, HttpClient.Version.HTTP_2  }
+        };
+    }
+
+    static final AtomicLong requestCounter = new AtomicLong();
+
+    @Test(dataProvider = "positive")
+    void test(String uriString, String method,
+                        int expResp, HttpClient.Version version) throws Exception {
+        out.printf("%n---- starting (%s) ----%n", uriString);
+        HttpClient client = HttpClient.newBuilder()
+                .followRedirects(Redirect.ALWAYS)
+                .sslContext(sslContext)
+                .build();
+
+        URI uri = URI.create(uriString);
+
+        HttpRequest.Builder requestBuilder = HttpRequest
+                .newBuilder(uri)
+                .method(method, HttpRequest.BodyPublishers.noBody());
+
+        if (version != null) {
+            requestBuilder.version(version);
+        }
+        HttpRequest request = requestBuilder.build();
+        out.println("Initial request: " + request.uri());
+
+        HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
+
+        out.println("  Got response: " + response);
+
+        assertEquals(response.statusCode(), expResp);
+        assertEquals(response.body(), "");
+        assertEquals(response.headers().firstValue("Content-length").get(), CONTENT_LEN);
+    }
+
+    // -- Infrastructure
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+
+        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+
+        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
+        httpTestServer.addHandler(new HeadHandler(), "/");
+        httpURI = "http://" + httpTestServer.serverAuthority() + "/";
+        HttpsServer httpsServer = HttpsServer.create(sa, 0);
+        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
+        httpsTestServer = HttpTestServer.of(httpsServer);
+        httpsTestServer.addHandler(new HeadHandler(),"/");
+        httpsURI = "https://" + httpsTestServer.serverAuthority() + "/";
+
+        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
+        http2TestServer.addHandler(new HeadHandler(), "/");
+        http2URI = "http://" + http2TestServer.serverAuthority() + "/";
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer.addHandler(new HeadHandler(), "/");
+        https2URI = "https://" + https2TestServer.serverAuthority() + "/";
+
+
+        httpTestServer.start();
+        httpsTestServer.start();
+        http2TestServer.start();
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        httpTestServer.stop();
+        httpsTestServer.stop();
+        http2TestServer.stop();
+        https2TestServer.stop();
+    }
+
+    static class HeadHandler implements HttpTestHandler {
+
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            readAllRequestData(t); // shouldn't be any
+            String method = t.getRequestMethod();
+            String path = t.getRequestURI().getPath();
+            HttpTestResponseHeaders rsph = t.getResponseHeaders();
+            if (path.contains("transfer"))
+                rsph.addHeader("Transfer-Encoding", "chunked");
+            rsph.addHeader("Content-length", CONTENT_LEN);
+            if (method.equals("HEAD")) {
+                t.sendResponseHeaders(HTTP_OK, -1);
+            } else if (method.equals("GET")) {
+                t.sendResponseHeaders(HTTP_NOT_MODIFIED, -1);
+            }
+            t.close();
+        }
+    }
+
+    static void readAllRequestData(HttpTestExchange t) throws IOException {
+        try (InputStream is = t.getRequestBody()) {
+            is.readAllBytes();
+        }
+    }
+}
--- a/test/jdk/java/net/httpclient/HeadersTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/HeadersTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -32,6 +32,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.BiPredicate;
 import static java.net.http.HttpClient.Builder.NO_PROXY;
 
 /**
@@ -41,20 +42,11 @@
  */
 public class HeadersTest {
 
+    static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
     static final URI TEST_URI = URI.create("http://www.foo.com/");
     static final HttpClient client = HttpClient.newBuilder().proxy(NO_PROXY).build();
 
-    static final class HttpHeadersStub extends HttpHeaders {
-        Map<String, List<String>> map;
-        HttpHeadersStub(Map<String, List<String>> map) {
-            this.map = map;
-        }
-        @Override
-        public Map<String, List<String>> map() {
-            return map;
-        }
-    }
-
     static void bad(String name) throws Exception {
         HttpRequest.Builder builder = HttpRequest.newBuilder(TEST_URI);
         try {
@@ -85,7 +77,7 @@
                 }
                 @Override public HttpHeaders headers() {
                     Map<String, List<String>> map = Map.of(name, List.of("foo"));
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -127,7 +119,7 @@
                 }
                 @Override public HttpHeaders headers() {
                     Map<String, List<String>> map = Map.of("x-bad", List.of(value));
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -170,7 +162,7 @@
                 @Override public HttpHeaders headers() {
                     Map<String, List<String>> map = new HashMap<>();
                     map.put(null, List.of("foo"));
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -211,7 +203,7 @@
                 @Override public HttpHeaders headers() {
                     Map<String, List<String>> map = new HashMap<>();
                     map.put("x-bar", null);
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -243,11 +235,10 @@
                     List<String> values = new ArrayList<>();
                     values.add("foo");
                     values.add(null);
-                    return new HttpHeadersStub(Map.of("x-bar", values));
+                    return HttpHeaders.of(Map.of("x-bar", values), ACCEPT_ALL);
                 }
             };
-            client
-                    .send(req, HttpResponse.BodyHandlers.ofString());
+            client.send(req, HttpResponse.BodyHandlers.ofString());
             throw new RuntimeException("Expected NPE for null header value");
         } catch (NullPointerException expected) {
             System.out.println("Got expected NPE: " + expected);
@@ -276,7 +267,7 @@
                     return Optional.empty();
                 }
                 @Override public HttpHeaders headers() {
-                    return new HttpHeadersStub(null);
+                    return HttpHeaders.of(null, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -370,7 +361,7 @@
                 }
                 @Override public HttpHeaders headers() {
                     Map<String, List<String>> map = Map.of("x-good", List.of("foo"));
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -416,7 +407,7 @@
                 }
                 @Override public HttpHeaders headers() {
                     Map<String, List<String>> map = Map.of("x-good", List.of("foo"));
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -472,7 +463,7 @@
                     @Override
                     public HttpHeaders headers() {
                         Map<String, List<String>> map = Map.of("x-good", List.of("foo"));
-                        return new HttpHeadersStub(map);
+                        return HttpHeaders.of(map, ACCEPT_ALL);
                     }
                 };
                 client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -526,7 +517,7 @@
                 @Override
                 public HttpHeaders headers() {
                     Map<String, List<String>> map = Map.of("x-good", List.of("foo"));
-                    return new HttpHeadersStub(map);
+                    return HttpHeaders.of(map, ACCEPT_ALL);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
@@ -538,12 +529,10 @@
 
     public static void main(String[] args) throws Exception {
         bad("bad:header");
-        bad("Foo\n");
         good("X-Foo!");
         good("Bar~");
         good("x");
         bad(" ");
-        bad("Bar\r\n");
         good("Hello#world");
         good("Qwer#ert");
         badValue("blah\r\n blah");
--- a/test/jdk/java/net/httpclient/HttpClientBuilderTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/HttpClientBuilderTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -275,16 +275,7 @@
         @Override public boolean expectContinue() { return false; }
         @Override public URI uri() { return URI.create("http://foo.com/"); }
         @Override public Optional<Version> version() { return Optional.empty(); }
-        private final FixedHttpHeaders headers = new FixedHttpHeaders();
-        @Override public HttpHeaders headers() { return headers; }
-        public class FixedHttpHeaders extends HttpHeaders {
-            private final Map<String, List<String>> map =
-                    new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-            @Override
-            public Map<String, List<String>> map() {
-                return map;
-            }
-        }
+        @Override public HttpHeaders headers() { return HttpHeaders.of(Map.of(), (x, y) -> true); }
     }
 
     // ---
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/HttpHeadersOf.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests for HttpHeaders.of factory method
+ * @run testng HttpHeadersOf
+ */
+
+import java.net.http.HttpHeaders;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiPredicate;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+public class HttpHeadersOf {
+
+    static final Class<NullPointerException> NPE = NullPointerException.class;
+    static final Class<NumberFormatException> NFE = NumberFormatException.class;
+    static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
+
+    static final BiPredicate<String,String> ACCEPT_ALL =
+        new BiPredicate<>() {
+            @Override public boolean test(String name, String value) { return true; }
+            @Override public String toString() { return "ACCEPT_ALL"; }
+        };
+
+    static final BiPredicate<String,String> REJECT_ALL =
+        new BiPredicate<>() {
+            @Override public boolean test(String name, String value) { return false; }
+            @Override public String toString() { return "REJECT_ALL"; }
+        };
+
+    @DataProvider(name = "predicates")
+    public Object[][] predicates() {
+        return new Object[][] { { ACCEPT_ALL }, { REJECT_ALL } };
+    }
+
+    @Test(dataProvider = "predicates")
+    public void testNull(BiPredicate<String,String> filter) {
+        assertThrows(NPE, () -> HttpHeaders.of(null, null));
+        assertThrows(NPE, () -> HttpHeaders.of(null, filter));
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of(), null));
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of("value")), null));
+
+        // nulls in the Map
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of(null, List.of("value)")), filter));
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", null), filter));
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of(null)), filter));
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of("aValue", null)), filter));
+        assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of(null, "aValue")), filter));
+    }
+
+
+    @DataProvider(name = "filterMaps")
+    public Object[][] filterMaps() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("A", List.of("B"),           "X", List.of("Y", "Z")),
+                Map.of("A", List.of("B", "C"),      "X", List.of("Y", "Z")),
+                Map.of("A", List.of("B", "C", "D"), "X", List.of("Y", "Z"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "filterMaps")
+    public void testFilter(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, REJECT_ALL);
+        assertEquals(headers.map().size(), 0);
+        assertFalse(headers.firstValue("A").isPresent());
+        assertEquals(headers.allValues("A").size(), 0);
+
+        headers = HttpHeaders.of(map, (name, value) -> {
+            if (name.equals("A")) return true; else return false; });
+        assertEquals(headers.map().size(), 1);
+        assertTrue(headers.firstValue("A").isPresent());
+        assertEquals(headers.allValues("A"), map.get("A"));
+        assertEquals(headers.allValues("A").size(), map.get("A").size());
+        assertFalse(headers.firstValue("X").isPresent());
+
+        headers = HttpHeaders.of(map, (name, value) -> {
+            if (name.equals("X")) return true; else return false; });
+        assertEquals(headers.map().size(), 1);
+        assertTrue(headers.firstValue("X").isPresent());
+        assertEquals(headers.allValues("X"), map.get("X"));
+        assertEquals(headers.allValues("X").size(), map.get("X").size());
+        assertFalse(headers.firstValue("A").isPresent());
+    }
+
+
+    @DataProvider(name = "mapValues")
+    public Object[][] mapValues() {
+        List<Map<String, List<String>>> maps = List.of(
+            Map.of("A", List.of("B")),
+            Map.of("A", List.of("B", "C")),
+            Map.of("A", List.of("B", "C", "D")),
+
+            Map.of("A", List.of("B"),           "X", List.of("Y", "Z")),
+            Map.of("A", List.of("B", "C"),      "X", List.of("Y", "Z")),
+            Map.of("A", List.of("B", "C", "D"), "X", List.of("Y", "Z")),
+
+            Map.of("A", List.of("B"),           "X", List.of("Y", "Z")),
+            Map.of("A", List.of("B", "C"),      "X", List.of("Y", "Z")),
+            Map.of("A", List.of("B", "C", "D"), "X", List.of("Y", "Z")),
+
+            Map.of("X", List.of("Y", "Z"), "A", List.of("B")),
+            Map.of("X", List.of("Y", "Z"), "A", List.of("B", "C")),
+            Map.of("X", List.of("Y", "Z"), "A", List.of("B", "C", "D"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "mapValues")
+    public void testMapValues(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL);
+
+        assertEquals(headers.map().size(), map.size());
+        assertTrue(headers.firstValue("A").isPresent());
+        assertTrue(headers.firstValue("a").isPresent());
+        assertEquals(headers.firstValue("A").get(), "B");
+        assertEquals(headers.firstValue("a").get(), "B");
+        assertEquals(headers.allValues("A"), map.get("A"));
+        assertEquals(headers.allValues("a"), map.get("A"));
+        assertEquals(headers.allValues("F").size(), 0);
+        assertTrue(headers.map().get("A").contains("B"));
+        assertFalse(headers.map().get("A").contains("F"));
+        assertThrows(NFE, () -> headers.firstValueAsLong("A"));
+
+        // a non-exhaustive list of mutators
+        assertThrows(UOE, () -> headers.map().put("Z", List.of("Z")));
+        assertThrows(UOE, () -> headers.map().remove("A"));
+        assertThrows(UOE, () -> headers.map().remove("A", "B"));
+        assertThrows(UOE, () -> headers.map().clear());
+        assertThrows(UOE, () -> headers.allValues("A").remove("B"));
+        assertThrows(UOE, () -> headers.allValues("A").remove(1));
+        assertThrows(UOE, () -> headers.allValues("A").clear());
+        assertThrows(UOE, () -> headers.allValues("A").add("Z"));
+        assertThrows(UOE, () -> headers.allValues("A").addAll(List.of("Z")));
+        assertThrows(UOE, () -> headers.allValues("A").add(1, "Z"));
+    }
+
+
+    @DataProvider(name = "caseInsensitivity")
+    public Object[][] caseInsensitivity() {
+        List<Map<String, List<String>>> maps = List.of(
+             Map.of("Accept-Encoding", List.of("gzip, deflate")),
+             Map.of("accept-encoding", List.of("gzip, deflate")),
+             Map.of("AccePT-ENCoding", List.of("gzip, deflate")),
+             Map.of("ACCept-EncodING", List.of("gzip, deflate")),
+             Map.of("ACCEPT-ENCODING", List.of("gzip, deflate"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "caseInsensitivity")
+    public void testCaseInsensitivity(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL);
+
+        for (String name : List.of("Accept-Encoding", "accept-encoding",
+                                   "aCCept-EnCODing", "accepT-encodinG")) {
+            assertTrue(headers.firstValue(name).isPresent());
+            assertTrue(headers.allValues(name).contains("gzip, deflate"));
+            assertEquals(headers.firstValue(name).get(), "gzip, deflate");
+            assertEquals(headers.allValues(name).size(), 1);
+            assertEquals(headers.map().size(), 1);
+            assertEquals(headers.map().get(name).size(), 1);
+            assertEquals(headers.map().get(name).get(0), "gzip, deflate");
+        }
+    }
+
+    @Test
+    public void testEqualsAndHashCode() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("Accept-Encoding", List.of("gzip, deflate")),
+                Map.of("accept-encoding", List.of("gzip, deflate")),
+                Map.of("AccePT-ENCoding", List.of("gzip, deflate")),
+                Map.of("ACCept-EncodING", List.of("gzip, deflate")),
+                Map.of("ACCEPT-ENCODING", List.of("gzip, deflate"))
+        );
+        int mapDiffer = 0;
+        int mapHashDiffer = 0;
+        for (Map<String, List<String>> m1 : maps) {
+            HttpHeaders h1 = HttpHeaders.of(m1, ACCEPT_ALL);
+            for (Map<String, List<String>> m2 : maps) {
+                HttpHeaders h2 = HttpHeaders.of(m2, ACCEPT_ALL);
+                if (!m1.equals(m2)) mapDiffer++;
+                if (m1.hashCode() != m2.hashCode()) mapHashDiffer++;
+                assertEquals(h1, h2, "HttpHeaders differ");
+                assertEquals(h1.hashCode(), h2.hashCode(),
+                        "hashCode differ for " + List.of(m1,m2));
+            }
+        }
+        assertTrue(mapDiffer > 0, "all maps were equal!");
+        assertTrue(mapHashDiffer > 0, "all maps had same hashCode!");
+    }
+
+    @DataProvider(name = "valueAsLong")
+    public Object[][] valueAsLong() {
+        return new Object[][] {
+            new Object[] { Map.of("Content-Length", List.of("10")), 10l },
+            new Object[] { Map.of("Content-Length", List.of("101")), 101l },
+            new Object[] { Map.of("Content-Length", List.of("56789")), 56789l },
+            new Object[] { Map.of("Content-Length", List.of(Long.toString(Long.MAX_VALUE))), Long.MAX_VALUE },
+            new Object[] { Map.of("Content-Length", List.of(Long.toString(Long.MIN_VALUE))), Long.MIN_VALUE }
+        };
+    }
+
+    @Test(dataProvider = "valueAsLong")
+    public void testValueAsLong(Map<String,List<String>> map, long expected) {
+        HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL);
+        assertEquals(headers.firstValueAsLong("Content-Length").getAsLong(), expected);
+    }
+
+
+    @DataProvider(name = "duplicateNames")
+    public Object[][] duplicateNames() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("X-name", List.of(),
+                       "x-name", List.of()),
+                Map.of("X-name", List.of(""),
+                       "x-name", List.of("")),
+                Map.of("X-name", List.of("C"),
+                       "x-name", List.of("D")),
+                Map.of("X-name", List.of("E"),
+                       "Y-name", List.of("F"),
+                       "X-Name", List.of("G")),
+                Map.of("X-chegar", List.of("H"),
+                       "y-dfuchs", List.of("I"),
+                       "Y-dfuchs", List.of("J")),
+                Map.of("X-name ", List.of("K"),
+                       "X-Name", List.of("L")),
+                Map.of("X-name", List.of("M"),
+                       "\rX-Name", List.of("N"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "duplicateNames")
+    public void testDuplicates(Map<String,List<String>> map) {
+        HttpHeaders headers;
+        try {
+            headers = HttpHeaders.of(map, ACCEPT_ALL);
+            fail("UNEXPECTED: " + headers);
+        } catch (IllegalArgumentException iae) {
+            System.out.println("caught EXPECTED IAE:" + iae);
+            assertTrue(iae.getMessage().contains("duplicate"));
+        }
+    }
+
+
+    @DataProvider(name = "noSplittingJoining")
+    public Object[][] noSplittingJoining() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("A", List.of("B")),
+                Map.of("A", List.of("B", "C")),
+                Map.of("A", List.of("B", "C", "D")),
+                Map.of("A", List.of("B", "C", "D", "E")),
+                Map.of("A", List.of("B", "C", "D", "E", "F")),
+                Map.of("A", List.of("B, C")),
+                Map.of("A", List.of("B, C, D")),
+                Map.of("A", List.of("B, C, D, E")),
+                Map.of("A", List.of("B, C, D, E, F")),
+                Map.of("A", List.of("B, C", "D", "E", "F")),
+                Map.of("A", List.of("B", "C, D", "E", "F")),
+                Map.of("A", List.of("B", "C, D", "E, F")),
+                Map.of("A", List.of("B", "C, D, E", "F")),
+                Map.of("A", List.of("B", "C, D, E, F"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "noSplittingJoining")
+    public void testNoSplittingJoining(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL);
+        Map<String,List<String>> headersMap = headers.map();
+
+        assertEquals(headers.map().size(), map.size());
+        for (Map.Entry<String,List<String>> entry : map.entrySet()) {
+            String headerName = entry.getKey();
+            List<String> headerValues = entry.getValue();
+            assertEquals(headerValues, headersMap.get(headerName));
+            assertEquals(headerValues, headers.allValues(headerName));
+            assertEquals(headerValues.get(0), headers.firstValue(headerName).get());
+        }
+    }
+
+
+    @DataProvider(name = "trimming")
+    public Object[][] trimming() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("A", List.of("B")),
+                Map.of(" A", List.of("B")),
+                Map.of("A ", List.of("B")),
+                Map.of("A", List.of(" B")),
+                Map.of("A", List.of("B ")),
+                Map.of("\tA", List.of("B")),
+                Map.of("A\t", List.of("B")),
+                Map.of("A", List.of("\tB")),
+                Map.of("A", List.of("B\t")),
+                Map.of("A\r", List.of("B")),
+                Map.of("A\n", List.of("B")),
+                Map.of("A\r\n", List.of("B"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "trimming")
+    public void testTrimming(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, (name, value) -> {
+            assertEquals(name, "A");
+            assertEquals(value, "B");
+            return true;
+        });
+
+        assertEquals(headers.map().size(), 1);
+        assertEquals(headers.firstValue("A").get(), "B");
+        assertEquals(headers.allValues("A"), List.of("B"));
+        assertTrue(headers.map().get("A").equals(List.of("B")));
+    }
+
+
+    @DataProvider(name = "emptyKey")
+    public Object[][] emptyKey() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("", List.of("B")),
+                Map.of(" ", List.of("B")),
+                Map.of("  ", List.of("B")),
+                Map.of("\t", List.of("B")),
+                Map.of("\t\t", List.of("B"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "emptyKey")
+    public void testEmptyKey(Map<String,List<String>> map) {
+        HttpHeaders headers;
+        try {
+            headers = HttpHeaders.of(map, ACCEPT_ALL);
+            fail("UNEXPECTED: " + headers);
+        } catch (IllegalArgumentException iae) {
+            System.out.println("caught EXPECTED IAE:" + iae);
+            assertTrue(iae.getMessage().contains("empty"));
+        }
+    }
+
+
+    @DataProvider(name = "emptyValue")
+    public Object[][] emptyValue() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("A", List.of("")),
+                Map.of("A", List.of("", "")),
+                Map.of("A", List.of("", "", " ")),
+                Map.of("A", List.of("\t")),
+                Map.of("A", List.of("\t\t"))
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "emptyValue")
+    public void testEmptyValue(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, (name, value) -> {
+            assertEquals(value, "");
+            return true;
+        });
+        assertEquals(headers.map().size(), map.size());
+        assertEquals(headers.map().get("A").get(0), "");
+        headers.allValues("A").forEach(v -> assertEquals(v, ""));
+        assertEquals(headers.firstValue("A").get(), "");
+    }
+
+
+    @DataProvider(name = "noValues")
+    public Object[][] noValues() {
+        List<Map<String, List<String>>> maps = List.of(
+                Map.of("A", List.of()),
+                Map.of("A", List.of(), "B", List.of()),
+                Map.of("A", List.of(), "B", List.of(), "C", List.of()),
+                Map.of("A", new ArrayList()),
+                Map.of("A", new LinkedList())
+        );
+        return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "noValues")
+    public void testNoValues(Map<String,List<String>> map) {
+        HttpHeaders headers = HttpHeaders.of(map, (name, value) -> {
+            fail("UNEXPECTED call to filter");
+            return true;
+        });
+        assertEquals(headers.map().size(), 0);
+        assertEquals(headers.map().get("A"), null);
+        assertEquals(headers.allValues("A").size(), 0);
+        assertFalse(headers.firstValue("A").isPresent());
+    }
+}
--- a/test/jdk/java/net/httpclient/HttpInputStreamTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/HttpInputStreamTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -47,7 +47,7 @@
 /*
  * @test
  * @summary An example on how to read a response body with InputStream.
- * @run main/manual -Dtest.debug=true HttpInputStreamTest
+ * @run main/othervm/manual -Dtest.debug=true HttpInputStreamTest
  * @author daniel fuchs
  */
 public class HttpInputStreamTest {
--- a/test/jdk/java/net/httpclient/HttpServerAdapters.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/HttpServerAdapters.java	Thu Jun 21 09:53:50 2018 -0700
@@ -27,11 +27,11 @@
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpHandler;
 import com.sun.net.httpserver.HttpServer;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 
 import java.net.InetAddress;
 import java.io.ByteArrayInputStream;
 import java.net.http.HttpClient.Version;
-import jdk.internal.net.http.common.HttpHeadersImpl;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -41,6 +41,7 @@
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
 import java.net.URI;
+import java.net.http.HttpHeaders;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
@@ -95,26 +96,26 @@
     }
 
     /**
-     * A version agnostic adapter class for HTTP Headers.
+     * A version agnostic adapter class for HTTP request Headers.
      */
-    public static abstract class HttpTestHeaders {
+    public static abstract class HttpTestRequestHeaders {
         public abstract Optional<String> firstValue(String name);
-        public abstract void addHeader(String name, String value);
         public abstract Set<String> keySet();
         public abstract Set<Map.Entry<String, List<String>>> entrySet();
         public abstract List<String> get(String name);
         public abstract boolean containsKey(String name);
 
-        public static HttpTestHeaders of(Headers headers) {
-            return new Http1TestHeaders(headers);
-        }
-        public static HttpTestHeaders of(HttpHeadersImpl headers) {
-            return new Http2TestHeaders(headers);
+        public static HttpTestRequestHeaders of(Headers headers) {
+            return new Http1TestRequestHeaders(headers);
         }
 
-        private final static class Http1TestHeaders extends HttpTestHeaders {
+        public static HttpTestRequestHeaders of(HttpHeaders headers) {
+            return new Http2TestRequestHeaders(headers);
+        }
+
+        private static final class Http1TestRequestHeaders extends HttpTestRequestHeaders {
             private final Headers headers;
-            Http1TestHeaders(Headers h) { this.headers = h; }
+            Http1TestRequestHeaders(Headers h) { this.headers = h; }
             @Override
             public Optional<String> firstValue(String name) {
                 if (headers.containsKey(name)) {
@@ -123,11 +124,6 @@
                 return Optional.empty();
             }
             @Override
-            public void addHeader(String name, String value) {
-                headers.add(name, value);
-            }
-
-            @Override
             public Set<String> keySet() { return headers.keySet(); }
             @Override
             public Set<Map.Entry<String, List<String>>> entrySet() {
@@ -142,17 +138,14 @@
                 return headers.containsKey(name);
             }
         }
-        private final static class Http2TestHeaders extends HttpTestHeaders {
-            private final HttpHeadersImpl headers;
-            Http2TestHeaders(HttpHeadersImpl h) { this.headers = h; }
+        private static final class Http2TestRequestHeaders extends HttpTestRequestHeaders {
+            private final HttpHeaders headers;
+            Http2TestRequestHeaders(HttpHeaders h) { this.headers = h; }
             @Override
             public Optional<String> firstValue(String name) {
                 return headers.firstValue(name);
             }
             @Override
-            public void addHeader(String name, String value) {
-                headers.addHeader(name, value);
-            }
             public Set<String> keySet() { return headers.map().keySet(); }
             @Override
             public Set<Map.Entry<String, List<String>>> entrySet() {
@@ -170,6 +163,37 @@
     }
 
     /**
+     * A version agnostic adapter class for HTTP response Headers.
+     */
+    public static abstract class HttpTestResponseHeaders {
+        public abstract void addHeader(String name, String value);
+
+        public static HttpTestResponseHeaders of(Headers headers) {
+            return new Http1TestResponseHeaders(headers);
+        }
+        public static HttpTestResponseHeaders of(HttpHeadersBuilder headersBuilder) {
+            return new Http2TestResponseHeaders(headersBuilder);
+        }
+
+        private final static class Http1TestResponseHeaders extends HttpTestResponseHeaders {
+            private final Headers headers;
+            Http1TestResponseHeaders(Headers h) { this.headers = h; }
+            @Override
+            public void addHeader(String name, String value) {
+                headers.add(name, value);
+            }
+        }
+        private final static class Http2TestResponseHeaders extends HttpTestResponseHeaders {
+            private final HttpHeadersBuilder headersBuilder;
+            Http2TestResponseHeaders(HttpHeadersBuilder hb) { this.headersBuilder = hb; }
+            @Override
+            public void addHeader(String name, String value) {
+                headersBuilder.addHeader(name, value);
+            }
+        }
+    }
+
+    /**
      * A version agnostic adapter class for HTTP Server Exchange.
      */
     public static abstract class HttpTestExchange {
@@ -177,17 +201,17 @@
         public abstract Version getExchangeVersion();
         public abstract InputStream   getRequestBody();
         public abstract OutputStream  getResponseBody();
-        public abstract HttpTestHeaders getRequestHeaders();
-        public abstract HttpTestHeaders getResponseHeaders();
+        public abstract HttpTestRequestHeaders getRequestHeaders();
+        public abstract HttpTestResponseHeaders getResponseHeaders();
         public abstract void sendResponseHeaders(int code, int contentLength) throws IOException;
         public abstract URI getRequestURI();
         public abstract String getRequestMethod();
         public abstract void close();
-        public void serverPush(URI uri, HttpTestHeaders headers, byte[] body) {
+        public void serverPush(URI uri, HttpHeaders headers, byte[] body) {
             ByteArrayInputStream bais = new ByteArrayInputStream(body);
             serverPush(uri, headers, bais);
         }
-        public void serverPush(URI uri, HttpTestHeaders headers, InputStream body) {
+        public void serverPush(URI uri, HttpHeaders headers, InputStream body) {
             throw new UnsupportedOperationException("serverPush with " + getExchangeVersion());
         }
         public boolean serverPushAllowed() {
@@ -221,12 +245,12 @@
                 return exchange.getResponseBody();
             }
             @Override
-            public HttpTestHeaders getRequestHeaders() {
-                return HttpTestHeaders.of(exchange.getRequestHeaders());
+            public HttpTestRequestHeaders getRequestHeaders() {
+                return HttpTestRequestHeaders.of(exchange.getRequestHeaders());
             }
             @Override
-            public HttpTestHeaders getResponseHeaders() {
-                return HttpTestHeaders.of(exchange.getResponseHeaders());
+            public HttpTestResponseHeaders getResponseHeaders() {
+                return HttpTestResponseHeaders.of(exchange.getResponseHeaders());
             }
             @Override
             public void sendResponseHeaders(int code, int contentLength) throws IOException {
@@ -268,12 +292,13 @@
                 return exchange.getResponseBody();
             }
             @Override
-            public HttpTestHeaders getRequestHeaders() {
-                return HttpTestHeaders.of(exchange.getRequestHeaders());
+            public HttpTestRequestHeaders getRequestHeaders() {
+                return HttpTestRequestHeaders.of(exchange.getRequestHeaders());
             }
+
             @Override
-            public HttpTestHeaders getResponseHeaders() {
-                return HttpTestHeaders.of(exchange.getResponseHeaders());
+            public HttpTestResponseHeaders getResponseHeaders() {
+                return HttpTestResponseHeaders.of(exchange.getResponseHeaders());
             }
             @Override
             public void sendResponseHeaders(int code, int contentLength) throws IOException {
@@ -286,20 +311,8 @@
                 return exchange.serverPushAllowed();
             }
             @Override
-            public void serverPush(URI uri, HttpTestHeaders headers, InputStream body) {
-                HttpHeadersImpl headersImpl;
-                if (headers instanceof HttpTestHeaders.Http2TestHeaders) {
-                    headersImpl = ((HttpTestHeaders.Http2TestHeaders)headers).headers.deepCopy();
-                } else {
-                    headersImpl = new HttpHeadersImpl();
-                    for (Map.Entry<String, List<String>> e : headers.entrySet()) {
-                        String name = e.getKey();
-                        for (String v : e.getValue()) {
-                            headersImpl.addHeader(name, v);
-                        }
-                    }
-                }
-                exchange.serverPush(uri, headersImpl, body);
+            public void serverPush(URI uri, HttpHeaders headers, InputStream body) {
+                exchange.serverPush(uri, headers, body);
             }
             void doFilter(Filter.Chain filter) throws IOException {
                 throw new IOException("cannot use HTTP/1.1 filter with HTTP/2 server");
@@ -363,7 +376,7 @@
     }
 
     public static boolean expectException(HttpTestExchange e) {
-        HttpTestHeaders h = e.getRequestHeaders();
+        HttpTestRequestHeaders h = e.getRequestHeaders();
         Optional<String> expectException = h.firstValue("X-expect-exception");
         if (expectException.isPresent()) {
             return expectException.get().equalsIgnoreCase("true");
--- a/test/jdk/java/net/httpclient/ImmutableFlowItems.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/ImmutableFlowItems.java	Thu Jun 21 09:53:50 2018 -0700
@@ -206,7 +206,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
--- a/test/jdk/java/net/httpclient/InvalidInputStreamSubscriptionRequest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/InvalidInputStreamSubscriptionRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -472,7 +472,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
--- a/test/jdk/java/net/httpclient/InvalidSSLContextTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/InvalidSSLContextTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -53,6 +53,8 @@
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
+
+import static java.net.http.HttpClient.Builder.NO_PROXY;
 import static java.net.http.HttpClient.Version.HTTP_1_1;
 import static java.net.http.HttpClient.Version.HTTP_2;
 
@@ -75,6 +77,7 @@
     public void testSync(Version version) throws Exception {
         // client-side uses a different context to that of the server-side
         HttpClient client = HttpClient.newBuilder()
+                .proxy(NO_PROXY)
                 .sslContext(SSLContext.getDefault())
                 .build();
 
@@ -85,8 +88,9 @@
         try {
             HttpResponse<?> response = client.send(request, BodyHandlers.discarding());
             Assert.fail("UNEXPECTED response" + response);
-        } catch (SSLException sslex) {
-            System.out.println("Caught expected: " + sslex);
+        } catch (IOException ex) {
+            System.out.println("Caught expected: " + ex);
+            assertExceptionOrCause(SSLException.class, ex);
         }
     }
 
@@ -94,6 +98,7 @@
     public void testAsync(Version version) throws Exception {
         // client-side uses a different context to that of the server-side
         HttpClient client = HttpClient.newBuilder()
+                .proxy(NO_PROXY)
                 .sslContext(SSLContext.getDefault())
                 .build();
 
@@ -117,21 +122,26 @@
                 if (cause == null) {
                     Assert.fail("Unexpected null cause: " + error);
                 }
-                assertException(clazz, cause);
+                assertExceptionOrCause(clazz, cause);
             } else {
-                assertException(clazz, error);
+                assertExceptionOrCause(clazz, error);
             }
             return null;
         }).join();
     }
 
-    static void assertException(Class<? extends Throwable> clazz, Throwable t) {
+    static void assertExceptionOrCause(Class<? extends Throwable> clazz, Throwable t) {
         if (t == null) {
             Assert.fail("Expected " + clazz + ", caught nothing");
         }
-        if (!clazz.isInstance(t)) {
-            Assert.fail("Expected " + clazz + ", caught " + t);
-        }
+        final Throwable original = t;
+        do {
+            if (clazz.isInstance(t)) {
+                return; // found
+            }
+        } while ((t = t.getCause()) != null);
+        original.printStackTrace(System.out);
+        Assert.fail("Expected " + clazz + "in " + original);
     }
 
     @BeforeTest
@@ -163,7 +173,7 @@
                         s.startHandshake();
                         s.close();
                         Assert.fail("SERVER: UNEXPECTED ");
-                    } catch (SSLHandshakeException he) {
+                    } catch (SSLException he) {
                         System.out.println("SERVER: caught expected " + he);
                     } catch (IOException e) {
                         System.out.println("SERVER: caught: " + e);
--- a/test/jdk/java/net/httpclient/InvalidSubscriptionRequest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/InvalidSubscriptionRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -404,7 +404,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
--- a/test/jdk/java/net/httpclient/LineBodyHandlerTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/LineBodyHandlerTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -661,7 +661,7 @@
         http2TestServer.addHandler(new HttpTestEchoHandler(), "/http2/echo");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/echo";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(new HttpTestEchoHandler(), "/https2/echo");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/echo";
 
--- a/test/jdk/java/net/httpclient/MappingResponseSubscriber.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/MappingResponseSubscriber.java	Thu Jun 21 09:53:50 2018 -0700
@@ -88,7 +88,7 @@
     String https2URI_fixed;
     String https2URI_chunk;
 
-    static final int ITERATION_COUNT = 10;
+    static final int ITERATION_COUNT = 3;
     // a shared executor helps reduce the amount of threads created by the test
     static final Executor executor = Executors.newCachedThreadPool();
 
@@ -224,7 +224,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/MaxStreams.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8196389
+ * @summary Should HttpClient support SETTINGS_MAX_CONCURRENT_STREAMS from the server
+ *
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ *          java.logging
+ *          jdk.httpserver
+ * @library /lib/testlibrary http2/server
+ * @build Http2TestServer
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm -ea -esa MaxStreams
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Semaphore;
+import javax.net.ssl.SSLContext;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandler;
+import java.net.http.HttpResponse.BodyHandlers;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.net.http.HttpResponse.BodyHandlers.discarding;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+public class MaxStreams {
+
+    Http2TestServer http2TestServer;   // HTTP/2 ( h2c )
+    Http2TestServer https2TestServer;   // HTTP/2 ( h2 )
+    final Http2FixedHandler handler = new Http2FixedHandler();
+    SSLContext ctx;
+    String http2FixedURI;
+    String https2FixedURI;
+    volatile CountDownLatch latch;
+    ExecutorService exec;
+    final Semaphore canStartTestRun = new Semaphore(1);
+
+    // we send an initial warm up request, then MAX_STREAMS+1 requests
+    // in parallel. The last of them should hit the limit.
+    // Then we wait for all the responses and send a further request
+    // which should succeed. The server should see (and respond to)
+    // MAX_STREAMS+2 requests per test run.
+
+    static final int MAX_STREAMS = 10;
+    static final String RESPONSE = "Hello world";
+
+    @DataProvider(name = "uris")
+    public Object[][] variants() {
+        return new Object[][]{
+                {http2FixedURI},
+                {https2FixedURI},
+                {http2FixedURI},
+                {https2FixedURI}
+        };
+    }
+
+
+    @Test(dataProvider = "uris", timeOut=20000)
+    void testAsString(String uri) throws Exception {
+        canStartTestRun.acquire();
+        latch = new CountDownLatch(1);
+        handler.setLatch(latch);
+        HttpClient client = HttpClient.newBuilder().sslContext(ctx).build();
+        List<CompletableFuture<HttpResponse<String>>> responses = new LinkedList<>();
+
+        HttpRequest request = HttpRequest.newBuilder(URI.create(uri))
+                                         .version(HttpClient.Version.HTTP_2)
+                                         .GET()
+                                         .build();
+        // send warmup to ensure we only have one Http2Connection
+        HttpResponse<String> warmup = client.send(request, BodyHandlers.ofString());
+        if (warmup.statusCode() != 200 || !warmup.body().equals(RESPONSE))
+            throw new RuntimeException();
+
+        for (int i=0;i<MAX_STREAMS+1; i++) {
+            responses.add(client.sendAsync(request, BodyHandlers.ofString()));
+        }
+
+        // wait until we get local exception before allow server to proceed
+        try {
+            CompletableFuture.anyOf(responses.toArray(new CompletableFuture<?>[0])).join();
+        } catch (Exception ee) {
+            System.err.println("Expected exception 1 " + ee);
+        }
+
+        latch.countDown();
+
+        // check the first MAX_STREAMS requests succeeded
+        try {
+            CompletableFuture.allOf(responses.toArray(new CompletableFuture<?>[0])).join();
+            System.err.println("Did not get Expected exception 2 ");
+        } catch (Exception ee) {
+            System.err.println("Expected exception 2 " + ee);
+        }
+        int count = 0;
+        int failures = 0;
+        for (CompletableFuture<HttpResponse<String>> cf : responses) {
+            HttpResponse<String> r = null;
+            try {
+                count++;
+                r = cf.join();
+                if (r.statusCode() != 200 || !r.body().equals(RESPONSE))
+                    throw new RuntimeException();
+            } catch (Throwable t) {
+                failures++;
+                System.err.printf("Failure %d at count %d\n", failures, count);
+                System.err.println(t);
+                t.printStackTrace();
+            }
+        }
+        if (failures != 1) {
+            String msg = "Expected 1 failure. Got " + failures;
+            throw new RuntimeException(msg);
+        }
+
+        // make sure it succeeds now as number of streams == 0 now
+        HttpResponse<String> warmdown = client.send(request, BodyHandlers.ofString());
+        if (warmdown.statusCode() != 200 || !warmdown.body().equals(RESPONSE))
+            throw new RuntimeException();
+        System.err.println("Test OK");
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        ctx = (new SimpleSSLContext()).get();
+        exec = Executors.newCachedThreadPool();
+
+        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+
+        Properties props = new Properties();
+        props.setProperty("http2server.settings.max_concurrent_streams", Integer.toString(MAX_STREAMS));
+        http2TestServer = new Http2TestServer("localhost", false, 0, exec, 10, props, null);
+        http2TestServer.addHandler(handler, "/http2/fixed");
+        http2FixedURI = "http://" + http2TestServer.serverAuthority()+ "/http2/fixed";
+        http2TestServer.start();
+
+        https2TestServer = new Http2TestServer("localhost", true, 0, exec, 10, props, ctx);
+        https2TestServer.addHandler(handler, "/http2/fixed");
+        https2FixedURI = "https://" + https2TestServer.serverAuthority()+ "/http2/fixed";
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        System.err.println("Stopping test server now");
+        http2TestServer.stop();
+    }
+
+    class Http2FixedHandler implements Http2Handler {
+        final AtomicInteger counter = new AtomicInteger(0);
+        CountDownLatch latch;
+
+        synchronized void setLatch(CountDownLatch latch) {
+            this.latch = latch;
+        }
+
+        synchronized CountDownLatch getLatch() {
+            return latch;
+        }
+
+        @Override
+        public void handle(Http2TestExchange t) throws IOException {
+            int c = -1;
+            try (InputStream is = t.getRequestBody();
+                 OutputStream os = t.getResponseBody()) {
+
+                is.readAllBytes();
+                c = counter.getAndIncrement();
+                if (c > 0 && c <= MAX_STREAMS) {
+                    // Wait for latch.
+                    try {
+                        // don't send any replies until all requests are sent
+                        System.err.println("latch await");
+                        getLatch().await();
+                        System.err.println("latch resume");
+                    } catch (InterruptedException ee) {}
+                }
+                t.sendResponseHeaders(200, RESPONSE.length());
+                os.write(RESPONSE.getBytes());
+            } finally {
+                // client issues MAX_STREAMS + 3 requests in total
+                // but server should only see MAX_STREAMS + 2 in total. One is rejected by client
+                // counter c captured before increment so final value is MAX_STREAMS + 1
+                if (c == MAX_STREAMS + 1) {
+                    counter.set(0);
+                    canStartTestRun.release();
+                }
+            }
+        }
+    }
+}
--- a/test/jdk/java/net/httpclient/MethodsTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/MethodsTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -21,8 +21,6 @@
  * questions.
  */
 
-import jdk.internal.net.http.common.HttpHeadersImpl;
-
 import java.io.IOException;
 import java.net.http.HttpClient;
 import java.net.http.HttpHeaders;
@@ -30,10 +28,10 @@
 import java.net.URI;
 import java.net.http.HttpResponse;
 import java.time.Duration;
+import java.util.Map;
 import java.util.Optional;
 import static java.net.http.HttpClient.Builder.NO_PROXY;
 
-
 /**
  * @test
  * @bug 8199135
@@ -75,7 +73,7 @@
                     return Optional.empty();
                 }
                 @Override public HttpHeaders headers() {
-                    return new HttpHeadersImpl();
+                    return HttpHeaders.of(Map.of(), (x, y) -> true);
                 }
             };
             client.send(req, HttpResponse.BodyHandlers.ofString());
--- a/test/jdk/java/net/httpclient/NonAsciiCharsInURI.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/NonAsciiCharsInURI.java	Thu Jun 21 09:53:50 2018 -0700
@@ -216,7 +216,7 @@
         http2TestServer.addHandler(handler, "/http2");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(handler, "/https2");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2";
 
--- a/test/jdk/java/net/httpclient/RedirectMethodChange.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/RedirectMethodChange.java	Thu Jun 21 09:53:50 2018 -0700
@@ -212,7 +212,7 @@
         http2TestServer.addHandler(handler, "/http2/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/test/rmt";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         targetURI = "https://" + https2TestServer.serverAuthority() + "/https2/redirect/rmt";
         handler = new RedirMethodChgeHandler(targetURI);
         https2TestServer.addHandler(handler, "/https2/");
@@ -283,14 +283,14 @@
             }
 
             if (newtest) {
-                HttpTestHeaders hdrs = he.getRequestHeaders();
+                HttpTestRequestHeaders hdrs = he.getRequestHeaders();
                 String value = hdrs.firstValue("X-Redirect-Code").get();
                 int redirectCode = Integer.parseInt(value);
                 expectedMethod = hdrs.firstValue("X-Expect-Method").get();
                 if (!readAndCheckBody(he))
                     return;
-                hdrs = he.getResponseHeaders();
-                hdrs.addHeader("Location", targetURL);
+                HttpTestResponseHeaders headersbuilder = he.getResponseHeaders();
+                headersbuilder.addHeader("Location", targetURL);
                 he.sendResponseHeaders(redirectCode, 0);
                 inTest = true;
             } else {
--- a/test/jdk/java/net/httpclient/RedirectWithCookie.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/RedirectWithCookie.java	Thu Jun 21 09:53:50 2018 -0700
@@ -167,7 +167,7 @@
         http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
         http2TestServer.addHandler(new CookieRedirectHandler(), "/http2/cookie/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/cookie/redirect";
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(new CookieRedirectHandler(), "/https2/cookie/");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/cookie/redirect";
 
--- a/test/jdk/java/net/httpclient/RequestBuilderTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/RequestBuilderTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -209,6 +209,7 @@
         for (HttpRequest r : requests) {
             assertEquals(r.headers().map().size(), 1);
             assertTrue(r.headers().firstValue("A").isPresent());
+            assertTrue(r.headers().firstValue("a").isPresent());
             assertEquals(r.headers().firstValue("A").get(), "B");
             assertEquals(r.headers().allValues("A"), List.of("B"));
             assertEquals(r.headers().allValues("C").size(), 0);
@@ -310,6 +311,30 @@
             assertThrows(UOE, () -> r.headers().allValues("A").addAll(List.of("Z")));
             assertThrows(UOE, () -> r.headers().allValues("A").add(1, "Z"));
         }
+
+        // case-insensitivity
+        requests = List.of(
+                newBuilder(uri)
+                        .header("Accept-Encoding", "gzip, deflate").build(),
+                newBuilder(uri)
+                        .header("accept-encoding", "gzip, deflate").build(),
+                newBuilder(uri)
+                        .header("AccePt-EncodINg", "gzip, deflate").build(),
+                newBuilder(uri)
+                        .header("AcCEpt-EncoDIng", "gzip, deflate").build()
+        );
+        for (HttpRequest r : requests) {
+            for (String name : List.of("Accept-Encoding", "accept-encoding",
+                                       "aCCept-EnCODing", "accepT-encodinG")) {
+                assertTrue(r.headers().firstValue(name).isPresent());
+                assertTrue(r.headers().allValues(name).contains("gzip, deflate"));
+                assertEquals(r.headers().firstValue(name).get(), "gzip, deflate");
+                assertEquals(r.headers().allValues(name).size(), 1);
+                assertEquals(r.headers().map().size(), 1);
+                assertEquals(r.headers().map().get(name).size(), 1);
+                assertEquals(r.headers().map().get(name).get(0), "gzip, deflate");
+            }
+        }
     }
 
     private static final Set<String> RESTRICTED = Set.of("connection", "content-length",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ResponseBodyBeforeError.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests that all response body is delivered to the BodySubscriber
+ *          before an abortive error terminates the flow
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm ResponseBodyBeforeError
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodySubscriber;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Flow;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocketFactory;
+import static java.lang.System.out;
+import static java.net.http.HttpClient.Builder.NO_PROXY;
+import static java.net.http.HttpResponse.BodyHandlers.ofString;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class ResponseBodyBeforeError {
+
+    ReplyingServer variableLengthServer;
+    ReplyingServer variableLengthHttpsServer;
+    ReplyingServer fixedLengthServer;
+    ReplyingServer fixedLengthHttpsServer;
+
+    String httpURIVarLen;
+    String httpsURIVarLen;
+    String httpURIFixLen;
+    String httpsURIFixLen;
+
+    SSLContext sslContext;
+
+    static final String EXPECTED_RESPONSE_BODY =
+            "<html><body><h1>Heading</h1><p>Some Text</p></body></html>";
+
+    @DataProvider(name = "sanity")
+    public Object[][] sanity() {
+        return new Object[][]{
+                { httpURIVarLen   + "?length=all" },
+                { httpsURIVarLen  + "?length=all" },
+                { httpURIFixLen   + "?length=all" },
+                { httpsURIFixLen  + "?length=all" },
+        };
+    }
+
+    @Test(dataProvider = "sanity")
+    void sanity(String url) throws Exception {
+        HttpClient client = HttpClient.newBuilder()
+                .proxy(NO_PROXY)
+                .sslContext(sslContext)
+                .build();
+        HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
+        HttpResponse<String> response = client.send(request, ofString());
+        String body = response.body();
+        assertEquals(body, EXPECTED_RESPONSE_BODY);
+        client.sendAsync(request, ofString())
+                .thenApply(resp -> resp.body())
+                .thenAccept(b -> assertEquals(b, EXPECTED_RESPONSE_BODY))
+                .join();
+    }
+
+    @DataProvider(name = "uris")
+    public Object[][] variants() {
+        Object[][] cases = new Object[][] {
+            // The length query string is the total number of response body
+            // bytes in the reply, before the server closes the connection. The
+            // second arg is a partial-expected-body that the body subscriber
+            // should receive before onError is invoked.
+
+            { httpURIFixLen + "?length=0",   ""               },
+            { httpURIFixLen + "?length=1",   "<"              },
+            { httpURIFixLen + "?length=2",   "<h"             },
+            { httpURIFixLen + "?length=10",  "<html><bod"     },
+            { httpURIFixLen + "?length=19",  "<html><body><h1>Hea"             },
+            { httpURIFixLen + "?length=31",  "<html><body><h1>Heading</h1><p>" },
+
+            { httpsURIFixLen + "?length=0",   ""              },
+            { httpsURIFixLen + "?length=1",   "<"             },
+            { httpsURIFixLen + "?length=2",   "<h"            },
+            { httpsURIFixLen + "?length=10",  "<html><bod"    },
+            { httpsURIFixLen + "?length=19",  "<html><body><h1>Hea"             },
+            { httpsURIFixLen + "?length=31",  "<html><body><h1>Heading</h1><p>" },
+
+            // accounts for chunk framing
+            { httpURIVarLen + "?length=0",   ""               },
+            { httpURIVarLen + "?length=1",   ""               },
+            { httpURIVarLen + "?length=2",   ""               },
+            { httpURIVarLen + "?length=4",   "<"              },
+            { httpURIVarLen + "?length=5",   "<h"             },
+            { httpURIVarLen + "?length=18",  "<html><bod"     },
+            { httpURIVarLen + "?length=20",  "<html><body>"   },
+            { httpURIVarLen + "?length=21",  "<html><body>"   }, // boundary around chunk framing
+            { httpURIVarLen + "?length=22",  "<html><body>"   },
+            { httpURIVarLen + "?length=23",  "<html><body>"   },
+            { httpURIVarLen + "?length=24",  "<html><body>"   },
+            { httpURIVarLen + "?length=25",  "<html><body>"   },
+            { httpURIVarLen + "?length=26",  "<html><body>"   },
+            { httpURIVarLen + "?length=27",  "<html><body><"  },
+            { httpURIVarLen + "?length=51",  "<html><body><h1>Heading</h1><p>" },
+
+            { httpsURIVarLen + "?length=0",   ""              },
+            { httpsURIVarLen + "?length=1",   ""              },
+            { httpsURIVarLen + "?length=2",   ""              },
+            { httpsURIVarLen + "?length=4",   "<"             },
+            { httpsURIVarLen + "?length=5",   "<h"            },
+            { httpsURIVarLen + "?length=18",  "<html><bod"    },
+            { httpsURIVarLen + "?length=20",  "<html><body>"  },
+            { httpsURIVarLen + "?length=21",  "<html><body>"  },
+            { httpsURIVarLen + "?length=22",  "<html><body>"  },
+            { httpsURIVarLen + "?length=23",  "<html><body>"  },
+            { httpsURIVarLen + "?length=24",  "<html><body>"  },
+            { httpsURIVarLen + "?length=25",  "<html><body>"  },
+            { httpsURIVarLen + "?length=26",  "<html><body>"  },
+            { httpsURIVarLen + "?length=27",  "<html><body><" },
+            { httpsURIVarLen + "?length=51",  "<html><body><h1>Heading</h1><p>" },
+        };
+
+        List<Object[]> list = new ArrayList<>();
+        Arrays.asList(cases).stream()
+                .map(e -> new Object[] {e[0], e[1], true})  // reuse client
+                .forEach(list::add);
+        Arrays.asList(cases).stream()
+                .map(e -> new Object[] {e[0], e[1], false}) // do not reuse client
+                .forEach(list::add);
+        return list.stream().toArray(Object[][]::new);
+    }
+
+    static final int ITERATION_COUNT = 3;
+
+    @Test(dataProvider = "uris")
+    void testSynchronousAllRequestBody(String url,
+                                       String expectedPatrialBody,
+                                       boolean sameClient)
+        throws Exception
+    {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder()
+                        .proxy(NO_PROXY)
+                        .sslContext(sslContext)
+                        .build();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
+            CustomBodySubscriber bs = new CustomBodySubscriber();
+            try {
+                HttpResponse<String> response = client.send(request, r -> bs);
+                String body = response.body();
+                out.println(response + ": " + body);
+                fail("UNEXPECTED RESPONSE: " + response);
+            } catch (IOException expected) {
+                String pm = bs.receivedAsString();
+                out.println("partial body received: " + pm);
+                assertEquals(pm, expectedPatrialBody);
+            }
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testAsynchronousAllRequestBody(String url,
+                                        String expectedPatrialBody,
+                                        boolean sameClient)
+        throws Exception
+    {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder()
+                        .proxy(NO_PROXY)
+                        .sslContext(sslContext)
+                        .build();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
+            CustomBodySubscriber bs = new CustomBodySubscriber();
+            try {
+                HttpResponse<String> response = client.sendAsync(request, r -> bs).get();
+                String body = response.body();
+                out.println(response + ": " + body);
+                fail("UNEXPECTED RESPONSE: " + response);
+            } catch (ExecutionException ee) {
+                if (ee.getCause() instanceof IOException) {
+                    String pm = bs.receivedAsString();
+                    out.println("partial body received: " + pm);
+                    assertEquals(pm, expectedPatrialBody);
+                } else {
+                    throw ee;
+                }
+            }
+        }
+    }
+
+    static final class CustomBodySubscriber implements BodySubscriber<String> {
+
+        Flow.Subscription subscription;
+        private final List<ByteBuffer> received = new ArrayList<>();
+        private final CompletableFuture<String> cf = new CompletableFuture<>();
+
+        @Override
+        public CompletionStage<String> getBody() {
+            return cf;
+        }
+
+        @Override
+        public void onSubscribe(Flow.Subscription subscription) {
+            out.println("CustomBodySubscriber got onSubscribe: ");
+            this.subscription = subscription;
+            subscription.request(1);
+        }
+
+        @Override
+        public void onNext(List<ByteBuffer> items) {
+            out.println("CustomBodySubscriber got onNext: " + items);
+            received.addAll(items);
+            subscription.request(1);
+        }
+
+        @Override
+        public void onError(Throwable expected) {
+            out.println("CustomBodySubscriber got expected: " + expected);
+            cf.completeExceptionally(expected);
+        }
+
+        String receivedAsString() {
+            int size = received.stream().mapToInt(ByteBuffer::remaining).sum();
+            byte[] res = new byte[size];
+            int from = 0;
+            for (ByteBuffer b : received) {
+                int l = b.remaining();
+                b.get(res, from, l);
+                from += l;
+            }
+            return new String(res, UTF_8);
+        }
+
+        @Override
+        public void onComplete() {
+            out.println("CustomBodySubscriber got complete: ");
+            assert false : "Unexpected onComplete";
+        }
+    }
+
+    // -- infra
+
+    /**
+     * A server that replies with headers and a, possibly partial, reply, before
+     * closing the connection. The number of body bytes of written, is
+     * controllable through the "length" query string param in the requested
+     * URI.
+     */
+    static abstract class ReplyingServer extends Thread implements Closeable {
+
+        private final String name;
+        private final ServerSocket ss;
+        private volatile boolean closed;
+
+        private ReplyingServer(String name) throws IOException {
+            super(name);
+            this.name = name;
+            ss = newServerSocket();
+            ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+            this.start();
+        }
+
+        protected ServerSocket newServerSocket() throws IOException {
+            return new ServerSocket();
+        }
+
+        abstract String responseHeaders();
+
+        abstract String responseBody();
+
+        @Override
+        public void run() {
+            while (!closed) {
+                try (Socket s = ss.accept()) {
+                    out.print(name + ": got connection ");
+                    InputStream is = s.getInputStream();
+                    URI requestMethod = readRequestMethod(is);
+                    out.print(requestMethod + " ");
+                    URI uriPath = readRequestPath(is);
+                    out.println(uriPath);
+                    readRequestHeaders(is);
+
+                    String query = uriPath.getRawQuery();
+                    assert query != null;
+                    String qv = query.split("=")[1];
+                    int len;
+                    if (qv.equals("all")) {
+                        len = responseBody().getBytes(US_ASCII).length;
+                    } else {
+                        len = Integer.parseInt(query.split("=")[1]);
+                    }
+
+                    OutputStream os = s.getOutputStream();
+                    os.write(responseHeaders().getBytes(US_ASCII));
+                    out.println(name  + ": headers written, writing " + len  + " body bytes");
+                    byte[] responseBytes = responseBody().getBytes(US_ASCII);
+                    for (int i = 0; i< len; i++) {
+                        os.write(responseBytes[i]);
+                        os.flush();
+                    }
+                } catch (IOException e) {
+                    if (!closed)
+                        throw new UncheckedIOException("Unexpected", e);
+                }
+            }
+        }
+
+        static final byte[] requestEnd = new byte[] { '\r', '\n', '\r', '\n' };
+
+        // Read the request method
+        static URI readRequestMethod(InputStream is) throws IOException {
+            StringBuilder sb = new StringBuilder();
+            int r;
+            while ((r = is.read()) != -1 && r != 0x20) {
+                sb.append((char)r);
+            }
+            return URI.create(sb.toString());
+        }
+
+        // Read the request URI path
+        static URI readRequestPath(InputStream is) throws IOException {
+            StringBuilder sb = new StringBuilder();
+            int r;
+            while ((r = is.read()) != -1 && r != 0x20) {
+                sb.append((char)r);
+            }
+            return URI.create(sb.toString());
+        }
+
+        // Read until the end of a HTTP request headers
+        static void readRequestHeaders(InputStream is) throws IOException {
+            int requestEndCount = 0, r;
+            while ((r = is.read()) != -1) {
+                if (r == requestEnd[requestEndCount]) {
+                    requestEndCount++;
+                    if (requestEndCount == 4) {
+                        break;
+                    }
+                } else {
+                    requestEndCount = 0;
+                }
+            }
+        }
+
+        public int getPort() { return ss.getLocalPort(); }
+
+        @Override
+        public void close() {
+            if (closed)
+                return;
+            closed = true;
+            try {
+                ss.close();
+            } catch (IOException e) {
+                throw new UncheckedIOException("Unexpected", e);
+            }
+        }
+    }
+
+    /** A server that issues a possibly-partial chunked reply. */
+    static class PlainVariableLengthServer extends ReplyingServer {
+
+        static final String CHUNKED_RESPONSE_BODY =
+                "6\r\n"+ "<html>\r\n" +
+                "6\r\n"+ "<body>\r\n" +
+                "10\r\n"+ "<h1>Heading</h1>\r\n" +
+                "10\r\n"+ "<p>Some Text</p>\r\n" +
+                "7\r\n"+ "</body>\r\n" +
+                "7\r\n"+ "</html>\r\n" +
+                "0\r\n"+ "\r\n";
+
+        static final String RESPONSE_HEADERS =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/html; charset=utf-8\r\n" +
+                "Transfer-Encoding: chunked\r\n" +
+                "Connection: close\r\n\r\n";
+
+
+        PlainVariableLengthServer() throws IOException {
+            super("PlainVariableLengthServer");
+        }
+
+        protected PlainVariableLengthServer(String name) throws IOException {
+            super(name);
+        }
+
+        @Override
+        String responseHeaders( ) { return RESPONSE_HEADERS; }
+
+        @Override
+        String responseBody( ) { return CHUNKED_RESPONSE_BODY; }
+    }
+
+    /** A server that issues a, possibly-partial, chunked reply over SSL */
+    static final class SSLVariableLengthServer extends PlainVariableLengthServer {
+        SSLVariableLengthServer() throws IOException {
+            super("SSLVariableLengthServer");
+        }
+        @Override
+        public ServerSocket newServerSocket() throws IOException {
+            return SSLServerSocketFactory.getDefault().createServerSocket();
+        }
+    }
+
+    /** A server that issues a, possibly-partial, fixed-length reply. */
+    static class PlainFixedLengthServer extends ReplyingServer {
+
+        static final String RESPONSE_BODY = EXPECTED_RESPONSE_BODY;
+
+        static final String RESPONSE_HEADERS =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/html; charset=utf-8\r\n" +
+                "Content-Length: " + RESPONSE_BODY.length() + "\r\n" +
+                "Connection: close\r\n\r\n";
+
+        PlainFixedLengthServer() throws IOException {
+            super("PlainFixedLengthServer");
+        }
+
+        protected PlainFixedLengthServer(String name) throws IOException {
+            super(name);
+        }
+
+        @Override
+        String responseHeaders( ) { return RESPONSE_HEADERS; }
+
+        @Override
+        String responseBody( ) { return RESPONSE_BODY; }
+    }
+
+    /** A server that issues a,  possibly-partial, fixed-length reply over SSL */
+    static final class SSLFixedLengthServer extends PlainFixedLengthServer {
+        SSLFixedLengthServer() throws IOException {
+            super("SSLFixedLengthServer");
+        }
+        @Override
+        public ServerSocket newServerSocket() throws IOException {
+            return SSLServerSocketFactory.getDefault().createServerSocket();
+        }
+    }
+
+    static String serverAuthority(ReplyingServer server) {
+        return InetAddress.getLoopbackAddress().getHostName() + ":"
+                + server.getPort();
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+        SSLContext.setDefault(sslContext);
+
+        variableLengthServer = new PlainVariableLengthServer();
+        httpURIVarLen = "http://" + serverAuthority(variableLengthServer)
+                + "/http1/variable/foo";
+
+        variableLengthHttpsServer = new SSLVariableLengthServer();
+        httpsURIVarLen = "https://" + serverAuthority(variableLengthHttpsServer)
+                + "/https1/variable/bar";
+
+        fixedLengthServer = new PlainFixedLengthServer();
+        httpURIFixLen = "http://" + serverAuthority(fixedLengthServer)
+                + "/http1/fixed/baz";
+
+        fixedLengthHttpsServer = new SSLFixedLengthServer();
+        httpsURIFixLen = "https://" + serverAuthority(fixedLengthHttpsServer)
+                + "/https1/fixed/foz";
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        variableLengthServer.close();
+        variableLengthHttpsServer.close();
+        fixedLengthServer.close();
+        fixedLengthHttpsServer.close();
+    }
+}
--- a/test/jdk/java/net/httpclient/ResponsePublisher.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/ResponsePublisher.java	Thu Jun 21 09:53:50 2018 -0700
@@ -426,7 +426,7 @@
         http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed";
         http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";
 
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
         https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
         https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/RetryPost.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Ensure that the POST method is retied when the property is set.
+ * @run testng/othervm -Djdk.httpclient.enableAllMethodRetry RetryPost
+ * @run testng/othervm -Djdk.httpclient.enableAllMethodRetry=true RetryPost
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.lang.System.out;
+import static java.net.http.HttpClient.Builder.NO_PROXY;
+import static java.net.http.HttpResponse.BodyHandlers.ofString;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static org.testng.Assert.assertEquals;
+
+public class RetryPost {
+
+    FixedLengthServer fixedLengthServer;
+    String httpURIFixLen;
+
+    static final String RESPONSE_BODY =
+            "You use a glass mirror to see your face: you use works of art to see your soul.";
+
+    @DataProvider(name = "uris")
+    public Object[][] variants() {
+        return new Object[][] {
+                { httpURIFixLen, true  },
+                { httpURIFixLen, false },
+        };
+    }
+
+    static final int ITERATION_COUNT = 3;
+
+    static final String REQUEST_BODY = "Body";
+
+    @Test(dataProvider = "uris")
+    void testSynchronousPOST(String url, boolean sameClient) throws Exception  {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder().proxy(NO_PROXY).build();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url))
+                    .POST(BodyPublishers.ofString(REQUEST_BODY))
+                    .build();
+            HttpResponse<String> response = client.send(request, ofString());
+            String body = response.body();
+            out.println(response + ": " + body);
+            assertEquals(response.statusCode(), 200);
+            assertEquals(body, RESPONSE_BODY);
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testAsynchronousPOST(String url, boolean sameClient) {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder().proxy(NO_PROXY).build();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url))
+                    .POST(BodyPublishers.ofString(REQUEST_BODY))
+                    .build();
+            client.sendAsync(request, ofString())
+                    .thenApply(r -> { out.println(r + ": " + r.body()); return r; })
+                    .thenApply(r -> { assertEquals(r.statusCode(), 200); return r; })
+                    .thenApply(HttpResponse::body)
+                    .thenAccept(b -> assertEquals(b, RESPONSE_BODY))
+                    .join();
+        }
+    }
+
+
+    /**
+     * A server that issues a valid fixed-length reply on even requests, and
+     * immediately closes the connection on odd requests ( tick-tock ).
+     */
+    static class FixedLengthServer extends Thread implements AutoCloseable {
+
+        static final String RESPONSE_HEADERS =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/html; charset=utf-8\r\n" +
+                "Content-Length: " + RESPONSE_BODY.length() + "\r\n" +
+                "Connection: close\r\n\r\n";
+
+        static final String RESPONSE = RESPONSE_HEADERS + RESPONSE_BODY;
+
+        private final ServerSocket ss;
+        private volatile boolean closed;
+        private int invocationTimes;
+
+        FixedLengthServer() throws IOException {
+            super("FixedLengthServer");
+            ss = new ServerSocket();
+            ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+            this.start();
+        }
+
+        public int getPort() { return ss.getLocalPort(); }
+
+        @Override
+        public void run() {
+            while (!closed) {
+                try (Socket s = ss.accept()) {
+                    invocationTimes++;
+                    out.print("FixedLengthServer: got connection ");
+                    if ((invocationTimes & 0x1) == 0x1) {
+                        out.println(" closing immediately");
+                        s.close();
+                        continue;
+                    }
+                    InputStream is = s.getInputStream();
+                    URI requestMethod = readRequestMethod(is);
+                    out.print(requestMethod + " ");
+                    URI uriPath = readRequestPath(is);
+                    out.println(uriPath);
+                    readRequestHeaders(is);
+                    byte[] body = is.readNBytes(4);
+                    assert body.length == REQUEST_BODY.length() :
+                            "Unexpected request body " + body.length;
+
+                    OutputStream os = s.getOutputStream();
+                    out.println("Server: writing response bytes");
+                    byte[] responseBytes = RESPONSE.getBytes(US_ASCII);
+                    os.write(responseBytes);
+                } catch (IOException e) {
+                    if (!closed)
+                        throw new UncheckedIOException("Unexpected", e);
+                }
+            }
+        }
+
+        @Override
+        public void close() {
+            if (closed)
+                return;
+            closed = true;
+            try {
+                ss.close();
+            } catch (IOException e) {
+                throw new UncheckedIOException("Unexpected", e);
+            }
+        }
+
+        static final byte[] requestEnd = new byte[] { '\r', '\n', '\r', '\n' };
+
+        // Read the request method
+        static URI readRequestMethod(InputStream is) throws IOException {
+            StringBuilder sb = new StringBuilder();
+            int r;
+            while ((r = is.read()) != -1 && r != 0x20) {
+                sb.append((char)r);
+            }
+            return URI.create(sb.toString());
+        }
+
+        // Read the request URI path
+        static URI readRequestPath(InputStream is) throws IOException {
+            StringBuilder sb = new StringBuilder();
+            int r;
+            while ((r = is.read()) != -1 && r != 0x20) {
+                sb.append((char)r);
+            }
+            return URI.create(sb.toString());
+        }
+
+        // Read until the end of a HTTP request headers
+        static void readRequestHeaders(InputStream is) throws IOException {
+            int requestEndCount = 0, r;
+            while ((r = is.read()) != -1) {
+                if (r == requestEnd[requestEndCount]) {
+                    requestEndCount++;
+                    if (requestEndCount == 4) {
+                        break;
+                    }
+                } else {
+                    requestEndCount = 0;
+                }
+            }
+        }
+    }
+
+    static String serverAuthority(FixedLengthServer server) {
+        return InetAddress.getLoopbackAddress().getHostName() + ":"
+                + server.getPort();
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        fixedLengthServer = new FixedLengthServer();
+        httpURIFixLen = "http://" + serverAuthority(fixedLengthServer)
+                + "/http1/fixed/baz";
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        fixedLengthServer.close();
+    }
+}
\ No newline at end of file
--- a/test/jdk/java/net/httpclient/RetryWithCookie.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/RetryWithCookie.java	Thu Jun 21 09:53:50 2018 -0700
@@ -165,7 +165,7 @@
         http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
         http2TestServer.addHandler(new CookieRetryHandler(), "/http2/cookie/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/cookie/retry";
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(new CookieRetryHandler(), "/https2/cookie/");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/cookie/retry";
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ShortResponseBody.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,668 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests Exception detail message when too few response bytes are
+ *          received before a socket exception or eof.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm
+ *       -Djdk.httpclient.HttpClient.log=headers,errors,channel
+ *       ShortResponseBody
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Stream;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import static java.lang.System.out;
+import static java.net.http.HttpClient.Builder.NO_PROXY;
+import static java.net.http.HttpResponse.BodyHandlers.ofString;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.util.stream.Collectors.toList;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class ShortResponseBody {
+
+    Server closeImmediatelyServer;
+    Server closeImmediatelyHttpsServer;
+    Server variableLengthServer;
+    Server variableLengthHttpsServer;
+    Server fixedLengthServer;
+
+    String httpURIClsImed;
+    String httpsURIClsImed;
+    String httpURIVarLen;
+    String httpsURIVarLen;
+    String httpURIFixLen;
+
+    SSLContext sslContext;
+    SSLParameters sslParameters;
+
+    static final String EXPECTED_RESPONSE_BODY =
+            "<html><body><h1>Heading</h1><p>Some Text</p></body></html>";
+
+    final static AtomicLong ids = new AtomicLong();
+    final ThreadFactory factory = new ThreadFactory() {
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread thread = new Thread(r,  "HttpClient-Worker-" + ids.incrementAndGet());
+            thread.setDaemon(true);
+            return thread;
+        }
+    };
+    final ExecutorService service = Executors.newCachedThreadPool(factory);
+
+    @DataProvider(name = "sanity")
+    public Object[][] sanity() {
+        return new Object[][]{
+            { httpURIVarLen  + "?length=all" },
+            { httpsURIVarLen + "?length=all" },
+            { httpURIFixLen  + "?length=all" },
+        };
+    }
+
+    @Test(dataProvider = "sanity")
+    void sanity(String url) throws Exception {
+        HttpClient client = newHttpClient();
+        HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
+        HttpResponse<String> response = client.send(request, ofString());
+        String body = response.body();
+        assertEquals(body, EXPECTED_RESPONSE_BODY);
+        client.sendAsync(request, ofString())
+                .thenApply(resp -> resp.body())
+                .thenAccept(b -> assertEquals(b, EXPECTED_RESPONSE_BODY))
+                .join();
+    }
+
+    @DataProvider(name = "uris")
+    public Object[][] variants() {
+        String[][] cases = new String[][] {
+            // The length query string is the total number of bytes in the reply,
+            // including headers, before the server closes the connection. The
+            // second arg is a partial-expected-detail message in the exception.
+            { httpURIVarLen + "?length=0",   "no bytes"     }, // EOF without receiving anything
+            { httpURIVarLen + "?length=1",   "status line"  }, // EOF during status-line
+            { httpURIVarLen + "?length=2",   "status line"  },
+            { httpURIVarLen + "?length=10",  "status line"  },
+            { httpURIVarLen + "?length=19",  "header"       }, // EOF during Content-Type header
+            { httpURIVarLen + "?length=30",  "header"       },
+            { httpURIVarLen + "?length=45",  "header"       },
+            { httpURIVarLen + "?length=48",  "header"       },
+            { httpURIVarLen + "?length=51",  "header"       },
+            { httpURIVarLen + "?length=98",  "header"       }, // EOF during Connection header
+            { httpURIVarLen + "?length=100", "header"       },
+            { httpURIVarLen + "?length=101", "header"       },
+            { httpURIVarLen + "?length=104", "header"       },
+            { httpURIVarLen + "?length=106", "chunked transfer encoding" }, // EOF during chunk header ( length )
+            { httpURIVarLen + "?length=110", "chunked transfer encoding" }, // EOF during chunk response body data
+
+            { httpsURIVarLen + "?length=0",   "no bytes"    },
+            { httpsURIVarLen + "?length=1",   "status line" },
+            { httpsURIVarLen + "?length=2",   "status line" },
+            { httpsURIVarLen + "?length=10",  "status line" },
+            { httpsURIVarLen + "?length=19",  "header"      },
+            { httpsURIVarLen + "?length=30",  "header"      },
+            { httpsURIVarLen + "?length=45",  "header"      },
+            { httpsURIVarLen + "?length=48",  "header"      },
+            { httpsURIVarLen + "?length=51",  "header"      },
+            { httpsURIVarLen + "?length=98",  "header"      },
+            { httpsURIVarLen + "?length=100", "header"      },
+            { httpsURIVarLen + "?length=101", "header"      },
+            { httpsURIVarLen + "?length=104", "header"      },
+            { httpsURIVarLen + "?length=106", "chunked transfer encoding" },
+            { httpsURIVarLen + "?length=110", "chunked transfer encoding" },
+
+            { httpURIFixLen + "?length=0",   "no bytes"    }, // EOF without receiving anything
+            { httpURIFixLen + "?length=1",   "status line" }, // EOF during status-line
+            { httpURIFixLen + "?length=2",   "status line" },
+            { httpURIFixLen + "?length=10",  "status line" },
+            { httpURIFixLen + "?length=19",  "header"      }, // EOF during Content-Type header
+            { httpURIFixLen + "?length=30",  "header"      },
+            { httpURIFixLen + "?length=45",  "header"      },
+            { httpURIFixLen + "?length=48",  "header"      },
+            { httpURIFixLen + "?length=51",  "header"      },
+            { httpURIFixLen + "?length=78",  "header"      }, // EOF during Connection header
+            { httpURIFixLen + "?length=79",  "header"      },
+            { httpURIFixLen + "?length=86",  "header"      },
+            { httpURIFixLen + "?length=104", "fixed content-length" }, // EOF during body
+            { httpURIFixLen + "?length=106", "fixed content-length" },
+            { httpURIFixLen + "?length=110", "fixed content-length" },
+
+            // ## ADD https fixed
+
+            { httpURIClsImed,  "no bytes"},
+            { httpsURIClsImed, "no bytes"},
+        };
+
+        List<Object[]> list = new ArrayList<>();
+        Arrays.asList(cases).stream()
+                .map(e -> new Object[] {e[0], e[1], true})  // reuse client
+                .forEach(list::add);
+        Arrays.asList(cases).stream()
+                .map(e -> new Object[] {e[0], e[1], false}) // do not reuse client
+                .forEach(list::add);
+        return list.stream().toArray(Object[][]::new);
+    }
+
+    static final int ITERATION_COUNT = 3;
+
+    HttpClient newHttpClient() {
+        return HttpClient.newBuilder()
+                .proxy(NO_PROXY)
+                .sslContext(sslContext)
+                .sslParameters(sslParameters)
+                .executor(service)
+                .build();
+    }
+
+    @Test(dataProvider = "uris")
+    void testSynchronousGET(String url, String expectedMsg, boolean sameClient)
+        throws Exception
+    {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
+            try {
+                HttpResponse<String> response = client.send(request, ofString());
+                String body = response.body();
+                out.println(response + ": " + body);
+                fail("UNEXPECTED RESPONSE: " + response);
+            } catch (IOException ioe) {
+                out.println("Caught expected exception:" + ioe);
+                String msg = ioe.getMessage();
+                assertTrue(msg.contains(expectedMsg), "exception msg:[" + msg + "]");
+                // synchronous API must have the send method on the stack
+                assertSendMethodOnStack(ioe);
+                assertNoConnectionExpiredException(ioe);
+            }
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testAsynchronousGET(String url, String expectedMsg, boolean sameClient)
+        throws Exception
+    {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
+            try {
+                HttpResponse<String> response = client.sendAsync(request, ofString()).get();
+                String body = response.body();
+                out.println(response + ": " + body);
+                fail("UNEXPECTED RESPONSE: " + response);
+            } catch (ExecutionException ee) {
+                if (ee.getCause() instanceof IOException) {
+                    IOException ioe = (IOException) ee.getCause();
+                    out.println("Caught expected exception:" + ioe);
+                    String msg = ioe.getMessage();
+                    assertTrue(msg.contains(expectedMsg), "exception msg:[" + msg + "]");
+                    assertNoConnectionExpiredException(ioe);
+                } else {
+                    throw ee;
+                }
+            }
+        }
+    }
+
+    // can be used to prolong request body publication
+    static final class InfiniteInputStream extends InputStream {
+        @Override
+        public int read() throws IOException {
+            return 1;
+        }
+
+        @Override
+        public int read(byte[] buf, int offset, int length) {
+            //int count = offset;
+            //length = Math.max(0, Math.min(buf.length - offset, length));
+            //for (; count < length; count++)
+            //    buf[offset++] = 0x01;
+            //return count;
+            return Math.max(0, Math.min(buf.length - offset, length));
+        }
+    }
+
+    // POST tests are racy in what may be received before writing may cause a
+    // broken pipe or reset exception, before all the received data can be read.
+    // Any message up to, and including, the "expected" error message can occur.
+    // Strictly ordered list, in order of possible occurrence.
+    static final List<String> MSGS_ORDER =
+            List.of("no bytes", "status line", "header");
+
+
+    @Test(dataProvider = "uris")
+    void testSynchronousPOST(String url, String expectedMsg, boolean sameClient)
+        throws Exception
+    {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url))
+                    .POST(BodyPublishers.ofInputStream(() -> new InfiniteInputStream()))
+                    .build();
+            try {
+                HttpResponse<String> response = client.send(request, ofString());
+                String body = response.body();
+                out.println(response + ": " + body);
+                fail("UNEXPECTED RESPONSE: " + response);
+            } catch (IOException ioe) {
+                out.println("Caught expected exception:" + ioe);
+                String msg = ioe.getMessage();
+
+                List<String> expectedMessages = new ArrayList<>();
+                expectedMessages.add(expectedMsg);
+                MSGS_ORDER.stream().takeWhile(s -> !s.equals(expectedMsg))
+                                   .forEach(expectedMessages::add);
+
+                assertTrue(expectedMessages.stream().anyMatch(s -> msg.indexOf(s) != -1),
+                           "exception msg:[" + msg + "], not in [" + expectedMessages);
+                // synchronous API must have the send method on the stack
+                assertSendMethodOnStack(ioe);
+                assertNoConnectionExpiredException(ioe);
+            }
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    void testAsynchronousPOST(String url, String expectedMsg, boolean sameClient)
+        throws Exception
+    {
+        out.print("---\n");
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = newHttpClient();
+            HttpRequest request = HttpRequest.newBuilder(URI.create(url))
+                    .POST(BodyPublishers.ofInputStream(() -> new InfiniteInputStream()))
+                    .build();
+            try {
+                HttpResponse<String> response = client.sendAsync(request, ofString()).get();
+                String body = response.body();
+                out.println(response + ": " + body);
+                fail("UNEXPECTED RESPONSE: " + response);
+            } catch (ExecutionException ee) {
+                if (ee.getCause() instanceof IOException) {
+                    IOException ioe = (IOException) ee.getCause();
+                    out.println("Caught expected exception:" + ioe);
+                    String msg = ioe.getMessage();
+
+                    List<String> expectedMessages = new ArrayList<>();
+                    expectedMessages.add(expectedMsg);
+                    MSGS_ORDER.stream().takeWhile(s -> !s.equals(expectedMsg))
+                            .forEach(expectedMessages::add);
+
+                    assertTrue(expectedMessages.stream().anyMatch(s -> msg.indexOf(s) != -1),
+                               "exception msg:[" + msg + "], not in [" + expectedMessages);
+                    assertNoConnectionExpiredException(ioe);
+                } else {
+                    throw ee;
+                }
+            }
+        }
+    }
+
+    // Asserts that the "send" method appears in the stack of the given
+    // exception. The synchronous API must contain the send method on the stack.
+    static void assertSendMethodOnStack(IOException ioe) {
+        final String cn = "jdk.internal.net.http.HttpClientImpl";
+        List<StackTraceElement> list = Stream.of(ioe.getStackTrace())
+                .filter(ste -> ste.getClassName().equals(cn)
+                        && ste.getMethodName().equals("send"))
+                .collect(toList());
+        if (list.size() != 1) {
+            ioe.printStackTrace(out);
+            fail(cn + ".send method not found in stack.");
+        }
+    }
+
+    // Asserts that the implementation-specific ConnectionExpiredException does
+    // NOT appear anywhere in the exception or its causal chain.
+    static void assertNoConnectionExpiredException(IOException ioe) {
+        Throwable throwable = ioe;
+        do {
+            String cn = throwable.getClass().getSimpleName();
+            if (cn.equals("ConnectionExpiredException")) {
+                ioe.printStackTrace(out);
+                fail("UNEXPECTED ConnectionExpiredException in:[" + ioe + "]");
+            }
+        } while ((throwable = throwable.getCause()) != null);
+    }
+
+    // -- infra
+
+    /**
+     * A server that, listens on a port, accepts new connections, and can be
+     * closed.
+     */
+    static abstract class Server extends Thread implements AutoCloseable {
+        protected final ServerSocket ss;
+        protected volatile boolean closed;
+
+        Server(String name) throws IOException {
+            super(name);
+            ss = newServerSocket();
+            ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+            this.start();
+        }
+
+        protected ServerSocket newServerSocket() throws IOException {
+            return new ServerSocket();
+        }
+
+        public int getPort() { return ss.getLocalPort(); }
+
+        @Override
+        public void close() {
+            if (closed)
+                return;
+            closed = true;
+            try {
+                ss.close();
+            } catch (IOException e) {
+                throw new UncheckedIOException("Unexpected", e);
+            }
+        }
+    }
+
+    /**
+     * A server that closes the connection immediately, without reading or writing.
+     */
+    static class PlainCloseImmediatelyServer extends Server {
+        PlainCloseImmediatelyServer() throws IOException {
+            super("PlainCloseImmediatelyServer");
+        }
+
+        protected PlainCloseImmediatelyServer(String name) throws IOException {
+            super(name);
+        }
+
+        @Override
+        public void run() {
+            while (!closed) {
+                try (Socket s = ss.accept()) {
+                    if (s instanceof SSLSocket) {
+                        ((SSLSocket)s).startHandshake();
+                    }
+                    out.println("Server: got connection, closing immediately ");
+                } catch (IOException e) {
+                    if (!closed)
+                        throw new UncheckedIOException("Unexpected", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * A server that closes the connection immediately, without reading or writing,
+     * after completing the SSL handshake.
+     */
+    static final class SSLCloseImmediatelyServer extends PlainCloseImmediatelyServer {
+        SSLCloseImmediatelyServer() throws IOException {
+            super("SSLCloseImmediatelyServer");
+        }
+        @Override
+        public ServerSocket newServerSocket() throws IOException {
+            return SSLServerSocketFactory.getDefault().createServerSocket();
+        }
+    }
+
+    /**
+     * A server that replies with headers and a, possibly partial, reply, before
+     * closing the connection. The number of bytes of written ( header + body),
+     * is controllable through the "length" query string param in the requested
+     * URI.
+     */
+    static abstract class ReplyingServer extends Server {
+
+        private final String name;
+
+        ReplyingServer(String name) throws IOException {
+            super(name);
+            this.name = name;
+        }
+
+        abstract String response();
+
+        @Override
+        public void run() {
+            while (!closed) {
+                try (Socket s = ss.accept()) {
+                    out.print(name + ": got connection ");
+                    InputStream is = s.getInputStream();
+                    URI requestMethod = readRequestMethod(is);
+                    out.print(requestMethod + " ");
+                    URI uriPath = readRequestPath(is);
+                    out.println(uriPath);
+                    readRequestHeaders(is);
+
+                    String query = uriPath.getRawQuery();
+                    assert query != null;
+                    String qv = query.split("=")[1];
+                    int len;
+                    if (qv.equals("all")) {
+                        len = response().getBytes(US_ASCII).length;
+                    } else {
+                        len = Integer.parseInt(query.split("=")[1]);
+                    }
+
+                    OutputStream os = s.getOutputStream();
+                    out.println(name + ": writing " + len  + " bytes");
+                    byte[] responseBytes = response().getBytes(US_ASCII);
+                    for (int i = 0; i< len; i++) {
+                        os.write(responseBytes[i]);
+                        os.flush();
+                    }
+                } catch (IOException e) {
+                    if (!closed)
+                        throw new UncheckedIOException("Unexpected", e);
+                }
+            }
+        }
+
+        static final byte[] requestEnd = new byte[] { '\r', '\n', '\r', '\n' };
+
+        // Read the request method
+        static URI readRequestMethod(InputStream is) throws IOException {
+            StringBuilder sb = new StringBuilder();
+            int r;
+            while ((r = is.read()) != -1 && r != 0x20) {
+                sb.append((char)r);
+            }
+            return URI.create(sb.toString());
+        }
+
+        // Read the request URI path
+        static URI readRequestPath(InputStream is) throws IOException {
+            StringBuilder sb = new StringBuilder();
+            int r;
+            while ((r = is.read()) != -1 && r != 0x20) {
+                sb.append((char)r);
+            }
+            return URI.create(sb.toString());
+        }
+
+        // Read until the end of a HTTP request headers
+        static void readRequestHeaders(InputStream is) throws IOException {
+            int requestEndCount = 0, r;
+            while ((r = is.read()) != -1) {
+                if (r == requestEnd[requestEndCount]) {
+                    requestEndCount++;
+                    if (requestEndCount == 4) {
+                        break;
+                    }
+                } else {
+                    requestEndCount = 0;
+                }
+            }
+        }
+    }
+
+    /** A server that issues a, possibly-partial, chunked reply. */
+    static class PlainVariableLengthServer extends ReplyingServer {
+
+        static final String CHUNKED_RESPONSE_BODY =
+                "6\r\n"+ "<html>\r\n" +
+                "6\r\n"+ "<body>\r\n" +
+                "10\r\n"+ "<h1>Heading</h1>\r\n" +
+                "10\r\n"+ "<p>Some Text</p>\r\n" +
+                "7\r\n"+ "</body>\r\n" +
+                "7\r\n"+ "</html>\r\n" +
+                "0\r\n"+ "\r\n";
+
+        static final String RESPONSE_HEADERS =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/html; charset=utf-8\r\n" +
+                "Transfer-Encoding: chunked\r\n" +
+                "Connection: close\r\n\r\n";
+
+        static final String RESPONSE = RESPONSE_HEADERS + CHUNKED_RESPONSE_BODY;
+
+        PlainVariableLengthServer() throws IOException {
+            super("PlainVariableLengthServer");
+        }
+
+        protected PlainVariableLengthServer(String name) throws IOException {
+            super(name);
+        }
+
+        @Override
+        String response( ) { return RESPONSE; }
+    }
+
+    /** A server that issues a, possibly-partial, chunked reply over SSL. */
+    static final class SSLVariableLengthServer extends PlainVariableLengthServer {
+        SSLVariableLengthServer() throws IOException {
+            super("SSLVariableLengthServer");
+        }
+        @Override
+        public ServerSocket newServerSocket() throws IOException {
+            return SSLServerSocketFactory.getDefault().createServerSocket();
+        }
+    }
+
+    /** A server that issues a fixed-length reply. */
+    static final class FixedLengthServer extends ReplyingServer {
+
+        static final String RESPONSE_BODY = EXPECTED_RESPONSE_BODY;
+
+        static final String RESPONSE_HEADERS =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/html; charset=utf-8\r\n" +
+                "Content-Length: " + RESPONSE_BODY.length() + "\r\n" +
+                "Connection: close\r\n\r\n";
+
+        static final String RESPONSE = RESPONSE_HEADERS + RESPONSE_BODY;
+
+        FixedLengthServer() throws IOException {
+            super("FixedLengthServer");
+        }
+
+        @Override
+        String response( ) { return RESPONSE; }
+    }
+
+    static String serverAuthority(Server server) {
+        return InetAddress.getLoopbackAddress().getHostName() + ":"
+                + server.getPort();
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+        SSLContext.setDefault(sslContext);
+
+        sslParameters = new SSLParameters();
+        sslParameters.setProtocols(new String[] {"TLSv1.2"});
+
+        closeImmediatelyServer = new PlainCloseImmediatelyServer();
+        httpURIClsImed = "http://" + serverAuthority(closeImmediatelyServer)
+                + "/http1/closeImmediately/foo";
+
+        closeImmediatelyHttpsServer = new SSLCloseImmediatelyServer();
+        httpsURIClsImed = "https://" + serverAuthority(closeImmediatelyHttpsServer)
+                + "/https1/closeImmediately/foo";
+
+        variableLengthServer = new PlainVariableLengthServer();
+        httpURIVarLen = "http://" + serverAuthority(variableLengthServer)
+                + "/http1/variable/bar";
+
+        variableLengthHttpsServer = new SSLVariableLengthServer();
+        httpsURIVarLen = "https://" + serverAuthority(variableLengthHttpsServer)
+                + "/https1/variable/bar";
+
+        fixedLengthServer = new FixedLengthServer();
+        httpURIFixLen = "http://" + serverAuthority(fixedLengthServer)
+                + "/http1/fixed/baz";
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        closeImmediatelyServer.close();
+        closeImmediatelyHttpsServer.close();
+        variableLengthServer.close();
+        variableLengthHttpsServer.close();
+        fixedLengthServer.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ShortResponseBodyWithRetry.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Run of ShortResponseBody with -Djdk.httpclient.enableAllMethodRetry
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build ShortResponseBody
+ * @run testng/othervm
+ *       -Djdk.httpclient.HttpClient.log=headers,errors,channel
+ *       -Djdk.httpclient.enableAllMethodRetry
+ *       ShortResponseBody
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SpecialHeadersTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary  Verify that some special headers - such as User-Agent
+ *           can be specified by the caller.
+ * @bug 8203771
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ *          java.logging
+ *          jdk.httpserver
+ * @library /lib/testlibrary http2/server
+ * @build Http2TestServer HttpServerAdapters SpecialHeadersTest
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm
+ *       -Djdk.httpclient.HttpClient.log=requests,headers,errors
+ *       SpecialHeadersTest
+ */
+
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import static java.lang.System.err;
+import static java.lang.System.out;
+import static java.net.http.HttpClient.Builder.NO_PROXY;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static org.testng.Assert.assertEquals;
+
+public class SpecialHeadersTest implements HttpServerAdapters {
+
+    SSLContext sslContext;
+    HttpTestServer httpTestServer;         // HTTP/1.1    [ 4 servers ]
+    HttpTestServer httpsTestServer;        // HTTPS/1.1
+    HttpTestServer http2TestServer;        // HTTP/2 ( h2c )
+    HttpTestServer https2TestServer;       // HTTP/2 ( h2  )
+    String httpURI;
+    String httpsURI;
+    String http2URI;
+    String https2URI;
+
+    static final String[][] headerNamesAndValues = new String[][]{
+            {"User-Agent: <DEFAULT>"},
+            {"User-Agent: camel-cased"},
+            {"user-agent: all-lower-case"},
+            {"user-Agent: mixed"},
+    };
+
+    @DataProvider(name = "variants")
+    public Object[][] variants() {
+        List<Object[]> list = new ArrayList<>();
+
+        for (boolean sameClient : new boolean[] { false, true }) {
+            Arrays.asList(headerNamesAndValues).stream()
+                    .map(e -> new Object[] {httpURI, e[0], sameClient})
+                    .forEach(list::add);
+            Arrays.asList(headerNamesAndValues).stream()
+                    .map(e -> new Object[] {httpsURI, e[0], sameClient})
+                    .forEach(list::add);
+            Arrays.asList(headerNamesAndValues).stream()
+                    .map(e -> new Object[] {http2URI, e[0], sameClient})
+                    .forEach(list::add);
+            Arrays.asList(headerNamesAndValues).stream()
+                    .map(e -> new Object[] {https2URI, e[0], sameClient})
+                    .forEach(list::add);
+        }
+        return list.stream().toArray(Object[][]::new);
+    }
+
+    static final int ITERATION_COUNT = 3; // checks upgrade and re-use
+
+    static String userAgent() {
+        return "Java-http-client/" + System.getProperty("java.version");
+    }
+
+    static final Map<String, String> DEFAULTS = Map.of("USER-AGENT", userAgent());
+
+    @Test(dataProvider = "variants")
+    void test(String uriString, String headerNameAndValue, boolean sameClient) throws Exception {
+        out.println("\n--- Starting ");
+
+        int index = headerNameAndValue.indexOf(":");
+        String name = headerNameAndValue.substring(0, index);
+        String v = headerNameAndValue.substring(index+1).trim();
+        String key = name.toUpperCase(Locale.ROOT);
+        boolean useDefault = "<DEFAULT>".equals(v);
+        String value =  useDefault ? DEFAULTS.get(key) : v;
+
+        URI uri = URI.create(uriString+"?name="+key);
+
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder()
+                        .proxy(NO_PROXY)
+                        .sslContext(sslContext)
+                        .build();
+
+            HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri);
+            if (!useDefault) {
+                requestBuilder.header(name, value);
+            }
+            HttpRequest request = requestBuilder.build();
+            HttpResponse<String> resp = client.send(request, BodyHandlers.ofString());
+
+            out.println("Got response: " + resp);
+            out.println("Got body: " + resp.body());
+            assertEquals(resp.statusCode(), 200,
+                    "Expected 200, got:" + resp.statusCode());
+
+            String receivedHeaderString = value == null ? null
+                    : resp.headers().firstValue("X-"+key).get();
+            out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key));
+            if (value != null) {
+                assertEquals(receivedHeaderString, value);
+                assertEquals(resp.headers().allValues("X-"+key), List.of(value));
+            } else {
+                assertEquals(resp.headers().allValues("X-"+key).size(), 0);
+            }
+
+        }
+    }
+
+    @Test(dataProvider = "variants")
+    void testAsync(String uriString, String headerNameAndValue, boolean sameClient) {
+        out.println("\n--- Starting ");
+        int index = headerNameAndValue.indexOf(":");
+        String name = headerNameAndValue.substring(0, index);
+        String v = headerNameAndValue.substring(index+1).trim();
+        String key = name.toUpperCase(Locale.ROOT);
+        boolean useDefault = "<DEFAULT>".equals(v);
+        String value =  useDefault ? DEFAULTS.get(key) : v;
+
+        URI uri = URI.create(uriString+"?name="+key);
+
+        HttpClient client = null;
+        for (int i=0; i< ITERATION_COUNT; i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder()
+                        .proxy(NO_PROXY)
+                        .sslContext(sslContext)
+                        .build();
+
+            HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri);
+            if (!useDefault) {
+                requestBuilder.header(name, value);
+            }
+            HttpRequest request = requestBuilder.build();
+
+            client.sendAsync(request, BodyHandlers.ofString())
+                    .thenApply(response -> {
+                        out.println("Got response: " + response);
+                        out.println("Got body: " + response.body());
+                        assertEquals(response.statusCode(), 200);
+                        return response;})
+                    .thenAccept(resp -> {
+                        String receivedHeaderString = value == null ? null
+                                : resp.headers().firstValue("X-"+key).get();
+                        out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key));
+                        if (value != null) {
+                            assertEquals(receivedHeaderString, value);
+                            assertEquals(resp.headers().allValues("X-" + key), List.of(value));
+                        } else {
+                            assertEquals(resp.headers().allValues("X-" + key).size(), 1);
+                        } })
+                    .join();
+        }
+    }
+
+    static String serverAuthority(HttpTestServer server) {
+        return InetAddress.getLoopbackAddress().getHostName() + ":"
+                + server.getAddress().getPort();
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+
+        HttpTestHandler handler = new HttpUriStringHandler();
+        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
+        httpTestServer.addHandler(handler, "/http1");
+        httpURI = "http://" + serverAuthority(httpTestServer) + "/http1";
+
+        HttpsServer httpsServer = HttpsServer.create(sa, 0);
+        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
+        httpsTestServer = HttpTestServer.of(httpsServer);
+        httpsTestServer.addHandler(handler, "/https1");
+        httpsURI = "https://" + serverAuthority(httpsTestServer) + "/https1";
+
+        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
+        http2TestServer.addHandler(handler, "/http2");
+        http2URI = "http://" + http2TestServer.serverAuthority() + "/http2";
+
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
+        https2TestServer.addHandler(handler, "/https2");
+        https2URI = "https://" + https2TestServer.serverAuthority() + "/https2";
+
+        httpTestServer.start();
+        httpsTestServer.start();
+        http2TestServer.start();
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        httpTestServer.stop();
+        httpsTestServer.stop();
+        http2TestServer.stop();
+        https2TestServer.stop();
+    }
+
+    /** A handler that returns, as its body, the exact received request URI. */
+    static class HttpUriStringHandler implements HttpTestHandler {
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            URI uri = t.getRequestURI();
+            String uriString = uri.toString();
+            out.println("Http1UriStringHandler received, uri: " + uriString);
+            String query = uri.getQuery();
+            String headerName = query.substring(query.indexOf("=")+1).trim();
+            try (InputStream is = t.getRequestBody();
+                 OutputStream os = t.getResponseBody()) {
+                is.readAllBytes();
+                byte[] bytes = uriString.getBytes(US_ASCII);
+                t.getRequestHeaders().keySet().stream()
+                        .filter(headerName::equalsIgnoreCase)
+                        .forEach(h -> {
+                            for (String v : t.getRequestHeaders().get(headerName)) {
+                                t.getResponseHeaders().addHeader("X-"+h, v);
+                            }
+                        });
+                t.sendResponseHeaders(200, bytes.length);
+                os.write(bytes);
+            }
+        }
+    }
+}
--- a/test/jdk/java/net/httpclient/SplitResponse.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/SplitResponse.java	Thu Jun 21 09:53:50 2018 -0700
@@ -24,6 +24,11 @@
 import java.io.IOException;
 import java.net.SocketException;
 import java.net.URI;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import javax.net.ssl.SSLContext;
 import javax.net.ServerSocketFactory;
@@ -32,6 +37,8 @@
 import java.net.http.HttpClient.Version;
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
+import java.util.stream.Stream;
+
 import jdk.testlibrary.SimpleSSLContext;
 import static java.lang.System.out;
 import static java.lang.String.format;
@@ -44,7 +51,10 @@
  * @library /lib/testlibrary
  * @build jdk.testlibrary.SimpleSSLContext
  * @build MockServer
- * @run main/othervm -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=all SplitResponse
+ * @run main/othervm
+ *     -Djdk.internal.httpclient.debug=true
+ *     -Djdk.httpclient.HttpClient.log=all
+ *     SplitResponse HTTP connection:CLOSE mode:SYNC
  */
 
 /**
@@ -106,20 +116,56 @@
         return client;
     }
 
+    enum Protocol {
+        HTTP, HTTPS
+    }
+    enum Connection {
+        KEEP_ALIVE,
+        CLOSE
+    }
+    enum Mode {
+        SYNC, ASYNC
+    }
+
+
     public static void main(String[] args) throws Exception {
         boolean useSSL = false;
-        if (args != null && args.length == 1) {
-            useSSL = "SSL".equals(args[0]);
+        if (args != null && args.length >= 1) {
+            useSSL = Protocol.valueOf(args[0]).equals(Protocol.HTTPS);
+        } else {
+            args = new String[] {"HTTP", "connection:KEEP_ALIVE:CLOSE", "mode:SYNC:ASYNC"};
         }
+
+        LinkedHashSet<Mode> modes = new LinkedHashSet<>();
+        LinkedHashSet<Connection> keepAlive = new LinkedHashSet<>();
+        Stream.of(args).skip(1).forEach(s -> {
+            if (s.startsWith("connection:")) {
+                Stream.of(s.split(":")).skip(1).forEach(c -> {
+                    keepAlive.add(Connection.valueOf(c));
+                });
+            } else if (s.startsWith("mode:")) {
+                Stream.of(s.split(":")).skip(1).forEach(m -> {
+                    modes.add(Mode.valueOf(m));
+                });
+            } else {
+                System.err.println("Illegal argument: " + s);
+                System.err.println("Allowed syntax is: HTTP|HTTPS [connection:KEEP_ALIVE[:CLOSE]] [mode:SYNC[:ASYNC]");
+                throw new IllegalArgumentException(s);
+            }
+        });
+
+        if (keepAlive.isEmpty()) keepAlive.addAll(EnumSet.allOf(Connection.class));
+        if (modes.isEmpty()) modes.addAll(EnumSet.allOf(Mode.class));
+
         SplitResponse sp = new SplitResponse(useSSL);
 
         for (Version version : Version.values()) {
-            for (boolean serverKeepalive : new boolean[]{ true, false }) {
+            for (Connection serverKeepalive : keepAlive) {
                 // Note: the mock server doesn't support Keep-Alive, but
                 // pretending that it might exercises code paths in and out of
                 // the connection pool, and retry logic
-                for (boolean async : new boolean[]{ true, false }) {
-                    sp.test(version, serverKeepalive, async);
+                for (Mode mode : modes) {
+                    sp.test(version,serverKeepalive == Connection.KEEP_ALIVE,mode == Mode.ASYNC);
                 }
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SplitResponseAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build MockServer SplitResponse
+ * @run main/othervm
+ *      -Djdk.internal.httpclient.debug=true
+ *      -Djdk.httpclient.HttpClient.log=all
+ *      SplitResponse HTTP connection:CLOSE mode:ASYNC
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SplitResponseKeepAlive.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build MockServer SplitResponse
+ * @run main/othervm
+ *      -Djdk.internal.httpclient.debug=true
+ *      -Djdk.httpclient.HttpClient.log=all
+ *      SplitResponse HTTP connection:KEEP_ALIVE mode:SYNC
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SplitResponseKeepAliveAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build MockServer SplitResponse
+ * @run main/othervm
+ *      -Djdk.internal.httpclient.debug=true
+ *      -Djdk.httpclient.HttpClient.log=all
+ *      SplitResponse HTTP connection:KEEP_ALIVE mode:ASYNC
+ */
--- a/test/jdk/java/net/httpclient/SplitResponseSSL.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/SplitResponseSSL.java	Thu Jun 21 09:53:50 2018 -0700
@@ -30,10 +30,5 @@
  * @run main/othervm
  *      -Djdk.internal.httpclient.debug=true
  *      -Djdk.httpclient.HttpClient.log=all
- *      SplitResponseSSL SSL
+ *      SplitResponse HTTPS connection:CLOSE mode:SYNC
  */
-public class SplitResponseSSL {
-    public static void main(String[] args) throws Exception {
-        SplitResponse.main(args);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SplitResponseSSLAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build MockServer SplitResponse
+ * @run main/othervm
+ *      -Djdk.internal.httpclient.debug=true
+ *      -Djdk.httpclient.HttpClient.log=all
+ *      SplitResponse HTTPS connection:CLOSE mode:ASYNC
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SplitResponseSSLKeepAlive.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build MockServer SplitResponse
+ * @run main/othervm
+ *      -Djdk.internal.httpclient.debug=true
+ *      -Djdk.httpclient.HttpClient.log=all
+ *      SplitResponse HTTPS connection:KEEP_ALIVE mode:SYNC
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/SplitResponseSSLKeepAliveAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @build MockServer SplitResponse
+ * @run main/othervm
+ *      -Djdk.internal.httpclient.debug=true
+ *      -Djdk.httpclient.HttpClient.log=all
+ *      SplitResponse HTTPS connection:KEEP_ALIVE mode:ASYNC
+ */
--- a/test/jdk/java/net/httpclient/StreamingBody.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/StreamingBody.java	Thu Jun 21 09:53:50 2018 -0700
@@ -136,7 +136,7 @@
         http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
         http2TestServer.addHandler(new MessageHandler(), "/http2/streamingbody/");
         http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/streamingbody/y";
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
         https2TestServer.addHandler(new MessageHandler(), "/https2/streamingbody/");
         https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/streamingbody/z";
 
--- a/test/jdk/java/net/httpclient/ThrowingPublishers.java	Wed Jun 20 11:12:48 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,685 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary Tests what happens when request publishers
- *          throw unexpected exceptions.
- * @library /lib/testlibrary http2/server
- * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
- *        ReferenceTracker ThrowingPublishers
- * @modules java.base/sun.net.www.http
- *          java.net.http/jdk.internal.net.http.common
- *          java.net.http/jdk.internal.net.http.frame
- *          java.net.http/jdk.internal.net.http.hpack
- * @run testng/othervm -Djdk.internal.httpclient.debug=true
- *                     -Djdk.httpclient.enableAllMethodRetry=true
- *                     ThrowingPublishers
- */
-
-import com.sun.net.httpserver.HttpServer;
-import com.sun.net.httpserver.HttpsConfigurator;
-import com.sun.net.httpserver.HttpsServer;
-import jdk.testlibrary.SimpleSSLContext;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import javax.net.ssl.SSLContext;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpRequest.BodyPublisher;
-import java.net.http.HttpRequest.BodyPublishers;
-import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandler;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Flow;
-import java.util.concurrent.SubmissionPublisher;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.BiPredicate;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.lang.String.format;
-import static java.lang.System.out;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-public class ThrowingPublishers implements HttpServerAdapters {
-
-    SSLContext sslContext;
-    HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
-    HttpTestServer httpsTestServer;   // HTTPS/1.1
-    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
-    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
-    String httpURI_fixed;
-    String httpURI_chunk;
-    String httpsURI_fixed;
-    String httpsURI_chunk;
-    String http2URI_fixed;
-    String http2URI_chunk;
-    String https2URI_fixed;
-    String https2URI_chunk;
-
-    static final int ITERATION_COUNT = 1;
-    // a shared executor helps reduce the amount of threads created by the test
-    static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
-    static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
-    static volatile boolean tasksFailed;
-    static final AtomicLong serverCount = new AtomicLong();
-    static final AtomicLong clientCount = new AtomicLong();
-    static final long start = System.nanoTime();
-    public static String now() {
-        long now = System.nanoTime() - start;
-        long secs = now / 1000_000_000;
-        long mill = (now % 1000_000_000) / 1000_000;
-        long nan = now % 1000_000;
-        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
-    }
-
-    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
-    private volatile HttpClient sharedClient;
-
-    static class TestExecutor implements Executor {
-        final AtomicLong tasks = new AtomicLong();
-        Executor executor;
-        TestExecutor(Executor executor) {
-            this.executor = executor;
-        }
-
-        @Override
-        public void execute(Runnable command) {
-            long id = tasks.incrementAndGet();
-            executor.execute(() -> {
-                try {
-                    command.run();
-                } catch (Throwable t) {
-                    tasksFailed = true;
-                    System.out.printf(now() + "Task %s failed: %s%n", id, t);
-                    System.err.printf(now() + "Task %s failed: %s%n", id, t);
-                    FAILURES.putIfAbsent("Task " + id, t);
-                    throw t;
-                }
-            });
-        }
-    }
-
-    @AfterClass
-    static final void printFailedTests() {
-        out.println("\n=========================");
-        try {
-            out.printf("%n%sCreated %d servers and %d clients%n",
-                    now(), serverCount.get(), clientCount.get());
-            if (FAILURES.isEmpty()) return;
-            out.println("Failed tests: ");
-            FAILURES.entrySet().forEach((e) -> {
-                out.printf("\t%s: %s%n", e.getKey(), e.getValue());
-                e.getValue().printStackTrace(out);
-            });
-            if (tasksFailed) {
-                System.out.println("WARNING: Some tasks failed");
-            }
-        } finally {
-            out.println("\n=========================\n");
-        }
-    }
-
-    private String[] uris() {
-        return new String[] {
-                httpURI_fixed,
-                httpURI_chunk,
-                httpsURI_fixed,
-                httpsURI_chunk,
-                http2URI_fixed,
-                http2URI_chunk,
-                https2URI_fixed,
-                https2URI_chunk,
-        };
-    }
-
-    @DataProvider(name = "noThrows")
-    public Object[][] noThrows() {
-        String[] uris = uris();
-        Object[][] result = new Object[uris.length * 2][];
-        //Object[][] result = new Object[uris.length][];
-        int i = 0;
-        for (boolean sameClient : List.of(false, true)) {
-            //if (!sameClient) continue;
-            for (String uri: uris()) {
-                result[i++] = new Object[] {uri + "/noThrows", sameClient};
-            }
-        }
-        assert i == uris.length * 2;
-        // assert i == uris.length ;
-        return result;
-    }
-
-    @DataProvider(name = "variants")
-    public Object[][] variants() {
-        String[] uris = uris();
-        Object[][] result = new Object[uris.length * 2 * 2][];
-        //Object[][] result = new Object[(uris.length/2) * 2 * 2][];
-        int i = 0;
-        for (Thrower thrower : List.of(
-                new UncheckedIOExceptionThrower(),
-                new UncheckedCustomExceptionThrower())) {
-            for (boolean sameClient : List.of(false, true)) {
-                for (String uri : uris()) {
-                    // if (uri.contains("http2") || uri.contains("https2")) continue;
-                    // if (!sameClient) continue;
-                    result[i++] = new Object[]{uri, sameClient, thrower};
-                }
-            }
-        }
-        assert i == uris.length * 2 * 2;
-        //assert Stream.of(result).filter(o -> o != null).count() == result.length;
-        return result;
-    }
-
-    private HttpClient makeNewClient() {
-        clientCount.incrementAndGet();
-        return TRACKER.track(HttpClient.newBuilder()
-                .proxy(HttpClient.Builder.NO_PROXY)
-                .executor(executor)
-                .sslContext(sslContext)
-                .build());
-    }
-
-    HttpClient newHttpClient(boolean share) {
-        if (!share) return makeNewClient();
-        HttpClient shared = sharedClient;
-        if (shared != null) return shared;
-        synchronized (this) {
-            shared = sharedClient;
-            if (shared == null) {
-                shared = sharedClient = makeNewClient();
-            }
-            return shared;
-        }
-    }
-
-    final String BODY = "Some string | that ? can | be split ? several | ways.";
-
-    @Test(dataProvider = "noThrows")
-    public void testNoThrows(String uri, boolean sameClient)
-            throws Exception {
-        HttpClient client = null;
-        out.printf("%n%s testNoThrows(%s, %b)%n", now(), uri, sameClient);
-        for (int i=0; i< ITERATION_COUNT; i++) {
-            if (!sameClient || client == null)
-                client = newHttpClient(sameClient);
-
-            SubmissionPublisher<ByteBuffer> publisher
-                    = new SubmissionPublisher<>(executor,10);
-            ThrowingBodyPublisher bodyPublisher = new ThrowingBodyPublisher((w) -> {},
-                    BodyPublishers.fromPublisher(publisher));
-            CompletableFuture<Void> subscribedCF = bodyPublisher.subscribedCF();
-            subscribedCF.whenComplete((r,t) -> System.out.println(now() + " subscribe completed " + t))
-                    .thenAcceptAsync((v) -> {
-                                Stream.of(BODY.split("\\|"))
-                                        .forEachOrdered(s -> {
-                                                System.out.println("submitting \"" + s +"\"");
-                                                publisher.submit(ByteBuffer.wrap(s.getBytes(StandardCharsets.UTF_8)));
-                                        });
-                                System.out.println("publishing done");
-                                publisher.close();
-                            },
-                    executor);
-
-            HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
-                    .POST(bodyPublisher)
-                    .build();
-            BodyHandler<String> handler = BodyHandlers.ofString();
-            CompletableFuture<HttpResponse<String>> response = client.sendAsync(req, handler);
-
-            String body = response.join().body();
-            assertEquals(body, Stream.of(BODY.split("\\|")).collect(Collectors.joining()));
-        }
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsString(String uri,
-                                     boolean sameClient,
-                                     Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsString(%s, %b, %s)",
-                             uri, sameClient, thrower);
-        List<byte[]> bytes = Stream.of(BODY.split("|"))
-                .map(s -> s.getBytes(UTF_8))
-                .collect(Collectors.toList());
-        testThrowing(test, uri, sameClient, () -> BodyPublishers.ofByteArrays(bytes),
-                this::shouldNotThrowInCancel, thrower,false);
-    }
-
-    private <T,U> void testThrowing(String name, String uri, boolean sameClient,
-                                    Supplier<BodyPublisher> publishers,
-                                    Finisher finisher, Thrower thrower, boolean async)
-            throws Exception
-    {
-        out.printf("%n%s%s%n", now(), name);
-        try {
-            testThrowing(uri, sameClient, publishers, finisher, thrower, async);
-        } catch (Error | Exception x) {
-            FAILURES.putIfAbsent(name, x);
-            throw x;
-        }
-    }
-
-    private void testThrowing(String uri, boolean sameClient,
-                                    Supplier<BodyPublisher> publishers,
-                                    Finisher finisher, Thrower thrower,
-                                    boolean async)
-            throws Exception
-    {
-        HttpClient client = null;
-        for (Where where : whereValues()) {
-            //if (where == Where.ON_SUBSCRIBE) continue;
-            //if (where == Where.ON_ERROR) continue;
-            if (!sameClient || client == null)
-                client = newHttpClient(sameClient);
-
-            ThrowingBodyPublisher bodyPublisher =
-                    new ThrowingBodyPublisher(where.select(thrower), publishers.get());
-            HttpRequest req = HttpRequest.
-                    newBuilder(URI.create(uri))
-                    .header("X-expect-exception", "true")
-                    .POST(bodyPublisher)
-                    .build();
-            BodyHandler<String> handler = BodyHandlers.ofString();
-            System.out.println("try throwing in " + where);
-            HttpResponse<String> response = null;
-            if (async) {
-                try {
-                    response = client.sendAsync(req, handler).join();
-                } catch (Error | Exception x) {
-                    Throwable cause = findCause(where, x, thrower);
-                    if (cause == null) throw causeNotFound(where, x);
-                    System.out.println(now() + "Got expected exception: " + cause);
-                }
-            } else {
-                try {
-                    response = client.send(req, handler);
-                } catch (Error | Exception t) {
-                    if (thrower.test(where, t)) {
-                        System.out.println(now() + "Got expected exception: " + t);
-                    } else throw causeNotFound(where, t);
-                }
-            }
-            if (response != null) {
-                finisher.finish(where, response, thrower);
-            }
-        }
-    }
-
-    enum Where {
-        BEFORE_SUBSCRIBE, BEFORE_REQUEST, BEFORE_NEXT_REQUEST, BEFORE_CANCEL,
-        AFTER_SUBSCRIBE, AFTER_REQUEST, AFTER_NEXT_REQUEST, AFTER_CANCEL;
-        public Consumer<Where> select(Consumer<Where> consumer) {
-            return new Consumer<Where>() {
-                @Override
-                public void accept(Where where) {
-                    if (Where.this == where) {
-                        consumer.accept(where);
-                    }
-                }
-            };
-        }
-    }
-
-    // can be used to reduce the surface of the test when diagnosing
-    // some failure
-    Set<Where> whereValues() {
-        //return EnumSet.of(Where.BEFORE_CANCEL, Where.AFTER_CANCEL);
-        return EnumSet.allOf(Where.class);
-    }
-
-    interface Thrower extends Consumer<Where>, BiPredicate<Where,Throwable> {
-
-    }
-
-    interface Finisher<T,U> {
-        U finish(Where w, HttpResponse<T> resp, Thrower thrower) throws IOException;
-    }
-
-    final <T,U> U shouldNotThrowInCancel(Where w, HttpResponse<T> resp, Thrower thrower) {
-        switch (w) {
-            case BEFORE_CANCEL: return null;
-            case AFTER_CANCEL: return null;
-            default: break;
-        }
-        return shouldHaveThrown(w, resp, thrower);
-    }
-
-
-    final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
-        String msg = "Expected exception not thrown in " + w
-                + "\n\tReceived: " + resp
-                + "\n\tWith body: " + resp.body();
-        System.out.println(msg);
-        throw new RuntimeException(msg);
-    }
-
-
-    private static Throwable findCause(Where w,
-                                       Throwable x,
-                                       BiPredicate<Where, Throwable> filter) {
-        while (x != null && !filter.test(w,x)) x = x.getCause();
-        return x;
-    }
-
-    static AssertionError causeNotFound(Where w, Throwable t) {
-        return new AssertionError("Expected exception not found in " + w, t);
-    }
-
-    static boolean isConnectionClosedLocally(Throwable t) {
-        if (t instanceof CompletionException) t = t.getCause();
-        if (t instanceof ExecutionException) t = t.getCause();
-        if (t instanceof IOException) {
-            String msg = t.getMessage();
-            return msg == null ? false
-                    : msg.contains("connection closed locally");
-        }
-        return false;
-    }
-
-    static final class UncheckedCustomExceptionThrower implements Thrower {
-        @Override
-        public void accept(Where where) {
-            out.println(now() + "Throwing in " + where);
-            throw new UncheckedCustomException(where.name());
-        }
-
-        @Override
-        public boolean test(Where w, Throwable throwable) {
-            switch (w) {
-                case AFTER_REQUEST:
-                case BEFORE_NEXT_REQUEST:
-                case AFTER_NEXT_REQUEST:
-                    if (isConnectionClosedLocally(throwable)) return true;
-                    break;
-                default:
-                    break;
-            }
-            return UncheckedCustomException.class.isInstance(throwable);
-        }
-
-        @Override
-        public String toString() {
-            return "UncheckedCustomExceptionThrower";
-        }
-    }
-
-    static final class UncheckedIOExceptionThrower implements Thrower {
-        @Override
-        public void accept(Where where) {
-            out.println(now() + "Throwing in " + where);
-            throw new UncheckedIOException(new CustomIOException(where.name()));
-        }
-
-        @Override
-        public boolean test(Where w, Throwable throwable) {
-            switch (w) {
-                case AFTER_REQUEST:
-                case BEFORE_NEXT_REQUEST:
-                case AFTER_NEXT_REQUEST:
-                    if (isConnectionClosedLocally(throwable)) return true;
-                    break;
-                default:
-                    break;
-            }
-            return UncheckedIOException.class.isInstance(throwable)
-                    && CustomIOException.class.isInstance(throwable.getCause());
-        }
-
-        @Override
-        public String toString() {
-            return "UncheckedIOExceptionThrower";
-        }
-    }
-
-    static final class UncheckedCustomException extends RuntimeException {
-        UncheckedCustomException(String message) {
-            super(message);
-        }
-        UncheckedCustomException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
-    static final class CustomIOException extends IOException {
-        CustomIOException(String message) {
-            super(message);
-        }
-        CustomIOException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
-
-    static final class ThrowingBodyPublisher implements BodyPublisher {
-        private final BodyPublisher publisher;
-        private final CompletableFuture<Void> subscribedCF = new CompletableFuture<>();
-        final Consumer<Where> throwing;
-        ThrowingBodyPublisher(Consumer<Where> throwing, BodyPublisher publisher) {
-            this.throwing = throwing;
-            this.publisher = publisher;
-        }
-
-        @Override
-        public long contentLength() {
-            return publisher.contentLength();
-        }
-
-        @Override
-        public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
-            try {
-                throwing.accept(Where.BEFORE_SUBSCRIBE);
-                publisher.subscribe(new SubscriberWrapper(subscriber));
-                subscribedCF.complete(null);
-                throwing.accept(Where.AFTER_SUBSCRIBE);
-            } catch (Throwable t) {
-                subscribedCF.completeExceptionally(t);
-                throw t;
-            }
-        }
-
-        CompletableFuture<Void> subscribedCF() {
-            return subscribedCF;
-        }
-
-        class SubscriptionWrapper implements Flow.Subscription {
-            final Flow.Subscription subscription;
-            final AtomicLong requestCount = new AtomicLong();
-            SubscriptionWrapper(Flow.Subscription subscription) {
-                this.subscription = subscription;
-            }
-            @Override
-            public void request(long n) {
-                long count = requestCount.incrementAndGet();
-                System.out.printf("%s request-%d(%d)%n", now(), count, n);
-                if (count > 1) throwing.accept(Where.BEFORE_NEXT_REQUEST);
-                throwing.accept(Where.BEFORE_REQUEST);
-                subscription.request(n);
-                throwing.accept(Where.AFTER_REQUEST);
-                if (count > 1) throwing.accept(Where.AFTER_NEXT_REQUEST);
-            }
-
-            @Override
-            public void cancel() {
-                throwing.accept(Where.BEFORE_CANCEL);
-                subscription.cancel();
-                throwing.accept(Where.AFTER_CANCEL);
-            }
-        }
-
-        class SubscriberWrapper implements Flow.Subscriber<ByteBuffer> {
-            final Flow.Subscriber<? super ByteBuffer> subscriber;
-            SubscriberWrapper(Flow.Subscriber<? super ByteBuffer> subscriber) {
-                this.subscriber = subscriber;
-            }
-            @Override
-            public void onSubscribe(Flow.Subscription subscription) {
-                subscriber.onSubscribe(new SubscriptionWrapper(subscription));
-            }
-            @Override
-            public void onNext(ByteBuffer item) {
-                subscriber.onNext(item);
-            }
-            @Override
-            public void onComplete() {
-                subscriber.onComplete();
-            }
-
-            @Override
-            public void onError(Throwable throwable) {
-                subscriber.onError(throwable);
-            }
-        }
-    }
-
-
-    @BeforeTest
-    public void setup() throws Exception {
-        sslContext = new SimpleSSLContext().get();
-        if (sslContext == null)
-            throw new AssertionError("Unexpected null sslContext");
-
-        // HTTP/1.1
-        HttpTestHandler h1_fixedLengthHandler = new HTTP_FixedLengthHandler();
-        HttpTestHandler h1_chunkHandler = new HTTP_ChunkedHandler();
-        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
-        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
-        httpTestServer.addHandler(h1_fixedLengthHandler, "/http1/fixed");
-        httpTestServer.addHandler(h1_chunkHandler, "/http1/chunk");
-        httpURI_fixed = "http://" + httpTestServer.serverAuthority() + "/http1/fixed/x";
-        httpURI_chunk = "http://" + httpTestServer.serverAuthority() + "/http1/chunk/x";
-
-        HttpsServer httpsServer = HttpsServer.create(sa, 0);
-        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
-        httpsTestServer = HttpTestServer.of(httpsServer);
-        httpsTestServer.addHandler(h1_fixedLengthHandler, "/https1/fixed");
-        httpsTestServer.addHandler(h1_chunkHandler, "/https1/chunk");
-        httpsURI_fixed = "https://" + httpsTestServer.serverAuthority() + "/https1/fixed/x";
-        httpsURI_chunk = "https://" + httpsTestServer.serverAuthority() + "/https1/chunk/x";
-
-        // HTTP/2
-        HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
-        HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
-
-        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
-        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
-        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
-        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
-        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
-
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
-        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
-        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
-        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
-        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
-
-        serverCount.addAndGet(4);
-        httpTestServer.start();
-        httpsTestServer.start();
-        http2TestServer.start();
-        https2TestServer.start();
-    }
-
-    @AfterTest
-    public void teardown() throws Exception {
-        String sharedClientName =
-                sharedClient == null ? null : sharedClient.toString();
-        sharedClient = null;
-        Thread.sleep(100);
-        AssertionError fail = TRACKER.check(500);
-        try {
-            httpTestServer.stop();
-            httpsTestServer.stop();
-            http2TestServer.stop();
-            https2TestServer.stop();
-        } finally {
-            if (fail != null) {
-                if (sharedClientName != null) {
-                    System.err.println("Shared client name is: " + sharedClientName);
-                }
-                throw fail;
-            }
-        }
-    }
-
-    static class HTTP_FixedLengthHandler implements HttpTestHandler {
-        @Override
-        public void handle(HttpTestExchange t) throws IOException {
-            out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
-            byte[] resp;
-            try (InputStream is = t.getRequestBody()) {
-                resp = is.readAllBytes();
-            }
-            t.sendResponseHeaders(200, resp.length);  //fixed content length
-            try (OutputStream os = t.getResponseBody()) {
-                os.write(resp);
-            }
-        }
-    }
-
-    static class HTTP_ChunkedHandler implements HttpTestHandler {
-        @Override
-        public void handle(HttpTestExchange t) throws IOException {
-            out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
-            byte[] resp;
-            try (InputStream is = t.getRequestBody()) {
-                resp = is.readAllBytes();
-            }
-            t.sendResponseHeaders(200, -1); // chunked/variable
-            try (OutputStream os = t.getResponseBody()) {
-                os.write(resp);
-            }
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersCustomAfterCancel.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersCustomAfterCancel
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersCustomAfterCancel
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersCustomAfterCancel extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "afterCancelProviderCustom")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersCustomBeforeCancel.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersCustomBeforeCancel
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersCustomBeforeCancel
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersCustomBeforeCancel extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "beforeCancelProviderCustom")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersIOAfterCancel.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersIOAfterCancel
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersIOAfterCancel
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersIOAfterCancel extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "afterCancelProviderIO")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersIOBeforeCancel.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersIOBeforeCancel
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersIOBeforeCancel
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersIOBeforeCancel extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "beforeCancelProviderIO")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersInNextRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersInNextRequest
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersInNextRequest
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersInNextRequest extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "nextRequestProvider")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersInRequest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersInRequest
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersInRequest
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersInRequest extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "requestProvider")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersInSubscribe.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersInSubscribe
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersInSubscribe
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+public class ThrowingPublishersInSubscribe extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "subscribeProvider")
+    public void testThrowingAsString(String uri, boolean sameClient,
+                                            Thrower thrower, Set<Where> whereValues)
+            throws Exception
+    {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower, whereValues);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPublishersSanity.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when request publishers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+ *        ReferenceTracker AbstractThrowingPublishers ThrowingPublishersSanity
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true
+ *                     -Djdk.httpclient.enableAllMethodRetry=true
+ *                     ThrowingPublishersSanity
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPublishersSanity extends AbstractThrowingPublishers {
+
+    @Test(dataProvider = "sanity")
+    public void testSanity(String uri, boolean sameClient)
+            throws Exception {
+        super.testSanityImpl(uri,sameClient);
+    }
+}
--- a/test/jdk/java/net/httpclient/ThrowingPushPromises.java	Wed Jun 20 11:12:48 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,757 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary Tests what happens when push promise handlers and their
- *          response body handlers and subscribers throw unexpected exceptions.
- * @library /lib/testlibrary http2/server
- * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
-  *       ReferenceTracker ThrowingPushPromises
- * @modules java.base/sun.net.www.http
- *          java.net.http/jdk.internal.net.http.common
- *          java.net.http/jdk.internal.net.http.frame
- *          java.net.http/jdk.internal.net.http.hpack
- * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromises
- */
-
-import jdk.internal.net.http.common.HttpHeadersImpl;
-import jdk.testlibrary.SimpleSSLContext;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import javax.net.ssl.SSLContext;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandler;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.net.http.HttpResponse.BodySubscriber;
-import java.net.http.HttpResponse.PushPromiseHandler;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Flow;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.lang.System.out;
-import static java.lang.System.err;
-import static java.lang.String.format;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-public class ThrowingPushPromises implements HttpServerAdapters {
-
-    SSLContext sslContext;
-    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
-    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
-    String http2URI_fixed;
-    String http2URI_chunk;
-    String https2URI_fixed;
-    String https2URI_chunk;
-
-    static final int ITERATION_COUNT = 1;
-    // a shared executor helps reduce the amount of threads created by the test
-    static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
-    static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
-    static volatile boolean tasksFailed;
-    static final AtomicLong serverCount = new AtomicLong();
-    static final AtomicLong clientCount = new AtomicLong();
-    static final long start = System.nanoTime();
-    public static String now() {
-        long now = System.nanoTime() - start;
-        long secs = now / 1000_000_000;
-        long mill = (now % 1000_000_000) / 1000_000;
-        long nan = now % 1000_000;
-        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
-    }
-
-    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
-    private volatile HttpClient sharedClient;
-
-    static class TestExecutor implements Executor {
-        final AtomicLong tasks = new AtomicLong();
-        Executor executor;
-        TestExecutor(Executor executor) {
-            this.executor = executor;
-        }
-
-        @Override
-        public void execute(Runnable command) {
-            long id = tasks.incrementAndGet();
-            executor.execute(() -> {
-                try {
-                    command.run();
-                } catch (Throwable t) {
-                    tasksFailed = true;
-                    out.printf(now() + "Task %s failed: %s%n", id, t);
-                    err.printf(now() + "Task %s failed: %s%n", id, t);
-                    FAILURES.putIfAbsent("Task " + id, t);
-                    throw t;
-                }
-            });
-        }
-    }
-
-    @AfterClass
-    static final void printFailedTests() {
-        out.println("\n=========================");
-        try {
-            out.printf("%n%sCreated %d servers and %d clients%n",
-                    now(), serverCount.get(), clientCount.get());
-            if (FAILURES.isEmpty()) return;
-            out.println("Failed tests: ");
-            FAILURES.entrySet().forEach((e) -> {
-                out.printf("\t%s: %s%n", e.getKey(), e.getValue());
-                e.getValue().printStackTrace(out);
-                e.getValue().printStackTrace();
-            });
-            if (tasksFailed) {
-                out.println("WARNING: Some tasks failed");
-            }
-        } finally {
-            out.println("\n=========================\n");
-        }
-    }
-
-    private String[] uris() {
-        return new String[] {
-                http2URI_fixed,
-                http2URI_chunk,
-                https2URI_fixed,
-                https2URI_chunk,
-        };
-    }
-
-    @DataProvider(name = "noThrows")
-    public Object[][] noThrows() {
-        String[] uris = uris();
-        Object[][] result = new Object[uris.length * 2][];
-
-        int i = 0;
-        for (boolean sameClient : List.of(false, true)) {
-            for (String uri: uris()) {
-                result[i++] = new Object[] {uri, sameClient};
-            }
-        }
-        assert i == uris.length * 2;
-        return result;
-    }
-
-    @DataProvider(name = "variants")
-    public Object[][] variants() {
-        String[] uris = uris();
-        Object[][] result = new Object[uris.length * 2 * 2][];
-        int i = 0;
-        for (Thrower thrower : List.of(
-                new UncheckedIOExceptionThrower(),
-                new UncheckedCustomExceptionThrower())) {
-            for (boolean sameClient : List.of(false, true)) {
-                for (String uri : uris()) {
-                    result[i++] = new Object[]{uri, sameClient, thrower};
-                }
-            }
-        }
-        assert i == uris.length * 2 * 2;
-        return result;
-    }
-
-    private HttpClient makeNewClient() {
-        clientCount.incrementAndGet();
-        return TRACKER.track(HttpClient.newBuilder()
-                .proxy(HttpClient.Builder.NO_PROXY)
-                .executor(executor)
-                .sslContext(sslContext)
-                .build());
-    }
-
-    HttpClient newHttpClient(boolean share) {
-        if (!share) return makeNewClient();
-        HttpClient shared = sharedClient;
-        if (shared != null) return shared;
-        synchronized (this) {
-            shared = sharedClient;
-            if (shared == null) {
-                shared = sharedClient = makeNewClient();
-            }
-            return shared;
-        }
-    }
-
-    @Test(dataProvider = "noThrows")
-    public void testNoThrows(String uri, boolean sameClient)
-            throws Exception {
-        HttpClient client = null;
-        out.printf("%ntestNoThrows(%s, %b)%n", uri, sameClient);
-        for (int i=0; i< ITERATION_COUNT; i++) {
-            if (!sameClient || client == null)
-                client = newHttpClient(sameClient);
-
-            HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
-                    .build();
-            BodyHandler<Stream<String>> handler =
-                    new ThrowingBodyHandler((w) -> {},
-                                            BodyHandlers.ofLines());
-            Map<HttpRequest, CompletableFuture<HttpResponse<Stream<String>>>> pushPromises =
-                    new ConcurrentHashMap<>();
-            PushPromiseHandler<Stream<String>> pushHandler = new PushPromiseHandler<>() {
-                @Override
-                public void applyPushPromise(HttpRequest initiatingRequest,
-                                             HttpRequest pushPromiseRequest,
-                                             Function<BodyHandler<Stream<String>>,
-                                                     CompletableFuture<HttpResponse<Stream<String>>>>
-                                                     acceptor) {
-                    pushPromises.putIfAbsent(pushPromiseRequest, acceptor.apply(handler));
-                }
-            };
-            HttpResponse<Stream<String>> response =
-                    client.sendAsync(req, BodyHandlers.ofLines(), pushHandler).get();
-            String body = response.body().collect(Collectors.joining("|"));
-            assertEquals(URI.create(body).getPath(), URI.create(uri).getPath());
-            for (HttpRequest promised : pushPromises.keySet()) {
-                out.printf("%s Received promise: %s%n\tresponse: %s%n",
-                        now(), promised, pushPromises.get(promised).get());
-                String promisedBody = pushPromises.get(promised).get().body()
-                        .collect(Collectors.joining("|"));
-                assertEquals(promisedBody, promised.uri().toASCIIString());
-            }
-            assertEquals(3, pushPromises.size());
-        }
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsString(String uri,
-                                     boolean sameClient,
-                                     Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsString(%s, %b, %s)",
-                             uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofString,
-                this::checkAsString, thrower);
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsLines(String uri,
-                                    boolean sameClient,
-                                    Thrower thrower)
-            throws Exception
-    {
-        String test =  format("testThrowingAsLines(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
-                this::checkAsLines, thrower);
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsInputStream(String uri,
-                                          boolean sameClient,
-                                          Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsInputStream(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
-                this::checkAsInputStream,  thrower);
-    }
-
-    private <T,U> void testThrowing(String name, String uri, boolean sameClient,
-                                    Supplier<BodyHandler<T>> handlers,
-                                    Finisher finisher, Thrower thrower)
-            throws Exception
-    {
-        out.printf("%n%s%s%n", now(), name);
-        try {
-            testThrowing(uri, sameClient, handlers, finisher, thrower);
-        } catch (Error | Exception x) {
-            FAILURES.putIfAbsent(name, x);
-            throw x;
-        }
-    }
-
-    private <T,U> void testThrowing(String uri, boolean sameClient,
-                                    Supplier<BodyHandler<T>> handlers,
-                                    Finisher finisher, Thrower thrower)
-            throws Exception
-    {
-        HttpClient client = null;
-        for (Where where : Where.values()) {
-            if (where == Where.ON_ERROR) continue;
-            if (!sameClient || client == null)
-                client = newHttpClient(sameClient);
-
-            HttpRequest req = HttpRequest.
-                    newBuilder(URI.create(uri))
-                    .build();
-            ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<T>>> promiseMap =
-                    new ConcurrentHashMap<>();
-            Supplier<BodyHandler<T>> throwing = () ->
-                    new ThrowingBodyHandler(where.select(thrower), handlers.get());
-            PushPromiseHandler<T> pushHandler = new ThrowingPromiseHandler<>(
-                    where.select(thrower),
-                    PushPromiseHandler.of((r) -> throwing.get(), promiseMap));
-            out.println("try throwing in " + where);
-            HttpResponse<T> response = null;
-            try {
-                response = client.sendAsync(req, handlers.get(), pushHandler).join();
-            } catch (Error | Exception x) {
-                throw x;
-            }
-            if (response != null) {
-                finisher.finish(where, req.uri(), response, thrower, promiseMap);
-            }
-        }
-    }
-
-    enum Where {
-        BODY_HANDLER, ON_SUBSCRIBE, ON_NEXT, ON_COMPLETE, ON_ERROR, GET_BODY, BODY_CF,
-        BEFORE_ACCEPTING, AFTER_ACCEPTING;
-        public Consumer<Where> select(Consumer<Where> consumer) {
-            return new Consumer<Where>() {
-                @Override
-                public void accept(Where where) {
-                    if (Where.this == where) {
-                        consumer.accept(where);
-                    }
-                }
-            };
-        }
-    }
-
-    interface Thrower extends Consumer<Where>, Predicate<Throwable> {
-
-    }
-
-    interface Finisher<T,U> {
-        U finish(Where w, URI requestURI, HttpResponse<T> resp, Thrower thrower,
-                 Map<HttpRequest, CompletableFuture<HttpResponse<T>>> promises);
-    }
-
-    final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
-        String msg = "Expected exception not thrown in " + w
-                + "\n\tReceived: " + resp
-                + "\n\tWith body: " + resp.body();
-        System.out.println(msg);
-        throw new RuntimeException(msg);
-    }
-
-    final List<String> checkAsString(Where w, URI reqURI,
-                                    HttpResponse<String> resp,
-                                    Thrower thrower,
-                                    Map<HttpRequest, CompletableFuture<HttpResponse<String>>> promises) {
-        Function<HttpResponse<String>, List<String>> extractor =
-                (r) -> List.of(r.body());
-        return check(w, reqURI, resp, thrower, promises, extractor);
-    }
-
-    final List<String> checkAsLines(Where w, URI reqURI,
-                                    HttpResponse<Stream<String>> resp,
-                                    Thrower thrower,
-                                    Map<HttpRequest, CompletableFuture<HttpResponse<Stream<String>>>> promises) {
-        Function<HttpResponse<Stream<String>>, List<String>> extractor =
-                (r) -> r.body().collect(Collectors.toList());
-        return check(w, reqURI, resp, thrower, promises, extractor);
-    }
-
-    final List<String> checkAsInputStream(Where w, URI reqURI,
-                                          HttpResponse<InputStream> resp,
-                                          Thrower thrower,
-                                          Map<HttpRequest, CompletableFuture<HttpResponse<InputStream>>> promises)
-    {
-        Function<HttpResponse<InputStream>, List<String>> extractor = (r) -> {
-            List<String> result;
-            try (InputStream is = r.body()) {
-                result = new BufferedReader(new InputStreamReader(is))
-                        .lines().collect(Collectors.toList());
-            } catch (Throwable t) {
-                throw new CompletionException(t);
-            }
-            return result;
-        };
-        return check(w, reqURI, resp, thrower, promises, extractor);
-    }
-
-    private final <T> List<String> check(Where w, URI reqURI,
-                                 HttpResponse<T> resp,
-                                 Thrower thrower,
-                                 Map<HttpRequest, CompletableFuture<HttpResponse<T>>> promises,
-                                 Function<HttpResponse<T>, List<String>> extractor)
-    {
-        List<String> result = extractor.apply(resp);
-        for (HttpRequest req : promises.keySet()) {
-            switch (w) {
-                case BEFORE_ACCEPTING:
-                    throw new RuntimeException("No push promise should have been received" +
-                            " for " + reqURI + " in " + w + ": got " + promises.keySet());
-                default:
-                    break;
-            }
-            HttpResponse<T> presp;
-            try {
-                presp = promises.get(req).join();
-            } catch (Error | Exception x) {
-                Throwable cause = findCause(x, thrower);
-                if (cause != null) {
-                    out.println(now() + "Got expected exception in "
-                            + w + ": " + cause);
-                    continue;
-                }
-                throw x;
-            }
-            switch (w) {
-                case BEFORE_ACCEPTING:
-                case AFTER_ACCEPTING:
-                case BODY_HANDLER:
-                case GET_BODY:
-                case BODY_CF:
-                    return shouldHaveThrown(w, presp, thrower);
-                default:
-                    break;
-            }
-            List<String> presult = null;
-            try {
-                presult = extractor.apply(presp);
-            } catch (Error | Exception x) {
-                Throwable cause = findCause(x, thrower);
-                if (cause != null) {
-                    out.println(now() + "Got expected exception for "
-                            + req + " in " + w + ": " + cause);
-                    continue;
-                }
-                throw x;
-            }
-            throw new RuntimeException("Expected exception not thrown for "
-                    + req + " in " + w);
-        }
-        final int expectedCount;
-        switch (w) {
-            case BEFORE_ACCEPTING:
-                expectedCount = 0;
-                break;
-            default:
-                expectedCount = 3;
-        }
-        assertEquals(promises.size(), expectedCount,
-                "bad promise count for " + reqURI + " with " + w);
-        assertEquals(result, List.of(reqURI.toASCIIString()));
-        return result;
-    }
-
-    private static Throwable findCause(Throwable x,
-                                       Predicate<Throwable> filter) {
-        while (x != null && !filter.test(x)) x = x.getCause();
-        return x;
-    }
-
-    static final class UncheckedCustomExceptionThrower implements Thrower {
-        @Override
-        public void accept(Where where) {
-            out.println(now() + "Throwing in " + where);
-            throw new UncheckedCustomException(where.name());
-        }
-
-        @Override
-        public boolean test(Throwable throwable) {
-            return UncheckedCustomException.class.isInstance(throwable);
-        }
-
-        @Override
-        public String toString() {
-            return "UncheckedCustomExceptionThrower";
-        }
-    }
-
-    static final class UncheckedIOExceptionThrower implements Thrower {
-        @Override
-        public void accept(Where where) {
-            out.println(now() + "Throwing in " + where);
-            throw new UncheckedIOException(new CustomIOException(where.name()));
-        }
-
-        @Override
-        public boolean test(Throwable throwable) {
-            return UncheckedIOException.class.isInstance(throwable)
-                    && CustomIOException.class.isInstance(throwable.getCause());
-        }
-
-        @Override
-        public String toString() {
-            return "UncheckedIOExceptionThrower";
-        }
-    }
-
-    static final class UncheckedCustomException extends RuntimeException {
-        UncheckedCustomException(String message) {
-            super(message);
-        }
-        UncheckedCustomException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
-    static final class CustomIOException extends IOException {
-        CustomIOException(String message) {
-            super(message);
-        }
-        CustomIOException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
-    static final class ThrowingPromiseHandler<T> implements PushPromiseHandler<T> {
-        final Consumer<Where> throwing;
-        final PushPromiseHandler<T> pushHandler;
-        ThrowingPromiseHandler(Consumer<Where> throwing, PushPromiseHandler<T> pushHandler) {
-            this.throwing = throwing;
-            this.pushHandler = pushHandler;
-        }
-
-        @Override
-        public void applyPushPromise(HttpRequest initiatingRequest,
-                                     HttpRequest pushPromiseRequest,
-                                     Function<BodyHandler<T>,
-                                             CompletableFuture<HttpResponse<T>>> acceptor) {
-            throwing.accept(Where.BEFORE_ACCEPTING);
-            pushHandler.applyPushPromise(initiatingRequest, pushPromiseRequest, acceptor);
-            throwing.accept(Where.AFTER_ACCEPTING);
-        }
-    }
-
-    static final class ThrowingBodyHandler<T> implements BodyHandler<T> {
-        final Consumer<Where> throwing;
-        final BodyHandler<T> bodyHandler;
-        ThrowingBodyHandler(Consumer<Where> throwing, BodyHandler<T> bodyHandler) {
-            this.throwing = throwing;
-            this.bodyHandler = bodyHandler;
-        }
-        @Override
-        public BodySubscriber<T> apply(HttpResponse.ResponseInfo rinfo) {
-            throwing.accept(Where.BODY_HANDLER);
-            BodySubscriber<T> subscriber = bodyHandler.apply(rinfo);
-            return new ThrowingBodySubscriber(throwing, subscriber);
-        }
-    }
-
-    static final class ThrowingBodySubscriber<T> implements BodySubscriber<T> {
-        private final BodySubscriber<T> subscriber;
-        volatile boolean onSubscribeCalled;
-        final Consumer<Where> throwing;
-        ThrowingBodySubscriber(Consumer<Where> throwing, BodySubscriber<T> subscriber) {
-            this.throwing = throwing;
-            this.subscriber = subscriber;
-        }
-
-        @Override
-        public void onSubscribe(Flow.Subscription subscription) {
-            //out.println("onSubscribe ");
-            onSubscribeCalled = true;
-            throwing.accept(Where.ON_SUBSCRIBE);
-            subscriber.onSubscribe(subscription);
-        }
-
-        @Override
-        public void onNext(List<ByteBuffer> item) {
-           // out.println("onNext " + item);
-            assertTrue(onSubscribeCalled);
-            throwing.accept(Where.ON_NEXT);
-            subscriber.onNext(item);
-        }
-
-        @Override
-        public void onError(Throwable throwable) {
-            //out.println("onError");
-            assertTrue(onSubscribeCalled);
-            throwing.accept(Where.ON_ERROR);
-            subscriber.onError(throwable);
-        }
-
-        @Override
-        public void onComplete() {
-            //out.println("onComplete");
-            assertTrue(onSubscribeCalled, "onComplete called before onSubscribe");
-            throwing.accept(Where.ON_COMPLETE);
-            subscriber.onComplete();
-        }
-
-        @Override
-        public CompletionStage<T> getBody() {
-            throwing.accept(Where.GET_BODY);
-            try {
-                throwing.accept(Where.BODY_CF);
-            } catch (Throwable t) {
-                return CompletableFuture.failedFuture(t);
-            }
-            return subscriber.getBody();
-        }
-    }
-
-
-    @BeforeTest
-    public void setup() throws Exception {
-        sslContext = new SimpleSSLContext().get();
-        if (sslContext == null)
-            throw new AssertionError("Unexpected null sslContext");
-
-        // HTTP/2
-        HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
-        HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
-
-        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
-        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
-        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
-        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
-        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
-
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
-        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
-        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
-        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
-        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
-
-        serverCount.addAndGet(2);
-        http2TestServer.start();
-        https2TestServer.start();
-    }
-
-    @AfterTest
-    public void teardown() throws Exception {
-        String sharedClientName =
-                sharedClient == null ? null : sharedClient.toString();
-        sharedClient = null;
-        Thread.sleep(100);
-        AssertionError fail = TRACKER.check(500);
-        try {
-            http2TestServer.stop();
-            https2TestServer.stop();
-        } finally {
-            if (fail != null) {
-                if (sharedClientName != null) {
-                    System.err.println("Shared client name is: " + sharedClientName);
-                }
-                throw fail;
-            }
-        }
-    }
-
-    private static void pushPromiseFor(HttpTestExchange t, URI requestURI, String pushPath, boolean fixed)
-            throws IOException
-    {
-        try {
-            URI promise = new URI(requestURI.getScheme(),
-                    requestURI.getAuthority(),
-                    pushPath, null, null);
-            byte[] promiseBytes = promise.toASCIIString().getBytes(UTF_8);
-            out.printf("TestServer: %s Pushing promise: %s%n", now(), promise);
-            err.printf("TestServer: %s Pushing promise: %s%n", now(), promise);
-            HttpTestHeaders headers =  HttpTestHeaders.of(new HttpHeadersImpl());
-            if (fixed) {
-                headers.addHeader("Content-length", String.valueOf(promiseBytes.length));
-            }
-            t.serverPush(promise, headers, promiseBytes);
-        } catch (URISyntaxException x) {
-            throw new IOException(x.getMessage(), x);
-        }
-    }
-
-    static class HTTP_FixedLengthHandler implements HttpTestHandler {
-        @Override
-        public void handle(HttpTestExchange t) throws IOException {
-            out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
-            try (InputStream is = t.getRequestBody()) {
-                is.readAllBytes();
-            }
-            URI requestURI = t.getRequestURI();
-            for (int i = 1; i<2; i++) {
-                String path = requestURI.getPath() + "/before/promise-" + i;
-                pushPromiseFor(t, requestURI, path, true);
-            }
-            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
-            t.sendResponseHeaders(200, resp.length);  //fixed content length
-            try (OutputStream os = t.getResponseBody()) {
-                int bytes = resp.length/3;
-                for (int i = 0; i<2; i++) {
-                    String path = requestURI.getPath() + "/after/promise-" + (i + 2);
-                    os.write(resp, i * bytes, bytes);
-                    os.flush();
-                    pushPromiseFor(t, requestURI, path, true);
-                }
-                os.write(resp, 2*bytes, resp.length - 2*bytes);
-            }
-        }
-
-    }
-
-    static class HTTP_ChunkedHandler implements HttpTestHandler {
-        @Override
-        public void handle(HttpTestExchange t) throws IOException {
-            out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
-            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
-            try (InputStream is = t.getRequestBody()) {
-                is.readAllBytes();
-            }
-            URI requestURI = t.getRequestURI();
-            for (int i = 1; i<2; i++) {
-                String path = requestURI.getPath() + "/before/promise-" + i;
-                pushPromiseFor(t, requestURI, path, false);
-            }
-            t.sendResponseHeaders(200, -1); // chunked/variable
-            try (OutputStream os = t.getResponseBody()) {
-                int bytes = resp.length/3;
-                for (int i = 0; i<2; i++) {
-                    String path = requestURI.getPath() + "/after/promise-" + (i + 2);
-                    os.write(resp, i * bytes, bytes);
-                    os.flush();
-                    pushPromiseFor(t, requestURI, path, false);
-                }
-                os.write(resp, 2*bytes, resp.length - 2*bytes);
-            }
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamCustom.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesAsInputStreamCustom
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesAsInputStreamCustom
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesAsInputStreamCustom extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "customVariants")
+    public void testThrowingAsInputStream(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsInputStreamImpl(uri, sameClient, thrower);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamIO.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesAsInputStreamIO
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesAsInputStreamIO
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesAsInputStreamIO extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "ioVariants")
+    public void testThrowingAsInputStream(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsInputStreamImpl(uri, sameClient, thrower);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesCustom.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesAsLinesCustom
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesAsLinesCustom
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesAsLinesCustom extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "customVariants")
+    public void testThrowingAsLines(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsLinesImpl(uri, sameClient, thrower);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesIO.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesAsLinesIO
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesAsLinesIO
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesAsLinesIO extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "ioVariants")
+    public void testThrowingAsLines(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsLinesImpl(uri, sameClient, thrower);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringCustom.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesAsStringCustom
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesAsStringCustom
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesAsStringCustom extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "customVariants")
+    public void testThrowingAsString(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringIO.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesAsStringIO
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesAsStringIO
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesAsStringIO extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "ioVariants")
+    public void testThrowingAsString(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesSanity.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when push promise handlers and their
+ *          response body handlers and subscribers throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker AbstractThrowingPushPromises ThrowingPushPromisesSanity
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingPushPromisesSanity
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingPushPromisesSanity extends AbstractThrowingPushPromises {
+
+    @Test(dataProvider = "sanity")
+    public void testSanity(String uri, boolean sameClient)
+            throws Exception {
+        super.testSanityImpl(uri, sameClient);
+    }
+}
--- a/test/jdk/java/net/httpclient/ThrowingSubscribers.java	Wed Jun 20 11:12:48 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,734 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary Tests what happens when response body handlers and subscribers
- *          throw unexpected exceptions.
- * @library /lib/testlibrary http2/server
- * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
-  *       ReferenceTracker ThrowingSubscribers
- * @modules java.base/sun.net.www.http
- *          java.net.http/jdk.internal.net.http.common
- *          java.net.http/jdk.internal.net.http.frame
- *          java.net.http/jdk.internal.net.http.hpack
- * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribers
- */
-
-import com.sun.net.httpserver.HttpServer;
-import com.sun.net.httpserver.HttpsConfigurator;
-import com.sun.net.httpserver.HttpsServer;
-import jdk.testlibrary.SimpleSSLContext;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import javax.net.ssl.SSLContext;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.net.http.HttpClient;
-import java.net.http.HttpHeaders;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandler;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.net.http.HttpResponse.BodySubscriber;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Flow;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.lang.System.out;
-import static java.lang.String.format;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-public class ThrowingSubscribers implements HttpServerAdapters {
-
-    SSLContext sslContext;
-    HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
-    HttpTestServer httpsTestServer;   // HTTPS/1.1
-    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
-    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
-    String httpURI_fixed;
-    String httpURI_chunk;
-    String httpsURI_fixed;
-    String httpsURI_chunk;
-    String http2URI_fixed;
-    String http2URI_chunk;
-    String https2URI_fixed;
-    String https2URI_chunk;
-
-    static final int ITERATION_COUNT = 1;
-    // a shared executor helps reduce the amount of threads created by the test
-    static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
-    static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
-    static volatile boolean tasksFailed;
-    static final AtomicLong serverCount = new AtomicLong();
-    static final AtomicLong clientCount = new AtomicLong();
-    static final long start = System.nanoTime();
-    public static String now() {
-        long now = System.nanoTime() - start;
-        long secs = now / 1000_000_000;
-        long mill = (now % 1000_000_000) / 1000_000;
-        long nan = now % 1000_000;
-        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
-    }
-
-    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
-    private volatile HttpClient sharedClient;
-
-    static class TestExecutor implements Executor {
-        final AtomicLong tasks = new AtomicLong();
-        Executor executor;
-        TestExecutor(Executor executor) {
-            this.executor = executor;
-        }
-
-        @Override
-        public void execute(Runnable command) {
-            long id = tasks.incrementAndGet();
-            executor.execute(() -> {
-                try {
-                    command.run();
-                } catch (Throwable t) {
-                    tasksFailed = true;
-                    System.out.printf(now() + "Task %s failed: %s%n", id, t);
-                    System.err.printf(now() + "Task %s failed: %s%n", id, t);
-                    FAILURES.putIfAbsent("Task " + id, t);
-                    throw t;
-                }
-            });
-        }
-    }
-
-    @AfterClass
-    static final void printFailedTests() {
-        out.println("\n=========================");
-        try {
-            out.printf("%n%sCreated %d servers and %d clients%n",
-                    now(), serverCount.get(), clientCount.get());
-            if (FAILURES.isEmpty()) return;
-            out.println("Failed tests: ");
-            FAILURES.entrySet().forEach((e) -> {
-                out.printf("\t%s: %s%n", e.getKey(), e.getValue());
-                e.getValue().printStackTrace(out);
-                e.getValue().printStackTrace();
-            });
-            if (tasksFailed) {
-                System.out.println("WARNING: Some tasks failed");
-            }
-        } finally {
-            out.println("\n=========================\n");
-        }
-    }
-
-    private String[] uris() {
-        return new String[] {
-                httpURI_fixed,
-                httpURI_chunk,
-                httpsURI_fixed,
-                httpsURI_chunk,
-                http2URI_fixed,
-                http2URI_chunk,
-                https2URI_fixed,
-                https2URI_chunk,
-        };
-    }
-
-    @DataProvider(name = "noThrows")
-    public Object[][] noThrows() {
-        String[] uris = uris();
-        Object[][] result = new Object[uris.length * 2][];
-        int i = 0;
-        for (boolean sameClient : List.of(false, true)) {
-            for (String uri: uris()) {
-                result[i++] = new Object[] {uri, sameClient};
-            }
-        }
-        assert i == uris.length * 2;
-        return result;
-    }
-
-    @DataProvider(name = "variants")
-    public Object[][] variants() {
-        String[] uris = uris();
-        Object[][] result = new Object[uris.length * 2 * 2][];
-        int i = 0;
-        for (Thrower thrower : List.of(
-                new UncheckedIOExceptionThrower(),
-                new UncheckedCustomExceptionThrower())) {
-            for (boolean sameClient : List.of(false, true)) {
-                for (String uri : uris()) {
-                    result[i++] = new Object[]{uri, sameClient, thrower};
-                }
-            }
-        }
-        assert i == uris.length * 2 * 2;
-        return result;
-    }
-
-    private HttpClient makeNewClient() {
-        clientCount.incrementAndGet();
-        HttpClient client =  HttpClient.newBuilder()
-                .proxy(HttpClient.Builder.NO_PROXY)
-                .executor(executor)
-                .sslContext(sslContext)
-                .build();
-        return TRACKER.track(client);
-    }
-
-    HttpClient newHttpClient(boolean share) {
-        if (!share) return makeNewClient();
-        HttpClient shared = sharedClient;
-        if (shared != null) return shared;
-        synchronized (this) {
-            shared = sharedClient;
-            if (shared == null) {
-                shared = sharedClient = makeNewClient();
-            }
-            return shared;
-        }
-    }
-
-    enum SubscriberType {
-        INLINE,  // In line subscribers complete their CF on ON_COMPLETE
-                 // e.g. BodySubscribers::ofString
-        OFFLINE; // Off line subscribers complete their CF immediately
-                 // but require the client to pull the data after the
-                 // CF completes (e.g. BodySubscribers::ofInputStream)
-    }
-
-    static EnumSet<Where> excludes(SubscriberType type) {
-        EnumSet<Where> set = EnumSet.noneOf(Where.class);
-
-        if (type == SubscriberType.OFFLINE) {
-            // Throwing on onSubscribe needs some more work
-            // for the case of InputStream, where the body has already
-            // completed by the time the subscriber is subscribed.
-            // The only way we have at that point to relay the exception
-            // is to call onError on the subscriber, but should we if
-            // Subscriber::onSubscribed has thrown an exception and
-            // not completed normally?
-            set.add(Where.ON_SUBSCRIBE);
-        }
-
-        // Don't know how to make the stack reliably cause onError
-        // to be called without closing the connection.
-        // And how do we get the exception if onError throws anyway?
-        set.add(Where.ON_ERROR);
-
-        return set;
-    }
-
-    @Test(dataProvider = "noThrows")
-    public void testNoThrows(String uri, boolean sameClient)
-            throws Exception {
-        HttpClient client = null;
-        out.printf("%ntestNoThrows(%s, %b)%n", uri, sameClient);
-        for (int i=0; i< ITERATION_COUNT; i++) {
-            if (!sameClient || client == null)
-                client = newHttpClient(sameClient);
-
-            HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
-                    .build();
-            BodyHandler<String> handler =
-                    new ThrowingBodyHandler((w) -> {},
-                                            BodyHandlers.ofString());
-            HttpResponse<String> response = client.send(req, handler);
-            String body = response.body();
-            assertEquals(URI.create(body).getPath(), URI.create(uri).getPath());
-        }
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsString(String uri,
-                                     boolean sameClient,
-                                     Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsString(%s, %b, %s)",
-                             uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofString,
-                this::shouldHaveThrown, thrower,false,
-                excludes(SubscriberType.INLINE));
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsLines(String uri,
-                                    boolean sameClient,
-                                    Thrower thrower)
-            throws Exception
-    {
-        String test =  format("testThrowingAsLines(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
-                this::checkAsLines, thrower,false,
-                excludes(SubscriberType.OFFLINE));
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsInputStream(String uri,
-                                          boolean sameClient,
-                                          Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsInputStream(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
-                this::checkAsInputStream,  thrower,false,
-                excludes(SubscriberType.OFFLINE));
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsStringAsync(String uri,
-                                          boolean sameClient,
-                                          Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsStringAsync(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofString,
-                     this::shouldHaveThrown, thrower, true,
-                excludes(SubscriberType.INLINE));
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsLinesAsync(String uri,
-                                         boolean sameClient,
-                                         Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsLinesAsync(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
-                this::checkAsLines, thrower,true,
-                excludes(SubscriberType.OFFLINE));
-    }
-
-    @Test(dataProvider = "variants")
-    public void testThrowingAsInputStreamAsync(String uri,
-                                               boolean sameClient,
-                                               Thrower thrower)
-            throws Exception
-    {
-        String test = format("testThrowingAsInputStreamAsync(%s, %b, %s)",
-                uri, sameClient, thrower);
-        testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
-                this::checkAsInputStream, thrower,true,
-                excludes(SubscriberType.OFFLINE));
-    }
-
-    private <T,U> void testThrowing(String name, String uri, boolean sameClient,
-                                    Supplier<BodyHandler<T>> handlers,
-                                    Finisher finisher, Thrower thrower,
-                                    boolean async, EnumSet<Where> excludes)
-            throws Exception
-    {
-        out.printf("%n%s%s%n", now(), name);
-        try {
-            testThrowing(uri, sameClient, handlers, finisher, thrower, async, excludes);
-        } catch (Error | Exception x) {
-            FAILURES.putIfAbsent(name, x);
-            throw x;
-        }
-    }
-
-    private <T,U> void testThrowing(String uri, boolean sameClient,
-                                    Supplier<BodyHandler<T>> handlers,
-                                    Finisher finisher, Thrower thrower,
-                                    boolean async,
-                                    EnumSet<Where> excludes)
-            throws Exception
-    {
-        HttpClient client = null;
-        for (Where where : EnumSet.complementOf(excludes)) {
-
-            if (!sameClient || client == null)
-                client = newHttpClient(sameClient);
-
-            HttpRequest req = HttpRequest.
-                    newBuilder(URI.create(uri))
-                    .build();
-            BodyHandler<T> handler =
-                    new ThrowingBodyHandler(where.select(thrower), handlers.get());
-            System.out.println("try throwing in " + where);
-            HttpResponse<T> response = null;
-            if (async) {
-                try {
-                    response = client.sendAsync(req, handler).join();
-                } catch (Error | Exception x) {
-                    Throwable cause = findCause(x, thrower);
-                    if (cause == null) throw causeNotFound(where, x);
-                    System.out.println(now() + "Got expected exception: " + cause);
-                }
-            } else {
-                try {
-                    response = client.send(req, handler);
-                } catch (Error | Exception t) {
-                    if (thrower.test(t)) {
-                        System.out.println(now() + "Got expected exception: " + t);
-                    } else throw causeNotFound(where, t);
-                }
-            }
-            if (response != null) {
-                finisher.finish(where, response, thrower);
-            }
-        }
-    }
-
-    enum Where {
-        BODY_HANDLER, ON_SUBSCRIBE, ON_NEXT, ON_COMPLETE, ON_ERROR, GET_BODY, BODY_CF;
-        public Consumer<Where> select(Consumer<Where> consumer) {
-            return new Consumer<Where>() {
-                @Override
-                public void accept(Where where) {
-                    if (Where.this == where) {
-                        consumer.accept(where);
-                    }
-                }
-            };
-        }
-    }
-
-    static AssertionError causeNotFound(Where w, Throwable t) {
-        return new AssertionError("Expected exception not found in " + w, t);
-    }
-
-    interface Thrower extends Consumer<Where>, Predicate<Throwable> {
-
-    }
-
-    interface Finisher<T,U> {
-        U finish(Where w, HttpResponse<T> resp, Thrower thrower) throws IOException;
-    }
-
-    final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
-        String msg = "Expected exception not thrown in " + w
-                + "\n\tReceived: " + resp
-                + "\n\tWith body: " + resp.body();
-        System.out.println(msg);
-        throw new RuntimeException(msg);
-    }
-
-    final List<String> checkAsLines(Where w, HttpResponse<Stream<String>> resp, Thrower thrower) {
-        switch(w) {
-            case BODY_HANDLER: return shouldHaveThrown(w, resp, thrower);
-            case GET_BODY: return shouldHaveThrown(w, resp, thrower);
-            case BODY_CF: return shouldHaveThrown(w, resp, thrower);
-            default: break;
-        }
-        List<String> result = null;
-        try {
-            result = resp.body().collect(Collectors.toList());
-        } catch (Error | Exception x) {
-            Throwable cause = findCause(x, thrower);
-            if (cause != null) {
-                out.println(now() + "Got expected exception in " + w + ": " + cause);
-                return result;
-            }
-            throw causeNotFound(w, x);
-        }
-        return shouldHaveThrown(w, resp, thrower);
-    }
-
-    final List<String> checkAsInputStream(Where w, HttpResponse<InputStream> resp,
-                                    Thrower thrower)
-            throws IOException
-    {
-        switch(w) {
-            case BODY_HANDLER: return shouldHaveThrown(w, resp, thrower);
-            case GET_BODY: return shouldHaveThrown(w, resp, thrower);
-            case BODY_CF: return shouldHaveThrown(w, resp, thrower);
-            default: break;
-        }
-        List<String> result = null;
-        try (InputStreamReader r1 = new InputStreamReader(resp.body(), UTF_8);
-             BufferedReader r = new BufferedReader(r1)) {
-            try {
-                result = r.lines().collect(Collectors.toList());
-            } catch (Error | Exception x) {
-                Throwable cause = findCause(x, thrower);
-                if (cause != null) {
-                    out.println(now() + "Got expected exception in " + w + ": " + cause);
-                    return result;
-                }
-                throw causeNotFound(w, x);
-            }
-        }
-        return shouldHaveThrown(w, resp, thrower);
-    }
-
-    private static Throwable findCause(Throwable x,
-                                       Predicate<Throwable> filter) {
-        while (x != null && !filter.test(x)) x = x.getCause();
-        return x;
-    }
-
-    static final class UncheckedCustomExceptionThrower implements Thrower {
-        @Override
-        public void accept(Where where) {
-            out.println(now() + "Throwing in " + where);
-            throw new UncheckedCustomException(where.name());
-        }
-
-        @Override
-        public boolean test(Throwable throwable) {
-            return UncheckedCustomException.class.isInstance(throwable);
-        }
-
-        @Override
-        public String toString() {
-            return "UncheckedCustomExceptionThrower";
-        }
-    }
-
-    static final class UncheckedIOExceptionThrower implements Thrower {
-        @Override
-        public void accept(Where where) {
-            out.println(now() + "Throwing in " + where);
-            throw new UncheckedIOException(new CustomIOException(where.name()));
-        }
-
-        @Override
-        public boolean test(Throwable throwable) {
-            return UncheckedIOException.class.isInstance(throwable)
-                    && CustomIOException.class.isInstance(throwable.getCause());
-        }
-
-        @Override
-        public String toString() {
-            return "UncheckedIOExceptionThrower";
-        }
-    }
-
-    static final class UncheckedCustomException extends RuntimeException {
-        UncheckedCustomException(String message) {
-            super(message);
-        }
-        UncheckedCustomException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
-    static final class CustomIOException extends IOException {
-        CustomIOException(String message) {
-            super(message);
-        }
-        CustomIOException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
-    static final class ThrowingBodyHandler<T> implements BodyHandler<T> {
-        final Consumer<Where> throwing;
-        final BodyHandler<T> bodyHandler;
-        ThrowingBodyHandler(Consumer<Where> throwing, BodyHandler<T> bodyHandler) {
-            this.throwing = throwing;
-            this.bodyHandler = bodyHandler;
-        }
-        @Override
-        public BodySubscriber<T> apply(HttpResponse.ResponseInfo rinfo) {
-            throwing.accept(Where.BODY_HANDLER);
-            BodySubscriber<T> subscriber = bodyHandler.apply(rinfo);
-            return new ThrowingBodySubscriber(throwing, subscriber);
-        }
-    }
-
-    static final class ThrowingBodySubscriber<T> implements BodySubscriber<T> {
-        private final BodySubscriber<T> subscriber;
-        volatile boolean onSubscribeCalled;
-        final Consumer<Where> throwing;
-        ThrowingBodySubscriber(Consumer<Where> throwing, BodySubscriber<T> subscriber) {
-            this.throwing = throwing;
-            this.subscriber = subscriber;
-        }
-
-        @Override
-        public void onSubscribe(Flow.Subscription subscription) {
-            //out.println("onSubscribe ");
-            onSubscribeCalled = true;
-            throwing.accept(Where.ON_SUBSCRIBE);
-            subscriber.onSubscribe(subscription);
-        }
-
-        @Override
-        public void onNext(List<ByteBuffer> item) {
-           // out.println("onNext " + item);
-            assertTrue(onSubscribeCalled);
-            throwing.accept(Where.ON_NEXT);
-            subscriber.onNext(item);
-        }
-
-        @Override
-        public void onError(Throwable throwable) {
-            //out.println("onError");
-            assertTrue(onSubscribeCalled);
-            throwing.accept(Where.ON_ERROR);
-            subscriber.onError(throwable);
-        }
-
-        @Override
-        public void onComplete() {
-            //out.println("onComplete");
-            assertTrue(onSubscribeCalled, "onComplete called before onSubscribe");
-            throwing.accept(Where.ON_COMPLETE);
-            subscriber.onComplete();
-        }
-
-        @Override
-        public CompletionStage<T> getBody() {
-            throwing.accept(Where.GET_BODY);
-            try {
-                throwing.accept(Where.BODY_CF);
-            } catch (Throwable t) {
-                return CompletableFuture.failedFuture(t);
-            }
-            return subscriber.getBody();
-        }
-    }
-
-
-    @BeforeTest
-    public void setup() throws Exception {
-        sslContext = new SimpleSSLContext().get();
-        if (sslContext == null)
-            throw new AssertionError("Unexpected null sslContext");
-
-        // HTTP/1.1
-        HttpTestHandler h1_fixedLengthHandler = new HTTP_FixedLengthHandler();
-        HttpTestHandler h1_chunkHandler = new HTTP_ChunkedHandler();
-        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
-        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
-        httpTestServer.addHandler(h1_fixedLengthHandler, "/http1/fixed");
-        httpTestServer.addHandler(h1_chunkHandler, "/http1/chunk");
-        httpURI_fixed = "http://" + httpTestServer.serverAuthority() + "/http1/fixed/x";
-        httpURI_chunk = "http://" + httpTestServer.serverAuthority() + "/http1/chunk/x";
-
-        HttpsServer httpsServer = HttpsServer.create(sa, 0);
-        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
-        httpsTestServer = HttpTestServer.of(httpsServer);
-        httpsTestServer.addHandler(h1_fixedLengthHandler, "/https1/fixed");
-        httpsTestServer.addHandler(h1_chunkHandler, "/https1/chunk");
-        httpsURI_fixed = "https://" + httpsTestServer.serverAuthority() + "/https1/fixed/x";
-        httpsURI_chunk = "https://" + httpsTestServer.serverAuthority() + "/https1/chunk/x";
-
-        // HTTP/2
-        HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
-        HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
-
-        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
-        http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
-        http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
-        http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
-        http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
-
-        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, 0));
-        https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
-        https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
-        https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
-        https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
-
-        serverCount.addAndGet(4);
-        httpTestServer.start();
-        httpsTestServer.start();
-        http2TestServer.start();
-        https2TestServer.start();
-    }
-
-    @AfterTest
-    public void teardown() throws Exception {
-        String sharedClientName =
-                sharedClient == null ? null : sharedClient.toString();
-        sharedClient = null;
-        Thread.sleep(100);
-        AssertionError fail = TRACKER.check(500);
-        try {
-            httpTestServer.stop();
-            httpsTestServer.stop();
-            http2TestServer.stop();
-            https2TestServer.stop();
-        } finally {
-            if (fail != null) {
-                if (sharedClientName != null) {
-                    System.err.println("Shared client name is: " + sharedClientName);
-                }
-                throw fail;
-            }
-        }
-    }
-
-    static class HTTP_FixedLengthHandler implements HttpTestHandler {
-        @Override
-        public void handle(HttpTestExchange t) throws IOException {
-            out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
-            try (InputStream is = t.getRequestBody()) {
-                is.readAllBytes();
-            }
-            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
-            t.sendResponseHeaders(200, resp.length);  //fixed content length
-            try (OutputStream os = t.getResponseBody()) {
-                os.write(resp);
-            }
-        }
-    }
-
-    static class HTTP_ChunkedHandler implements HttpTestHandler {
-        @Override
-        public void handle(HttpTestExchange t) throws IOException {
-            out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
-            byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
-            try (InputStream is = t.getRequestBody()) {
-                is.readAllBytes();
-            }
-            t.sendResponseHeaders(200, -1); // chunked/variable
-            try (OutputStream os = t.getResponseBody()) {
-                os.write(resp);
-            }
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersAsInputStream.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersAsInputStream AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersAsInputStream
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersAsInputStream extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "variants")
+    public void testThrowingAsInputStream(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsInputStreamImpl(uri, sameClient, thrower);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersAsInputStreamAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersAsInputStreamAsync AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersAsInputStreamAsync
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersAsInputStreamAsync extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "variants")
+    public void testThrowingAsInputStreamAsync(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsInputStreamAsyncImpl(uri, sameClient, thrower);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersAsLines.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersAsLines AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersAsLines
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersAsLines extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "variants")
+    public void testThrowingAsLines(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsLinesImpl(uri, sameClient, thrower);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersAsLinesAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersAsLinesAsync AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersAsLinesAsync
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersAsLinesAsync extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "variants")
+    public void testThrowingAsLinesAsync(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsLinesAsyncImpl(uri, sameClient, thrower);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersAsString.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersAsString AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersAsString
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersAsString extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "variants")
+    public void testThrowingAsString(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsStringImpl(uri, sameClient, thrower);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersAsStringAsync.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersAsStringAsync AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersAsStringAsync
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersAsStringAsync extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "variants")
+    public void testThrowingAsStringAsync(String uri, boolean sameClient, Thrower thrower)
+            throws Exception {
+        super.testThrowingAsStringAsyncImpl(uri, sameClient, thrower);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ThrowingSubscribersSanity.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Tests what happens when response body handlers and subscribers
+ *          throw unexpected exceptions.
+ * @library /lib/testlibrary http2/server
+ * @build jdk.testlibrary.SimpleSSLContext HttpServerAdapters
+  *       ReferenceTracker ThrowingSubscribersSanity AbstractThrowingSubscribers
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ * @run testng/othervm -Djdk.internal.httpclient.debug=true ThrowingSubscribersSanity
+ */
+
+import org.testng.annotations.Test;
+
+public class ThrowingSubscribersSanity extends AbstractThrowingSubscribers {
+
+    @Test(dataProvider = "sanity")
+    public void testSanity(String uri, boolean sameClient)
+            throws Exception {
+        super.testSanityImpl(uri, sameClient);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/UnauthorizedTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8203882
+ * @summary (httpclient) Check that HttpClient throws IOException when
+ *      receiving 401/407 with no WWW-Authenticate/Proxy-Authenticate
+ *      header only in the case where an authenticator is configured
+ *      for the client. If no authenticator is configured the client
+ *      should simply let the caller deal with the unauthorized response.
+ * @modules java.base/sun.net.www.http
+ *          java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ *          java.logging
+ *          jdk.httpserver
+ * @library /lib/testlibrary /test/lib http2/server
+ * @build Http2TestServer
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm
+ *       -Djdk.httpclient.HttpClient.log=headers
+ *       UnauthorizedTest
+ */
+
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Authenticator;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static java.lang.System.out;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class UnauthorizedTest implements HttpServerAdapters {
+
+    SSLContext sslContext;
+    HttpTestServer httpTestServer;        // HTTP/1.1
+    HttpTestServer httpsTestServer;       // HTTPS/1.1
+    HttpTestServer http2TestServer;       // HTTP/2 ( h2c )
+    HttpTestServer https2TestServer;      // HTTP/2 ( h2  )
+    String httpURI;
+    String httpsURI;
+    String http2URI;
+    String https2URI;
+    HttpClient authClient;
+    HttpClient noAuthClient;
+
+    static final int ITERATIONS = 3;
+
+    /*
+     * NOT_MODIFIED status code results from a conditional GET where
+     * the server does not (must not) return a response body because
+     * the condition specified in the request disallows it
+     */
+    static final int UNAUTHORIZED = 401;
+    static final int PROXY_UNAUTHORIZED = 407;
+    static final int HTTP_OK = 200;
+    static final String MESSAGE = "Unauthorized";
+
+    @DataProvider(name = "all")
+    public Object[][] positive() {
+        return new Object[][] {
+                { httpURI   + "/server", UNAUTHORIZED, true, authClient},
+                { httpsURI  + "/server", UNAUTHORIZED, true, authClient},
+                { http2URI  + "/server", UNAUTHORIZED, true, authClient},
+                { https2URI + "/server", UNAUTHORIZED, true, authClient},
+                { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
+                { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
+                { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
+                { https2URI + "/proxy",  PROXY_UNAUTHORIZED, true, authClient},
+                { httpURI   + "/server", UNAUTHORIZED, false, authClient},
+                { httpsURI  + "/server", UNAUTHORIZED, false, authClient},
+                { http2URI  + "/server", UNAUTHORIZED, false, authClient},
+                { https2URI + "/server", UNAUTHORIZED, false, authClient},
+                { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
+                { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
+                { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
+                { https2URI + "/proxy",  PROXY_UNAUTHORIZED, false, authClient},
+                { httpURI   + "/server", UNAUTHORIZED, true, noAuthClient},
+                { httpsURI  + "/server", UNAUTHORIZED, true, noAuthClient},
+                { http2URI  + "/server", UNAUTHORIZED, true, noAuthClient},
+                { https2URI + "/server", UNAUTHORIZED, true, noAuthClient},
+                { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
+                { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
+                { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
+                { https2URI + "/proxy",  PROXY_UNAUTHORIZED, true, noAuthClient},
+                { httpURI   + "/server", UNAUTHORIZED, false, noAuthClient},
+                { httpsURI  + "/server", UNAUTHORIZED, false, noAuthClient},
+                { http2URI  + "/server", UNAUTHORIZED, false, noAuthClient},
+                { https2URI + "/server", UNAUTHORIZED, false, noAuthClient},
+                { httpURI   + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
+                { httpsURI  + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
+                { http2URI  + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
+                { https2URI + "/proxy",  PROXY_UNAUTHORIZED, false, noAuthClient},
+        };
+    }
+
+    static final AtomicLong requestCounter = new AtomicLong();
+
+    static final Authenticator authenticator = new Authenticator() {
+    };
+
+    @Test(dataProvider = "all")
+    void test(String uriString, int code, boolean async, HttpClient client) throws Throwable {
+        out.printf("%n---- starting (%s, %d, %s, %s) ----%n",
+                uriString, code, async ? "async" : "sync",
+                client.authenticator().isPresent() ? "authClient" : "noAuthClient");
+        URI uri = URI.create(uriString);
+
+        HttpRequest.Builder requestBuilder = HttpRequest
+                .newBuilder(uri)
+                .GET();
+
+        HttpRequest request = requestBuilder.build();
+        out.println("Initial request: " + request.uri());
+
+        boolean shouldThrow = client.authenticator().isPresent();
+        String header = (code==UNAUTHORIZED)?"WWW-Authenticate":"Proxy-Authenticate";
+
+        HttpResponse<String> response = null;
+        try {
+           if (async) {
+                response = client.send(request, BodyHandlers.ofString());
+            } else {
+               try {
+                   response = client.sendAsync(request, BodyHandlers.ofString()).get();
+               } catch (ExecutionException ex) {
+                   throw ex.getCause();
+               }
+           }
+        } catch (IOException ex) {
+            if (shouldThrow && ex.getMessage().contains(header)) {
+                System.out.println("Got expected exception: " + ex);
+                return;
+            } else throw ex;
+        }
+
+        out.println("  Got response: " + response);
+        assertEquals(response.statusCode(), code);
+        assertEquals(response.body(),
+                (code == UNAUTHORIZED ? "WWW-" : "Proxy-") + MESSAGE);
+        if (shouldThrow) {
+            throw new RuntimeException("Expected IOException not thrown.");
+        }
+    }
+
+    // -- Infrastructure
+
+    @BeforeTest
+    public void setup() throws Exception {
+        sslContext = new SimpleSSLContext().get();
+        if (sslContext == null)
+            throw new AssertionError("Unexpected null sslContext");
+
+        InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+
+        httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
+        httpTestServer.addHandler(new UnauthorizedHandler(), "/http1/");
+        httpURI = "http://" + httpTestServer.serverAuthority() + "/http1";
+        HttpsServer httpsServer = HttpsServer.create(sa, 0);
+        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
+        httpsTestServer = HttpTestServer.of(httpsServer);
+        httpsTestServer.addHandler(new UnauthorizedHandler(),"/https1/");
+        httpsURI = "https://" + httpsTestServer.serverAuthority() + "/https1";
+
+        http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
+        http2TestServer.addHandler(new UnauthorizedHandler(), "/http2/");
+        http2URI = "http://" + http2TestServer.serverAuthority() + "/http2";
+        https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
+        https2TestServer.addHandler(new UnauthorizedHandler(), "/https2/");
+        https2URI = "https://" + https2TestServer.serverAuthority() + "/https2";
+
+        authClient = HttpClient.newBuilder()
+                .proxy(HttpClient.Builder.NO_PROXY)
+                .sslContext(sslContext)
+                .authenticator(authenticator)
+                .build();
+
+        noAuthClient = HttpClient.newBuilder()
+                .proxy(HttpClient.Builder.NO_PROXY)
+                .sslContext(sslContext)
+                .build();
+
+        httpTestServer.start();
+        httpsTestServer.start();
+        http2TestServer.start();
+        https2TestServer.start();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        httpTestServer.stop();
+        httpsTestServer.stop();
+        http2TestServer.stop();
+        https2TestServer.stop();
+    }
+
+    static class UnauthorizedHandler implements HttpTestHandler {
+
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            readAllRequestData(t); // shouldn't be any
+            String method = t.getRequestMethod();
+            String path = t.getRequestURI().getPath();
+            HttpTestResponseHeaders rsph = t.getResponseHeaders();
+
+            int code;
+            if (path.contains("server")) {
+                code = UNAUTHORIZED;
+            } else {
+                code = PROXY_UNAUTHORIZED;
+            }
+            String message = (code == UNAUTHORIZED ? "WWW-" : "Proxy-") + MESSAGE;
+            byte[] bytes = message.getBytes(UTF_8);
+            t.sendResponseHeaders(code, bytes.length);
+            try (OutputStream os = t.getResponseBody()) {
+                os.write(bytes);
+            }
+        }
+    }
+
+    static void readAllRequestData(HttpTestExchange t) throws IOException {
+        try (InputStream is = t.getRequestBody()) {
+            is.readAllBytes();
+        }
+    }
+}
--- a/test/jdk/java/net/httpclient/examples/JavadocExamples.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/examples/JavadocExamples.java	Thu Jun 21 09:53:50 2018 -0700
@@ -45,6 +45,7 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Flow;
 import java.util.regex.Pattern;
+import static java.nio.charset.StandardCharsets.UTF_8;
 
 /*
  * THE CONTENTS OF THIS FILE HAVE TO BE IN SYNC WITH THE EXAMPLES USED IN THE
@@ -156,6 +157,25 @@
         HttpResponse<Void> respons4 = client
                 .send(request, BodyHandlers.discarding());
 
+
+        // HttpResponse.BodySubscribers class-level description
+        // Streams the response body to a File
+        HttpResponse<byte[]> response5 = client
+                .send(request, responseInfo -> BodySubscribers.ofByteArray());
+
+        // Accumulates the response body and returns it as a byte[]
+        HttpResponse<byte[]> response6 = client
+                .send(request, responseInfo -> BodySubscribers.ofByteArray());
+
+        // Discards the response body
+        HttpResponse<Void> response7 = client
+                .send(request, responseInfo -> BodySubscribers.discarding());
+
+        // Accumulates the response body as a String then maps it to its bytes
+        HttpResponse<byte[]> response8 = client
+                .send(request, responseInfo ->
+                        BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes));
+
     }
 
     /**
--- a/test/jdk/java/net/httpclient/http2/BadHeadersTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/BadHeadersTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,8 +33,7 @@
  * @run testng/othervm -Djdk.internal.httpclient.debug=true BadHeadersTest
  */
 
-import jdk.internal.net.http.common.HttpHeadersImpl;
-import jdk.internal.net.http.common.Pair;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.frame.ContinuationFrame;
 import jdk.internal.net.http.frame.HeaderFrame;
 import jdk.internal.net.http.frame.HeadersFrame;
@@ -44,41 +43,38 @@
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.net.Socket;
 import java.net.URI;
 import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
 import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
 import java.util.function.BiFunction;
-
 import static java.util.List.of;
-import static jdk.internal.net.http.common.Pair.pair;
-import static org.testng.Assert.assertThrows;
+import static java.util.Map.entry;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 // Code copied from ContinuationFrameTest
 public class BadHeadersTest {
 
-    private static final List<List<Pair<String, String>>> BAD_HEADERS = of(
-            of(pair(":status", "200"),  pair(":hello", "GET")),                      // Unknown pseudo-header
-            of(pair(":status", "200"),  pair("hell o", "value")),                    // Space in the name
-            of(pair(":status", "200"),  pair("hello", "line1\r\n  line2\r\n")),      // Multiline value
-            of(pair(":status", "200"),  pair("hello", "DE" + ((char) 0x7F) + "L")),  // Bad byte in value
-            of(pair("hello", "world!"), pair(":status", "200"))                      // Pseudo header is not the first one
+    private static final List<List<Entry<String, String>>> BAD_HEADERS = of(
+        of(entry(":status", "200"),  entry(":hello", "GET")),                      // Unknown pseudo-header
+        of(entry(":status", "200"),  entry("hell o", "value")),                    // Space in the name
+        of(entry(":status", "200"),  entry("hello", "line1\r\n  line2\r\n")),      // Multiline value
+        of(entry(":status", "200"),  entry("hello", "DE" + ((char) 0x7F) + "L")),  // Bad byte in value
+        of(entry("hello", "world!"), entry(":status", "200"))                      // Pseudo header is not the first one
     );
 
     SSLContext sslContext;
@@ -143,7 +139,35 @@
     void test(String uri,
               boolean sameClient,
               BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> headerFramesSupplier)
-            throws Exception
+        throws Exception
+    {
+        CFTHttp2TestExchange.setHeaderFrameSupplier(headerFramesSupplier);
+
+        HttpClient client = null;
+        for (int i=0; i< BAD_HEADERS.size(); i++) {
+            if (!sameClient || client == null)
+                client = HttpClient.newBuilder().sslContext(sslContext).build();
+
+            URI uriWithQuery = URI.create(uri +  "?BAD_HEADERS=" + i);
+            HttpRequest request = HttpRequest.newBuilder(uriWithQuery)
+                    .POST(BodyPublishers.ofString("Hello there!"))
+                    .build();
+            System.out.println("\nSending request:" + uriWithQuery);
+            final HttpClient cc = client;
+            try {
+                HttpResponse<String> response = cc.send(request, BodyHandlers.ofString());
+                fail("Expected exception, got :" + response + ", " + response.body());
+            } catch (IOException ioe) {
+                System.out.println("Got EXPECTED: " + ioe);
+                assertDetailMessage(ioe, i);
+            }
+        }
+    }
+
+    @Test(dataProvider = "variants")
+    void testAsync(String uri,
+                   boolean sameClient,
+                   BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> headerFramesSupplier)
     {
         CFTHttp2TestExchange.setHeaderFrameSupplier(headerFramesSupplier);
 
@@ -152,31 +176,45 @@
             if (!sameClient || client == null)
                 client = HttpClient.newBuilder().sslContext(sslContext).build();
 
-            HttpRequest request = HttpRequest.newBuilder(URI.create(uri))
+            URI uriWithQuery = URI.create(uri +  "?BAD_HEADERS=" + i);
+            HttpRequest request = HttpRequest.newBuilder(uriWithQuery)
                     .POST(BodyPublishers.ofString("Hello there!"))
                     .build();
+            System.out.println("\nSending request:" + uriWithQuery);
             final HttpClient cc = client;
-            if (i % 2 == 0) {
-                assertThrows(IOException.class, () -> cc.send(request, BodyHandlers.ofString()));
-            } else {
-                Throwable t = null;
-                try {
-                    cc.sendAsync(request, BodyHandlers.ofString()).join();
-                } catch (Throwable t0) {
-                    t = t0;
+
+            Throwable t = null;
+            try {
+                HttpResponse<String> response = cc.sendAsync(request, BodyHandlers.ofString()).get();
+                fail("Expected exception, got :" + response + ", " + response.body());
+            } catch (Throwable t0) {
+                System.out.println("Got EXPECTED: " + t0);
+                if (t0 instanceof ExecutionException) {
+                    t0 = t0.getCause();
                 }
-                if (t == null) {
-                    throw new AssertionError("An exception was expected");
-                }
-                if (t instanceof CompletionException) {
-                    Throwable c = t.getCause();
-                    if (!(c instanceof IOException)) {
-                        throw new AssertionError("Unexpected exception", c);
-                    }
-                } else if (!(t instanceof IOException)) {
-                    throw new AssertionError("Unexpected exception", t);
-                }
+                t = t0;
             }
+            assertDetailMessage(t, i);
+        }
+    }
+
+    // Assertions based on implementation specific detail messages. Keep in
+    // sync with implementation.
+    static void assertDetailMessage(Throwable throwable, int iterationIndex) {
+        assertTrue(throwable instanceof IOException,
+                   "Expected IOException, got, " + throwable);
+        assertTrue(throwable.getMessage().contains("protocol error"),
+                "Expected \"protocol error\" in: " + throwable.getMessage());
+
+        if (iterationIndex == 0) { // unknown
+            assertTrue(throwable.getMessage().contains("Unknown pseudo-header"),
+                    "Expected \"Unknown pseudo-header\" in: " + throwable.getMessage());
+        } else if (iterationIndex == 4) { // unexpected
+            assertTrue(throwable.getMessage().contains(" Unexpected pseudo-header"),
+                    "Expected \" Unexpected pseudo-header\" in: " + throwable.getMessage());
+        } else {
+            assertTrue(throwable.getMessage().contains("Bad header"),
+                    "Expected \"Bad header\" in: " + throwable.getMessage());
         }
     }
 
@@ -186,38 +224,12 @@
         if (sslContext == null)
             throw new AssertionError("Unexpected null sslContext");
 
-        http2TestServer = new Http2TestServer("localhost", false, 0) {
-            @Override
-            protected Http2TestServerConnection createConnection(Http2TestServer http2TestServer,
-                                                                 Socket socket,
-                                                                 Http2TestExchangeSupplier exchangeSupplier)
-                    throws IOException {
-                return new Http2TestServerConnection(http2TestServer, socket, exchangeSupplier) {
-                    @Override
-                    protected HttpHeadersImpl createNewResponseHeaders() {
-                        return new OrderedHttpHeaders();
-                    }
-                };
-            }
-        };
+        http2TestServer = new Http2TestServer("localhost", false, 0);
         http2TestServer.addHandler(new Http2EchoHandler(), "/http2/echo");
         int port = http2TestServer.getAddress().getPort();
         http2URI = "http://localhost:" + port + "/http2/echo";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0){
-            @Override
-            protected Http2TestServerConnection createConnection(Http2TestServer http2TestServer,
-                                                                 Socket socket,
-                                                                 Http2TestExchangeSupplier exchangeSupplier)
-                    throws IOException {
-                return new Http2TestServerConnection(http2TestServer, socket, exchangeSupplier) {
-                    @Override
-                    protected HttpHeadersImpl createNewResponseHeaders() {
-                        return new OrderedHttpHeaders();
-                    }
-                };
-            }
-        };
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo");
         port = https2TestServer.getAddress().getPort();
         https2URI = "https://localhost:" + port + "/https2/echo";
@@ -239,16 +251,14 @@
 
     static class Http2EchoHandler implements Http2Handler {
 
-        private final AtomicInteger requestNo = new AtomicInteger();
-
         @Override
         public void handle(Http2TestExchange t) throws IOException {
             try (InputStream is = t.getRequestBody();
                  OutputStream os = t.getResponseBody()) {
                 byte[] bytes = is.readAllBytes();
-                int i = requestNo.incrementAndGet();
-                List<Pair<String, String>> p = BAD_HEADERS.get(i % BAD_HEADERS.size());
-                p.forEach(h -> t.getResponseHeaders().addHeader(h.first, h.second));
+                // Note: strictly ordered response headers will be added within
+                // the custom sendResponseHeaders implementation, based upon the
+                // query parameter
                 t.sendResponseHeaders(200, bytes.length);
                 os.write(bytes);
             }
@@ -259,23 +269,34 @@
     // allow headers to be sent with a number of CONTINUATION frames.
     static class CFTHttp2TestExchange extends Http2TestExchangeImpl {
         static volatile BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> headerFrameSupplier;
+        volatile int badHeadersIndex = -1;
 
         static void setHeaderFrameSupplier(BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> hfs) {
             headerFrameSupplier = hfs;
         }
 
-        CFTHttp2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders,
-                             HttpHeadersImpl rspheaders, URI uri, InputStream is,
+        CFTHttp2TestExchange(int streamid, String method, HttpHeaders reqheaders,
+                             HttpHeadersBuilder rspheadersBuilder, URI uri, InputStream is,
                              SSLSession sslSession, BodyOutputStream os,
                              Http2TestServerConnection conn, boolean pushAllowed) {
-            super(streamid, method, reqheaders, rspheaders, uri, is, sslSession,
+            super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession,
                   os, conn, pushAllowed);
-
+            String query = uri.getQuery();
+            badHeadersIndex = Integer.parseInt(query.substring(query.indexOf("=") + 1));
+            assert badHeadersIndex >= 0 && badHeadersIndex < BAD_HEADERS.size() :
+                    "Unexpected badHeadersIndex value: " + badHeadersIndex;
         }
 
         @Override
         public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
-            List<ByteBuffer> encodeHeaders = conn.encodeHeaders(rspheaders);
+            assert rspheadersBuilder.build().map().size() == 0;
+            assert badHeadersIndex >= 0 && badHeadersIndex < BAD_HEADERS.size() :
+                    "Unexpected badHeadersIndex value: " + badHeadersIndex;
+
+            List<Entry<String,String>> headers = BAD_HEADERS.get(badHeadersIndex);
+            System.out.println("Server replying with bad headers: " + headers);
+            List<ByteBuffer> encodeHeaders = conn.encodeHeadersOrdered(headers);
+
             List<Http2Frame> headerFrames = headerFrameSupplier.apply(streamid, encodeHeaders);
             assert headerFrames.size() > 0;  // there must always be at least 1
 
@@ -291,36 +312,4 @@
             System.err.println("Sent response headers " + rCode);
         }
     }
-
-    /*
-     * Use carefully. This class might not be suitable outside this test's
-     * context. Pay attention working with multi Map view returned from map().
-     * The reason is that header names must be lower-cased prior to any
-     * operation that depends on whether or not the map contains a specific
-     * element.
-     */
-    private static class OrderedHttpHeaders extends HttpHeadersImpl {
-
-        private final Map<String, List<String>> map = new LinkedHashMap<>();
-
-        @Override
-        public void addHeader(String name, String value) {
-            super.addHeader(name.toLowerCase(Locale.ROOT), value);
-        }
-
-        @Override
-        public void setHeader(String name, String value) {
-            super.setHeader(name.toLowerCase(Locale.ROOT), value);
-        }
-
-        @Override
-        protected Map<String, List<String>> headersMap() {
-            return map;
-        }
-
-        @Override
-        protected HttpHeadersImpl newDeepCopy() {
-            return new OrderedHttpHeaders();
-        }
-    }
 }
--- a/test/jdk/java/net/httpclient/http2/BasicTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/BasicTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -222,7 +222,7 @@
         httpsServer.addHandler((t -> {
             SSLSession s = t.getSSLSession();
             String prot = s.getProtocol();
-            if (prot.equals("TLSv1.2")) {
+            if (prot.equals("TLSv1.2") || prot.equals("TLSv1.3")) {
                 t.sendResponseHeaders(200, -1);
             } else {
                 System.err.printf("Protocols =%s\n", prot);
--- a/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -38,6 +38,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
+import java.net.http.HttpHeaders;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
@@ -49,7 +50,7 @@
 import java.net.http.HttpRequest.BodyPublishers;
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.frame.ContinuationFrame;
 import jdk.internal.net.http.frame.HeaderFrame;
 import jdk.internal.net.http.frame.HeadersFrame;
@@ -168,7 +169,7 @@
         int port = http2TestServer.getAddress().getPort();
         http2URI = "http://localhost:" + port + "/http2/echo";
 
-        https2TestServer = new Http2TestServer("localhost", true, 0);
+        https2TestServer = new Http2TestServer("localhost", true, sslContext);
         https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo");
         port = https2TestServer.getAddress().getPort();
         https2URI = "https://localhost:" + port + "/https2/echo";
@@ -212,11 +213,11 @@
             headerFrameSupplier = hfs;
         }
 
-        CFTHttp2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders,
-                             HttpHeadersImpl rspheaders, URI uri, InputStream is,
+        CFTHttp2TestExchange(int streamid, String method, HttpHeaders reqheaders,
+                             HttpHeadersBuilder rspheadersBuilder, URI uri, InputStream is,
                              SSLSession sslSession, BodyOutputStream os,
                              Http2TestServerConnection conn, boolean pushAllowed) {
-            super(streamid, method, reqheaders, rspheaders, uri, is, sslSession,
+            super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession,
                   os, conn, pushAllowed);
 
         }
@@ -226,11 +227,12 @@
             this.responseLength = responseLength;
             if (responseLength > 0 || responseLength < 0) {
                 long clen = responseLength > 0 ? responseLength : 0;
-                rspheaders.setHeader("Content-length", Long.toString(clen));
+                rspheadersBuilder.setHeader("Content-length", Long.toString(clen));
             }
-            rspheaders.setHeader(":status", Integer.toString(rCode));
+            rspheadersBuilder.setHeader(":status", Integer.toString(rCode));
+            HttpHeaders headers = rspheadersBuilder.build();
 
-            List<ByteBuffer> encodeHeaders = conn.encodeHeaders(rspheaders);
+            List<ByteBuffer> encodeHeaders = conn.encodeHeaders(headers);
             List<Http2Frame> headerFrames = headerFrameSupplier.apply(streamid, encodeHeaders);
             assert headerFrames.size() > 0;  // there must always be at least 1
 
--- a/test/jdk/java/net/httpclient/http2/ErrorTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/ErrorTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -58,7 +58,7 @@
  */
 public class ErrorTest {
 
-    static final String[] CIPHER_SUITES = new String[]{ "TLS_KRB5_WITH_3DES_EDE_CBC_SHA" };
+    static final String[] CIPHER_SUITES = new String[]{ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" };
 
     static final String SIMPLE_STRING = "Hello world Goodbye world";
 
--- a/test/jdk/java/net/httpclient/http2/ImplicitPushCancel.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/ImplicitPushCancel.java	Thu Jun 21 09:53:50 2018 -0700
@@ -40,18 +40,18 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.net.http.HttpResponse.PushPromiseHandler;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.net.http.HttpResponse.PushPromiseHandler;
-import jdk.internal.net.http.common.HttpHeadersImpl;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
@@ -177,7 +177,7 @@
             for (Map.Entry<String,String> promise : promises.entrySet()) {
                 URI uri = requestURI.resolve(promise.getKey());
                 InputStream is = new ByteArrayInputStream(promise.getValue().getBytes(UTF_8));
-                HttpHeadersImpl headers = new HttpHeadersImpl();
+                HttpHeaders headers = HttpHeaders.of(Collections.emptyMap(), (x, y) -> true);
                 exchange.serverPush(uri, headers, is);
             }
             System.err.println("Server: All pushes sent");
--- a/test/jdk/java/net/httpclient/http2/ServerPush.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/ServerPush.java	Thu Jun 21 09:53:50 2018 -0700
@@ -53,7 +53,6 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.testng.Assert.*;
 
-
 public class ServerPush {
 
     static final int LOOPS = 13;
--- a/test/jdk/java/net/httpclient/http2/ServerPushWithDiffTypes.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/ServerPushWithDiffTypes.java	Thu Jun 21 09:53:50 2018 -0700
@@ -46,7 +46,8 @@
 import java.net.http.HttpResponse.BodySubscribers;
 import java.util.*;
 import java.util.concurrent.*;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import java.util.function.BiPredicate;
+
 import org.testng.annotations.Test;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.testng.Assert.assertEquals;
@@ -242,14 +243,16 @@
             }
         }
 
+        static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
         private void pushPromises(Http2TestExchange exchange) throws IOException {
             URI requestURI = exchange.getRequestURI();
             for (Map.Entry<String,String> promise : promises.entrySet()) {
                 URI uri = requestURI.resolve(promise.getKey());
                 InputStream is = new ByteArrayInputStream(promise.getValue().getBytes(UTF_8));
-                HttpHeadersImpl headers = new HttpHeadersImpl();
+                Map<String,List<String>> map = Map.of("X-Promise", List.of(promise.getKey()));
+                HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL);
                 // TODO: add some check on headers, maybe
-                headers.addHeader("X-Promise", promise.getKey());
                 exchange.serverPush(uri, headers, is);
             }
             System.err.println("Server: All pushes sent");
--- a/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HeaderTableTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HeaderTableTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,9 +26,12 @@
 import org.testng.annotations.Test;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
 
 public class HeaderTableTest extends SimpleHeaderTableTest {
 
@@ -42,41 +45,39 @@
         HeaderTable table = createHeaderTable(0);
         Map<Integer, HeaderField> staticHeaderFields = createStaticEntries();
 
-        Map<String, Integer> minimalIndexes = new HashMap<>();
+        Map<String, Set<Integer>> indexes = new HashMap<>();
 
         for (Map.Entry<Integer, HeaderField> e : staticHeaderFields.entrySet()) {
             Integer idx = e.getKey();
-            String hName = e.getValue().name;
-            Integer midx = minimalIndexes.get(hName);
-            if (midx == null) {
-                minimalIndexes.put(hName, idx);
-            } else {
-                minimalIndexes.put(hName, Math.min(idx, midx));
-            }
+            String name = e.getValue().name;
+            indexes.merge(name, Set.of(idx), (v1, v2) -> {
+                HashSet<Integer> s = new HashSet<>();
+                s.addAll(v1);
+                s.addAll(v2);
+                return s;
+            });
         }
 
-        staticHeaderFields.entrySet().forEach(
-                e -> {
-                    // lookup
-                    HeaderField actualHeaderField = table.get(e.getKey());
-                    HeaderField expectedHeaderField = e.getValue();
-                    assertEquals(actualHeaderField, expectedHeaderField);
+        staticHeaderFields.forEach((key, expectedHeaderField) -> {
+            // lookup
+            HeaderField actualHeaderField = table.get(key);
+            assertEquals(actualHeaderField.name, expectedHeaderField.name);
+            assertEquals(actualHeaderField.value, expectedHeaderField.value);
 
-                    // reverse lookup (name, value)
-                    String hName = expectedHeaderField.name;
-                    String hValue = expectedHeaderField.value;
-                    int expectedIndex = e.getKey();
-                    int actualIndex = table.indexOf(hName, hValue);
-
-                    assertEquals(actualIndex, expectedIndex);
+            // reverse lookup (name, value)
+            String hName = expectedHeaderField.name;
+            String hValue = expectedHeaderField.value;
+            int expectedIndex = key;
+            int actualIndex = table.indexOf(hName, hValue);
 
-                    // reverse lookup (name)
-                    int expectedMinimalIndex = minimalIndexes.get(hName);
-                    int actualMinimalIndex = table.indexOf(hName, "blah-blah");
+            assertEquals(actualIndex, expectedIndex);
 
-                    assertEquals(-actualMinimalIndex, expectedMinimalIndex);
-                }
-        );
+            // reverse lookup (name)
+            Set<Integer> expectedIndexes = indexes.get(hName);
+            int actualMinimalIndex = table.indexOf(hName, "blah-blah");
+
+            assertTrue(expectedIndexes.contains(-actualMinimalIndex));
+        });
     }
 
     @Test
--- a/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HuffmanTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HuffmanTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -22,24 +22,39 @@
  */
 package jdk.internal.net.http.hpack;
 
+import jdk.internal.net.http.hpack.Huffman.Reader;
+import jdk.internal.net.http.hpack.Huffman.Writer;
 import org.testng.annotations.Test;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.nio.ByteBuffer;
-import java.util.Stack;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static java.lang.Integer.parseInt;
-import static org.testng.Assert.*;
+import static jdk.internal.net.http.hpack.HPACK.bytesForBits;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
 
 public final class HuffmanTest {
 
+    /*
+     * Implementations of Huffman.Reader and Huffman.Writer under test.
+     * Change them here.
+     */
+    private static final Supplier<Reader> READER = QuickHuffman.Reader::new;
+    private static final Supplier<Writer> WRITER = QuickHuffman.Writer::new;
+
     //
     // https://tools.ietf.org/html/rfc7541#appendix-B
     //
-    private static final String SPEC =
+    private static final String SPECIFICATION =
             // @formatter:off
      "                          code as bits                 as hex   len\n" +
      "        sym              aligned to MSB                aligned   in\n" +
@@ -303,137 +318,213 @@
      "   EOS (256)  |11111111|11111111|11111111|111111      3fffffff  [30]";
     // @formatter:on
 
-    @Test
-    public void read_table() throws IOException {
-        Pattern line = Pattern.compile(
-                "\\(\\s*(?<ascii>\\d+)\\s*\\)\\s*(?<binary>(\\|(0|1)+)+)\\s*" +
-                        "(?<hex>[0-9a-zA-Z]+)\\s*\\[\\s*(?<len>\\d+)\\s*\\]");
-        Matcher m = line.matcher(SPEC);
-        int i = 0;
-        while (m.find()) {
-            String ascii = m.group("ascii");
-            String binary = m.group("binary").replaceAll("\\|", "");
-            String hex = m.group("hex");
-            String len = m.group("len");
+    private static final Code EOS = new Code((char) 256, 0x3fffffff, 30);
+    private final SortedMap<Character, Code> CODES = readSpecification();
+
+    private static final class Code {
+
+        final char sym;
+        final int hex;
+        final int len;
+
+        public Code(char sym, int hex, int len) {
+            this.sym = sym;
+            this.hex = hex;
+            this.len = len;
+        }
 
-            // Several sanity checks for the data read from the table, just to
-            // make sure what we read makes sense
-            assertEquals(parseInt(len), binary.length());
-            assertEquals(parseInt(binary, 2), parseInt(hex, 16));
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Code code = (Code) o;
+            return sym == code.sym &&
+                    hex == code.hex &&
+                    len == code.len;
+        }
 
-            int expected = parseInt(ascii);
+        @Override
+        public int hashCode() {
+            return Objects.hash(sym, hex, len);
+        }
+    }
 
-            // TODO: find actual eos, do not hardcode it!
-            byte[] bytes = intToBytes(0x3fffffff, 30,
-                    parseInt(hex, 16), parseInt(len));
-
-            StringBuilder actual = new StringBuilder();
-            NaiveHuffman.Reader t = new NaiveHuffman.Reader();
-            t.read(ByteBuffer.wrap(bytes), actual, false, true);
+    private SortedMap<Character, Code> readSpecification() {
+        Pattern line = Pattern.compile(
+                "\\(\\s*(?<sym>\\d+)\\s*\\)\\s*(?<bits>(\\|([01])+)+)\\s*" +
+                        "(?<hex>[0-9a-zA-Z]+)\\s*\\[\\s*(?<len>\\d+)\\s*\\]");
+        Matcher m = line.matcher(SPECIFICATION);
+        SortedMap<Character, Code> map = new TreeMap<>();
+        while (m.find()) {
+            String symString = m.group("sym");
+            String binaryString = m.group("bits").replaceAll("\\|", "");
+            String hexString = m.group("hex");
+            String lenString = m.group("len");
+            // several sanity checks for the data read from the table, just to
+            // make sure what we read makes sense:
+            int sym = Integer.parseInt(symString);
+            if (sym < 0 || sym > 65535) {
+                throw new IllegalArgumentException();
+            }
+            int binary = Integer.parseInt(binaryString, 2);
+            int len = Integer.parseInt(lenString);
+            if (binaryString.length() != len) {
+                throw new IllegalArgumentException();
+            }
+            int hex = Integer.parseInt(hexString, 16);
+            if (hex != binary) {
+                throw new IllegalArgumentException();
+            }
+            if (map.put((char) sym, new Code((char) sym, hex, len)) != null) {
+                // a mapping for sym already exists
+                throw new IllegalStateException();
+            }
+        }
+        if (map.size() != 257) {
+            throw new IllegalArgumentException();
+        }
+        return map;
+    }
 
-            // What has been read MUST represent a single symbol
-            assertEquals(actual.length(), 1, "ascii: " + ascii);
+    /*
+     * Encodes manually each symbol (character) from the specification and
+     * checks that Huffman.Reader decodes the result back to the initial
+     * character. This verifies that Huffman.Reader is implemented according to
+     * RFC 7541.
+     */
+    @Test
+    public void decodingConsistentWithSpecification() throws IOException {
+        Reader reader = READER.get();
+        for (Code code : CODES.values()) {
+            if (code.equals(EOS)) {
+                continue; // skip EOS
+            }
+            ByteBuffer input = encode(code);
+            StringBuilder output = new StringBuilder(1);
+            reader.read(input, output, true);
+            reader.reset();
 
-            // It's a lot more visual to compare char as codes rather than
-            // characters (as some of them might not be visible)
-            assertEquals(actual.charAt(0), expected);
-            i++;
+            // compare chars using their decimal representation (as some chars
+            // might not be printable/visible)
+            int expected = code.sym;
+            int actual = (int) output.charAt(0);
+            assertEquals(output.length(), 1); // exactly 1 character
+            assertEquals(actual, expected);
+        }
+    }
 
-            // maybe not report EOS but rather throw an expected exception?
-        }
-        assertEquals(i, 257); // 256 + EOS
+    @Test
+    public void decodeEOS1() {
+        Reader reader = READER.get();
+        TestHelper.assertVoidThrows(
+                IOException.class,
+                () -> reader.read(encode(EOS), new StringBuilder(), true));
+    }
+
+    @Test
+    public void decodeEOS2() {
+        Reader reader = READER.get();
+        TestHelper.assertVoidThrows(
+                IOException.class,
+                () -> reader.read(encode(EOS), new StringBuilder(), false));
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.4.1
     //
     @Test
-    public void read_1() {
-        read("f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com");
+    public void read01() {
+        readExhaustively("f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com");
     }
 
     @Test
-    public void write_1() {
-        write("www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff");
+    public void write01() {
+        writeExhaustively("www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.4.2
     //
     @Test
-    public void read_2() {
-        read("a8eb 1064 9cbf", "no-cache");
+    public void read02() {
+        readExhaustively("a8eb 1064 9cbf", "no-cache");
     }
 
     @Test
-    public void write_2() {
-        write("no-cache", "a8eb 1064 9cbf");
+    public void write02() {
+        writeExhaustively("no-cache", "a8eb 1064 9cbf");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.4.3
     //
     @Test
-    public void read_3() {
-        read("25a8 49e9 5ba9 7d7f", "custom-key");
+    public void read03() {
+        readExhaustively("25a8 49e9 5ba9 7d7f", "custom-key");
     }
 
     @Test
-    public void write_3() {
-        write("custom-key", "25a8 49e9 5ba9 7d7f");
+    public void write03() {
+        writeExhaustively("custom-key", "25a8 49e9 5ba9 7d7f");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.4.3
     //
     @Test
-    public void read_4() {
-        read("25a8 49e9 5bb8 e8b4 bf", "custom-value");
+    public void read04() {
+        readExhaustively("25a8 49e9 5bb8 e8b4 bf", "custom-value");
     }
 
     @Test
-    public void write_4() {
-        write("custom-value", "25a8 49e9 5bb8 e8b4 bf");
+    public void write04() {
+        writeExhaustively("custom-value", "25a8 49e9 5bb8 e8b4 bf");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
     //
     @Test
-    public void read_5() {
-        read("6402", "302");
+    public void read05() {
+        readExhaustively("6402", "302");
     }
 
     @Test
-    public void write_5() {
-        write("302", "6402");
+    public void write05() {
+        writeExhaustively("302", "6402");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
     //
     @Test
-    public void read_6() {
-        read("aec3 771a 4b", "private");
+    public void read06() {
+        readExhaustively("aec3 771a 4b", "private");
     }
 
     @Test
-    public void write_6() {
-        write("private", "aec3 771a 4b");
+    public void write06() {
+        writeExhaustively("private", "aec3 771a 4b");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
     //
     @Test
-    public void read_7() {
-        read("d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff",
+    public void read07() {
+        readExhaustively(
+                "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff",
                 "Mon, 21 Oct 2013 20:13:21 GMT");
     }
 
     @Test
-    public void write_7() {
-        write("Mon, 21 Oct 2013 20:13:21 GMT",
+    public void write07() {
+        writeExhaustively(
+                "Mon, 21 Oct 2013 20:13:21 GMT",
                 "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff");
     }
 
@@ -441,42 +532,44 @@
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
     //
     @Test
-    public void read_8() {
-        read("9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3",
-                "https://www.example.com");
+    public void read08() {
+        readExhaustively("9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3",
+                         "https://www.example.com");
     }
 
     @Test
-    public void write_8() {
-        write("https://www.example.com",
-                "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3");
+    public void write08() {
+        writeExhaustively("https://www.example.com",
+                          "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.2
     //
     @Test
-    public void read_9() {
-        read("640e ff", "307");
+    public void read09() {
+        readExhaustively("640e ff", "307");
     }
 
     @Test
-    public void write_9() {
-        write("307", "640e ff");
+    public void write09() {
+        writeExhaustively("307", "640e ff");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
     //
     @Test
-    public void read_10() {
-        read("d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff",
+    public void read10() {
+        readExhaustively(
+                "d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff",
                 "Mon, 21 Oct 2013 20:13:22 GMT");
     }
 
     @Test
-    public void write_10() {
-        write("Mon, 21 Oct 2013 20:13:22 GMT",
+    public void write10() {
+        writeExhaustively(
+                "Mon, 21 Oct 2013 20:13:22 GMT",
                 "d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff");
     }
 
@@ -484,78 +577,179 @@
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
     //
     @Test
-    public void read_11() {
-        read("9bd9 ab", "gzip");
+    public void read11() {
+        readExhaustively("9bd9 ab", "gzip");
     }
 
     @Test
-    public void write_11() {
-        write("gzip", "9bd9 ab");
+    public void write11() {
+        writeExhaustively("gzip", "9bd9 ab");
     }
 
     //
     // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
     //
     @Test
-    public void read_12() {
-        read("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 " +
-             "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 " +
-             "3160 65c0 03ed 4ee5 b106 3d50 07",
+    public void read12() {
+        // The number of possibilities here grow as 2^(n-1). There are 45 bytes
+        // in this input. So it would require 2^44 decoding operations. If we
+        // spend 1 microsecond per operation, it would take approximately
+        //
+        //     ((10^15 * 10^(-6)) / 86400) / 365, or about 32 years
+        //
+        // Conclusion: too big to be read exhaustively
+        read("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 "
+                     + "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 "
+                     + "3160 65c0 03ed 4ee5 b106 3d50 07",
              "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1");
     }
 
     @Test
-    public void read_13() {
-        read("6274 a6b4 0989 4de4 b27f 80",
-             "/https2/fixed?0");
+    public void write12() {
+        write("foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
+              "94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 "
+                      + "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 "
+                      + "3160 65c0 03ed 4ee5 b106 3d50 07");
     }
 
     @Test
-    public void test_trie_has_no_empty_nodes() {
-        NaiveHuffman.Node root = NaiveHuffman.INSTANCE.getRoot();
-        Stack<NaiveHuffman.Node> backlog = new Stack<>();
-        backlog.push(root);
-        while (!backlog.isEmpty()) {
-            NaiveHuffman.Node n = backlog.pop();
-            // The only type of nodes we couldn't possibly catch during
-            // construction is an empty node: no children and no char
-            if (n.left != null) {
-                backlog.push(n.left);
-            }
-            if (n.right != null) {
-                backlog.push(n.right);
-            }
-            assertFalse(!n.charIsSet && n.left == null && n.right == null,
-                    "Empty node in the trie");
-        }
+    public void read13() {
+        readExhaustively("6274 a6b4 0989 4de4 b27f 80",
+                         "/https2/fixed?0");
     }
 
     @Test
-    public void test_trie_has_257_nodes() {
-        int count = 0;
-        NaiveHuffman.Node root = NaiveHuffman.INSTANCE.getRoot();
-        Stack<NaiveHuffman.Node> backlog = new Stack<>();
-        backlog.push(root);
-        while (!backlog.isEmpty()) {
-            NaiveHuffman.Node n = backlog.pop();
-            if (n.left != null) {
-                backlog.push(n.left);
+    public void roundTrip() throws IOException {
+
+        class Helper {
+            // Maps code's length to a character that is encoded with a code of
+            // that length. Which of the characters with the same code's length
+            // is picked is undefined.
+            private Map<Integer, Character> chars = new HashMap<>();
+            {
+                for (Map.Entry<Character, Code> e : CODES.entrySet()) {
+                    chars.putIfAbsent(e.getValue().len, e.getKey());
+                }
             }
-            if (n.right != null) {
-                backlog.push(n.right);
+
+            private CharSequence charsOfLength(int... lengths) {
+                StringBuilder b = new StringBuilder(lengths.length);
+                for (int length : lengths) {
+                    Character c = chars.get(length);
+                    if (c == null) {
+                        throw new IllegalArgumentException(
+                                "No code has length " + length);
+                    }
+                    b.append(c);
+                }
+                return b.toString();
             }
-            if (n.isLeaf()) {
-                count++;
+
+            private void identity(CharSequence str) throws IOException {
+                Writer w = WRITER.get();
+                StringBuilder b = new StringBuilder(str.length());
+                int size = w.lengthOf(str);
+                ByteBuffer buffer = ByteBuffer.allocate(size);
+                w.from(str, 0, str.length()).write(buffer);
+                Reader r = READER.get();
+                r.read(buffer.flip(), b, true);
+                assertEquals(b.toString(), str);
+            }
+
+            private void roundTrip(int... lengths) throws IOException {
+                identity(charsOfLength(lengths));
             }
         }
-        assertEquals(count, 257);
+
+        // The idea is to build a number of input strings that are encoded
+        // without the need for padding. The sizes of the encoded forms,
+        // therefore, must be 8, 16, 24, 32, 48, 56, 64 and 72 bits. Then check
+        // that they are encoded and then decoded into the same strings.
+
+        Helper h = new Helper();
+
+        // --  8 bit code --
+
+        h.roundTrip( 8);
+
+        // -- 16 bit code --
+
+        h.roundTrip( 5, 11);
+        h.roundTrip( 5,  5,  6);
+
+        // -- 24 bit code --
+
+        h.roundTrip(24);
+        h.roundTrip( 5, 19);
+        h.roundTrip( 5,  5, 14);
+        h.roundTrip( 5,  5,  6,  8);
+
+        // -- 32 bit code --
+
+        h.roundTrip( 5, 27);
+        h.roundTrip( 5,  5, 22);
+        h.roundTrip( 5,  5,  7, 15);
+        h.roundTrip( 5,  5,  5,  5, 12);
+        h.roundTrip( 5,  5,  5,  5,  5,  7);
+
+        // -- 48 bit code --
+
+        h.roundTrip(20, 28);
+        h.roundTrip( 5, 13, 30);
+        h.roundTrip( 5,  5,  8, 30);
+        h.roundTrip( 5,  5,  5,  5, 28);
+        h.roundTrip( 5,  5,  5,  5,  5, 23);
+        h.roundTrip( 5,  5,  5,  5,  5,  8, 15);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5, 13);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  8);
+
+        // -- 56 bit code --
+
+        h.roundTrip(26, 30);
+        h.roundTrip( 5, 21, 30);
+        h.roundTrip( 5,  5, 19, 27);
+        h.roundTrip( 5,  5,  5, 11, 30);
+        h.roundTrip( 5,  5,  5,  5,  6, 30);
+        h.roundTrip( 5,  5,  5,  5,  5,  5, 26);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5, 21);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  6, 15);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5, 11);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6);
+
+        // -- 64 bit code --
+
+        h.roundTrip( 6, 28, 30);
+        h.roundTrip( 5,  5, 24, 30);
+        h.roundTrip( 5,  5,  5, 19, 30);
+        h.roundTrip( 5,  5,  5,  5, 14, 30);
+        h.roundTrip( 5,  5,  5,  5,  5, 11, 28);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  6, 28);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5, 24);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5, 19);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 14);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  8);
+
+        // -- 72 bit code --
+
+        h.roundTrip(12, 30, 30);
+        h.roundTrip( 5,  7, 30, 30);
+        h.roundTrip( 5,  5,  5, 27, 30);
+        h.roundTrip( 5,  5,  5,  5, 22, 30);
+        h.roundTrip( 5,  5,  5,  5,  5, 19, 28);
+        h.roundTrip( 5,  5,  5,  5,  5,  5, 12, 30);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  7, 30);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5, 27);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 22);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  7, 15);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 12);
+        h.roundTrip( 5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  7);
     }
 
     @Test
-    public void cant_encode_outside_byte() {
+    public void cannotEncodeOutsideByte() {
         TestHelper.Block<Object> coding =
-                () -> new NaiveHuffman.Writer()
-                        .from(((char) 256) + "", 0, 1)
+                () -> WRITER.get()
+                        .from(String.valueOf((char) 256), 0, 1)
                         .write(ByteBuffer.allocate(1));
         RuntimeException e =
                 TestHelper.assertVoidThrows(RuntimeException.class, coding);
@@ -565,25 +759,58 @@
     private static void read(String hexdump, String decoded) {
         ByteBuffer source = SpecHelper.toBytes(hexdump);
         Appendable actual = new StringBuilder();
+        Reader reader = READER.get();
         try {
-            new QuickHuffman.Reader().read(source, actual, true);
+            reader.read(source, actual, true);
         } catch (IOException e) {
             throw new UncheckedIOException(e);
         }
         assertEquals(actual.toString(), decoded);
     }
 
+    private static void readExhaustively(String hexdump, String decoded) {
+        ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
+        Reader reader = READER.get();
+        ByteBuffer source = SpecHelper.toBytes(hexdump);
+        StringBuilder actual = new StringBuilder();
+        BuffersTestingKit.forEachSplit(source, buffers -> {
+            try {
+                for (ByteBuffer b : buffers) {
+                    reader.read(b, actual, false);
+                }
+                reader.read(EMPTY_BUFFER, actual, true);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+            assertEquals(actual.toString(), decoded);
+            reader.reset();
+            actual.setLength(0);
+        });
+    }
+
     private static void write(String decoded, String hexdump) {
-        Huffman.Writer writer = new QuickHuffman.Writer();
+        Writer writer = WRITER.get();
         int n = writer.lengthOf(decoded);
-        ByteBuffer destination = ByteBuffer.allocate(n); // Extra margin (1) to test having more bytes in the destination than needed is ok
+        ByteBuffer destination = ByteBuffer.allocateDirect(n);
+        writer.from(decoded, 0, decoded.length());
+        boolean written = writer.write(destination);
+        assertTrue(written);
+        String actual = SpecHelper.toHexdump(destination.flip());
+        assertEquals(actual, hexdump);
+        writer.reset();
+    }
+
+    private static void writeExhaustively(String decoded, String hexdump) {
+        Writer writer = WRITER.get();
+        int n = writer.lengthOf(decoded);
+        ByteBuffer destination = ByteBuffer.allocate(n);
         BuffersTestingKit.forEachSplit(destination, byteBuffers -> {
             writer.from(decoded, 0, decoded.length());
             boolean written = false;
             for (ByteBuffer b : byteBuffers) {
                 int pos = b.position();
                 written = writer.write(b);
-                b.position(pos);
+                b.position(pos); // "flip" to the saved position, for reading
             }
             assertTrue(written);
             ByteBuffer concated = BuffersTestingKit.concat(byteBuffers);
@@ -593,45 +820,20 @@
         });
     }
 
-    //
-    // It's not very pretty, yes I know that
-    //
-    //      hex:
-    //
-    //      |31|30|...|N-1|...|01|00|
-    //                  \        /
-    //                  codeLength
-    //
-    //      hex <<= 32 - codeLength; (align to MSB):
-    //
-    //      |31|30|...|32-N|...|01|00|
-    //        \        /
-    //        codeLength
-    //
-    //      EOS:
-    //
-    //      |31|30|...|M-1|...|01|00|
-    //                   \        /
-    //                   eosLength
-    //
-    //      eos <<= 32 - eosLength; (align to MSB):
-    //
-    //      pad with MSBs of EOS:
-    //
-    //      |31|30|...|32-N|32-N-1|...|01|00|
-    //                     |    32|...|
-    //
-    //      Finally, split into byte[]
-    //
-    private byte[] intToBytes(int eos, int eosLength, int hex, int codeLength) {
-        hex <<= 32 - codeLength;
-        eos >>= codeLength - (32 - eosLength);
-        hex |= eos;
-        int n = (int) Math.ceil(codeLength / 8.0);
+    /*
+     * Encodes a single character. This representation is padded, thus ready to
+     * be decoded.
+     */
+    private static ByteBuffer encode(Code code) {
+        int EOS_MSB = EOS.hex << (32 - EOS.len);
+        int padding = EOS_MSB >>> code.len;
+        int hexMSB = code.hex << (32 - code.len);
+        int c = hexMSB | padding;
+        int n = bytesForBits(code.len);
         byte[] result = new byte[n];
         for (int i = 0; i < n; i++) {
-            result[i] = (byte) (hex >> (32 - 8 * (i + 1)));
+            result[i] = (byte) (c >> (32 - 8 * (i + 1)));
         }
-        return result;
+        return ByteBuffer.wrap(result);
     }
 }
--- a/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/SimpleHeaderTableTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/SimpleHeaderTableTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -47,7 +47,7 @@
     // https://tools.ietf.org/html/rfc7541#appendix-A
     //
     // @formatter:off
-    private static final String SPEC =
+    private static final String SPECIFICATION =
        "          | 1     | :authority                  |               |\n" +
        "          | 2     | :method                     | GET           |\n" +
        "          | 3     | :method                     | POST          |\n" +
@@ -125,7 +125,8 @@
         Map<Integer, HeaderField> staticHeaderFields = createStaticEntries();
         staticHeaderFields.forEach((index, expectedHeaderField) -> {
             SimpleHeaderTable.HeaderField actualHeaderField = table.get(index);
-            assertEquals(actualHeaderField, expectedHeaderField);
+            assertEquals(actualHeaderField.name, expectedHeaderField.name);
+            assertEquals(actualHeaderField.value, expectedHeaderField.value);
         });
     }
 
@@ -318,7 +319,7 @@
     static Map<Integer, HeaderField> createStaticEntries() {
         Pattern line = Pattern.compile(
                 "\\|\\s*(?<index>\\d+?)\\s*\\|\\s*(?<name>.+?)\\s*\\|\\s*(?<value>.*?)\\s*\\|");
-        Matcher m = line.matcher(SPEC);
+        Matcher m = line.matcher(SPECIFICATION);
         Map<Integer, HeaderField> result = new HashMap<>();
         while (m.find()) {
             int index = Integer.parseInt(m.group("index"));
--- a/test/jdk/java/net/httpclient/http2/server/Http2EchoHandler.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2EchoHandler.java	Thu Jun 21 09:53:50 2018 -0700
@@ -22,11 +22,11 @@
  */
 
 import java.io.*;
+import java.net.http.HttpHeaders;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 
 public class Http2EchoHandler implements Http2Handler {
     static final Path CWD = Paths.get(".");
@@ -40,10 +40,10 @@
             System.err.printf("EchoHandler received request to %s from %s\n",
                               t.getRequestURI(), t.getRemoteAddress());
             InputStream is = t.getRequestBody();
-            HttpHeadersImpl map = t.getRequestHeaders();
-            HttpHeadersImpl map1 = t.getResponseHeaders();
-            map1.addHeader("X-Hello", "world");
-            map1.addHeader("X-Bye", "universe");
+            HttpHeaders map = t.getRequestHeaders();
+            HttpHeadersBuilder headersBuilder = t.getResponseHeaders();
+            headersBuilder.addHeader("X-Hello", "world");
+            headersBuilder.addHeader("X-Bye", "universe");
             String fixedrequest = map.firstValue("XFixed").orElse(null);
             File outfile = Files.createTempFile(CWD, "foo", "bar").toFile();
             //System.err.println ("QQQ = " + outfile.toString());
--- a/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,7 +25,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.function.Supplier;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 
 public class Http2RedirectHandler implements Http2Handler {
 
@@ -44,8 +44,8 @@
             System.err.printf("RedirectHandler request to %s from %s\n",
                 t.getRequestURI().toString(), t.getRemoteAddress().toString());
             System.err.println("Redirecting to: " + location);
-            HttpHeadersImpl map1 = t.getResponseHeaders();
-            map1.addHeader("Location", location);
+            HttpHeadersBuilder headersBuilder = t.getResponseHeaders();
+            headersBuilder.addHeader("Location", location);
             t.sendResponseHeaders(301, 1024);
             byte[] bb = new byte[1024];
             OutputStream os = t.getResponseBody();
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java	Thu Jun 21 09:53:50 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,16 +26,16 @@
 import java.io.OutputStream;
 import java.net.URI;
 import java.net.InetSocketAddress;
+import java.net.http.HttpHeaders;
 import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
 import javax.net.ssl.SSLSession;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 
 public interface Http2TestExchange {
 
-    HttpHeadersImpl getRequestHeaders();
+    HttpHeaders getRequestHeaders();
 
-    HttpHeadersImpl getResponseHeaders();
+    HttpHeadersBuilder getResponseHeaders();
 
     URI getRequestURI();
 
@@ -61,7 +61,7 @@
 
     boolean serverPushAllowed();
 
-    void serverPush(URI uri, HttpHeadersImpl headers, InputStream content);
+    void serverPush(URI uri, HttpHeaders headers, InputStream content);
 
     /**
      * Send a PING on this exchanges connection, and completes the returned CF
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java	Thu Jun 21 09:53:50 2018 -0700
@@ -26,17 +26,19 @@
 import java.io.IOException;
 import java.net.URI;
 import java.net.InetSocketAddress;
+import java.net.http.HttpHeaders;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
-import java.util.function.Consumer;
 import javax.net.ssl.SSLSession;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.frame.HeaderFrame;
 import jdk.internal.net.http.frame.HeadersFrame;
 
 public class Http2TestExchangeImpl implements Http2TestExchange {
 
-    final HttpHeadersImpl reqheaders;
-    final HttpHeadersImpl rspheaders;
+    final HttpHeaders reqheaders;
+    final HttpHeadersBuilder rspheadersBuilder;
     final URI uri;
     final String method;
     final InputStream is;
@@ -52,8 +54,8 @@
 
     Http2TestExchangeImpl(int streamid,
                           String method,
-                          HttpHeadersImpl reqheaders,
-                          HttpHeadersImpl rspheaders,
+                          HttpHeaders reqheaders,
+                          HttpHeadersBuilder rspheadersBuilder,
                           URI uri,
                           InputStream is,
                           SSLSession sslSession,
@@ -61,7 +63,7 @@
                           Http2TestServerConnection conn,
                           boolean pushAllowed) {
         this.reqheaders = reqheaders;
-        this.rspheaders = rspheaders;
+        this.rspheadersBuilder = rspheadersBuilder;
         this.uri = uri;
         this.method = method;
         this.is = is;
@@ -74,7 +76,7 @@
     }
 
     @Override
-    public HttpHeadersImpl getRequestHeaders() {
+    public HttpHeaders getRequestHeaders() {
         return reqheaders;
     }
 
@@ -84,8 +86,8 @@
     }
 
     @Override
-    public HttpHeadersImpl getResponseHeaders() {
-        return rspheaders;
+    public HttpHeadersBuilder getResponseHeaders() {
+        return rspheadersBuilder;
     }
 
     @Override
@@ -129,13 +131,14 @@
         this.responseLength = responseLength;
         if (responseLength > 0 || responseLength < 0) {
                 long clen = responseLength > 0 ? responseLength : 0;
-            rspheaders.setHeader("Content-length", Long.toString(clen));
+            rspheadersBuilder.setHeader("Content-length", Long.toString(clen));
         }
 
-        rspheaders.setHeader(":status", Integer.toString(rCode));
+        rspheadersBuilder.setHeader(":status", Integer.toString(rCode));
+        HttpHeaders headers = rspheadersBuilder.build();
 
         Http2TestServerConnection.ResponseHeaders response
-                = new Http2TestServerConnection.ResponseHeaders(rspheaders);
+                = new Http2TestServerConnection.ResponseHeaders(headers);
         response.streamid(streamid);
         response.setFlag(HeaderFrame.END_HEADERS);
 
@@ -175,13 +178,19 @@
     }
 
     @Override
-    public void serverPush(URI uri, HttpHeadersImpl headers, InputStream content) {
-        OutgoingPushPromise pp = new OutgoingPushPromise(
-                streamid, uri, headers, content);
-        headers.setHeader(":method", "GET");
-        headers.setHeader(":scheme", uri.getScheme());
-        headers.setHeader(":authority", uri.getAuthority());
-        headers.setHeader(":path", uri.getPath());
+    public void serverPush(URI uri, HttpHeaders headers, InputStream content) {
+        HttpHeadersBuilder headersBuilder = new HttpHeadersBuilder();
+        headersBuilder.setHeader(":method", "GET");
+        headersBuilder.setHeader(":scheme", uri.getScheme());
+        headersBuilder.setHeader(":authority", uri.getAuthority());
+        headersBuilder.setHeader(":path", uri.getPath());
+        for (Map.Entry<String,List<String>> entry : headers.map().entrySet()) {
+            for (String value : entry.getValue())
+                headersBuilder.addHeader(entry.getKey(), value);
+        }
+        HttpHeaders combinedHeaders = headersBuilder.build();
+        OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, combinedHeaders, content);
+
         try {
             conn.outputQ.put(pp);
             // writeLoop will spin up thread to read the InputStream
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeSupplier.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeSupplier.java	Thu Jun 21 09:53:50 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,8 @@
 import javax.net.ssl.SSLSession;
 import java.io.InputStream;
 import java.net.URI;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import java.net.http.HttpHeaders;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 
 /**
  * A supplier of Http2TestExchanges. If the default Http2TestExchange impl is
@@ -39,8 +40,8 @@
 
     Http2TestExchange get(int streamid,
                           String method,
-                          HttpHeadersImpl reqheaders,
-                          HttpHeadersImpl rspheaders,
+                          HttpHeaders reqheaders,
+                          HttpHeadersBuilder rspheadersBuilder,
                           URI uri,
                           InputStream is,
                           SSLSession sslSession,
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java	Thu Jun 21 09:53:50 2018 -0700
@@ -53,6 +53,7 @@
     final SSLContext sslContext;
     final String serverName;
     final HashMap<InetSocketAddress,Http2TestServerConnection> connections;
+    final Properties properties;
 
     private static ThreadFactory defaultThreadFac =
         (Runnable r) -> {
@@ -67,11 +68,11 @@
     }
 
     public Http2TestServer(String serverName, boolean secure, int port) throws Exception {
-        this(serverName, secure, port, getDefaultExecutor(), 50, null);
+        this(serverName, secure, port, getDefaultExecutor(), 50, null, null);
     }
 
     public Http2TestServer(boolean secure, int port) throws Exception {
-        this(null, secure, port, getDefaultExecutor(), 50, null);
+        this(null, secure, port, getDefaultExecutor(), 50, null, null);
     }
 
     public InetSocketAddress getAddress() {
@@ -85,19 +86,19 @@
 
     public Http2TestServer(boolean secure,
                            SSLContext context) throws Exception {
-        this(null, secure, 0, null, 50, context);
+        this(null, secure, 0, null, 50, null, context);
     }
 
     public Http2TestServer(String serverName, boolean secure,
                            SSLContext context) throws Exception {
-        this(serverName, secure, 0, null, 50, context);
+        this(serverName, secure, 0, null, 50, null, context);
     }
 
     public Http2TestServer(boolean secure,
                            int port,
                            ExecutorService exec,
                            SSLContext context) throws Exception {
-        this(null, secure, port, exec, 50, context);
+        this(null, secure, port, exec, 50, null, context);
     }
 
     public Http2TestServer(String serverName,
@@ -107,7 +108,7 @@
                            SSLContext context)
         throws Exception
     {
-        this(serverName, secure, port, exec, 50, context);
+        this(serverName, secure, port, exec, 50, null, context);
     }
 
     /**
@@ -120,6 +121,7 @@
      * @param port listen port
      * @param exec executor service (cached thread pool is used if null)
      * @param backlog the server socket backlog
+     * @param properties additional configuration properties
      * @param context the SSLContext used when secure is true
      */
     public Http2TestServer(String serverName,
@@ -127,19 +129,25 @@
                            int port,
                            ExecutorService exec,
                            int backlog,
+                           Properties properties,
                            SSLContext context)
         throws Exception
     {
         this.serverName = serverName;
         if (secure) {
+           if (context != null)
+               this.sslContext = context;
+           else
+               this.sslContext = SSLContext.getDefault();
             server = initSecure(port, backlog);
         } else {
+            this.sslContext = context;
             server = initPlaintext(port, backlog);
         }
         this.secure = secure;
         this.exec = exec == null ? getDefaultExecutor() : exec;
         this.handlers = Collections.synchronizedMap(new HashMap<>());
-        this.sslContext = context;
+        this.properties = properties;
         this.connections = new HashMap<>();
     }
 
@@ -206,15 +214,12 @@
 
     final ServerSocket initSecure(int port, int backlog) throws Exception {
         ServerSocketFactory fac;
-        if (sslContext != null) {
-            fac = sslContext.getServerSocketFactory();
-        } else {
-            fac = SSLServerSocketFactory.getDefault();
-        }
+        SSLParameters sslp = null;
+        fac = sslContext.getServerSocketFactory();
+        sslp = sslContext.getSupportedSSLParameters();
         SSLServerSocket se = (SSLServerSocket) fac.createServerSocket();
         se.setReuseAddress(false);
         se.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), backlog);
-        SSLParameters sslp = se.getSSLParameters();
         sslp.setApplicationProtocols(new String[]{"h2"});
         sslp.setEndpointIdentificationAlgorithm("HTTPS");
         se.setSSLParameters(sslp);
@@ -264,7 +269,6 @@
                             socket.close();
                         }
                         System.err.println("TestServer: start exception: " + e);
-                        //throw e;
                     }
                 }
             } catch (SecurityException se) {
@@ -285,7 +289,7 @@
                                                          Socket socket,
                                                          Http2TestExchangeSupplier exchangeSupplier)
             throws IOException {
-        return new Http2TestServerConnection(http2TestServer, socket, exchangeSupplier);
+        return new Http2TestServerConnection(http2TestServer, socket, exchangeSupplier, properties);
     }
 
     @Override
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java	Thu Jun 21 09:53:50 2018 -0700
@@ -33,14 +33,14 @@
 import java.net.InetAddress;
 import javax.net.ssl.*;
 import java.net.URISyntaxException;
+import java.net.http.HttpHeaders;
 import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.function.Consumer;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.frame.*;
 import jdk.internal.net.http.hpack.Decoder;
 import jdk.internal.net.http.hpack.DecodingCallback;
@@ -71,6 +71,7 @@
     final SettingsFrame serverSettings;
     final ExecutorService exec;
     final boolean secure;
+    final Properties properties;
     volatile boolean stopping;
     volatile int nextPushStreamId = 2;
     ConcurrentLinkedQueue<PingRequest> pings = new ConcurrentLinkedQueue<>();
@@ -118,7 +119,8 @@
 
     Http2TestServerConnection(Http2TestServer server,
                               Socket socket,
-                              Http2TestExchangeSupplier exchangeSupplier)
+                              Http2TestExchangeSupplier exchangeSupplier,
+                              Properties properties)
         throws IOException
     {
         if (socket instanceof SSLSocket) {
@@ -132,8 +134,9 @@
         this.outputQ = new Queue<>(sentinel);
         this.random = new Random();
         this.socket = socket;
+        this.properties = properties;
         this.socket.setTcpNoDelay(true);
-        this.serverSettings = SettingsFrame.getDefaultSettings();
+        this.serverSettings = getServerSettingProperties();
         this.exec = server.exec;
         this.secure = server.secure;
         this.pushStreams = new HashSet<>();
@@ -141,6 +144,38 @@
         os = new BufferedOutputStream(socket.getOutputStream());
     }
 
+    static final String propPrefix = "http2server.settings.";
+
+    static final String[][] propIDs = {
+        {"header_table_size", Integer.toString(SettingsFrame.HEADER_TABLE_SIZE)},
+        {"enable_push", Integer.toString(SettingsFrame.ENABLE_PUSH)},
+        {"max_concurrent_streams", Integer.toString(SettingsFrame.MAX_CONCURRENT_STREAMS)},
+        {"initial_window_size", Integer.toString(SettingsFrame.INITIAL_WINDOW_SIZE)},
+        {"max_frame_size", Integer.toString(SettingsFrame.MAX_FRAME_SIZE)},
+        {"max_header_list_size", Integer.toString(SettingsFrame.MAX_HEADER_LIST_SIZE)}
+    };
+
+    private SettingsFrame getServerSettingProperties() {
+        SettingsFrame s = SettingsFrame.getDefaultSettings();
+        if (properties == null)
+            return s;
+        for (int i=0; i<propIDs.length; i++) {
+            String key = propIDs[i][0];
+            String numS = propIDs[i][1];
+            String prop = properties.getProperty(propPrefix + key);
+            if (prop != null) {
+                try {
+                    System.err.println("TestServer: setting " + key + " property to: " +
+                        prop);
+                    int num = Integer.parseInt(numS);
+                    System.err.println("TestServer: num = " + num);
+                    s.setParameter(num, Integer.parseInt(prop));
+                } catch (NumberFormatException e) {/* ignore errors */}
+            }
+        }
+        return s;
+    }
+
     /**
      * Sends a PING frame on this connection, and completes the returned
      * CF when the PING ack is received. The CF is given
@@ -420,11 +455,11 @@
         outputQ.put(wup);
     }
 
-    HttpHeadersImpl decodeHeaders(List<HeaderFrame> frames) throws IOException {
-        HttpHeadersImpl headers = createNewResponseHeaders();
+    HttpHeaders decodeHeaders(List<HeaderFrame> frames) throws IOException {
+        HttpHeadersBuilder headersBuilder = createNewHeadersBuilder();
 
         DecodingCallback cb = (name, value) -> {
-            headers.addHeader(name.toString(), value.toString());
+            headersBuilder.addHeader(name.toString(), value.toString());
         };
 
         for (HeaderFrame frame : frames) {
@@ -434,7 +469,7 @@
             }
         }
         hpackIn.decode(EMPTY_BUFFER, true, cb);
-        return headers;
+        return headersBuilder.build();
     }
 
     String getRequestLine(String request) {
@@ -451,8 +486,8 @@
         return request.substring(start,end);
     }
 
-    void addHeaders(String headers, HttpHeadersImpl hdrs) {
-        String[] hh = headers.split(CRLF);
+    static void addHeaders(String headersString, HttpHeadersBuilder headersBuilder) {
+        String[] hh = headersString.split(CRLF);
         for (String header : hh) {
             int colon = header.indexOf(':');
             if (colon == -1)
@@ -461,14 +496,14 @@
             String value = header.substring(colon+1);
             while (value.startsWith(" "))
                 value = value.substring(1);
-            hdrs.addHeader(name, value);
+            headersBuilder.addHeader(name, value);
         }
     }
 
     // First stream (1) comes from a plaintext HTTP/1.1 request
     @SuppressWarnings({"rawtypes","unchecked"})
     void createPrimordialStream(Http1InitialRequest request) throws IOException {
-        HttpHeadersImpl headers = createNewResponseHeaders();
+        HttpHeadersBuilder headersBuilder = createNewHeadersBuilder();
         String requestLine = getRequestLine(request.headers);
         String[] tokens = requestLine.split(" ");
         if (!tokens[2].equals("HTTP/1.1")) {
@@ -485,18 +520,19 @@
             throw new IOException("missing Host");
         }
 
-        headers.setHeader(":method", tokens[0]);
-        headers.setHeader(":scheme", "http"); // always in this case
-        headers.setHeader(":authority", host);
+        headersBuilder.setHeader(":method", tokens[0]);
+        headersBuilder.setHeader(":scheme", "http"); // always in this case
+        headersBuilder.setHeader(":authority", host);
         String path = uri.getRawPath();
         if (uri.getRawQuery() != null)
             path = path + "?" + uri.getRawQuery();
-        headers.setHeader(":path", path);
+        headersBuilder.setHeader(":path", path);
 
         Queue q = new Queue(sentinel);
         byte[] body = getRequestBody(request);
-        addHeaders(getHeaders(request.headers), headers);
-        headers.setHeader("Content-length", Integer.toString(body.length));
+        addHeaders(getHeaders(request.headers), headersBuilder);
+        headersBuilder.setHeader("Content-length", Integer.toString(body.length));
+        HttpHeaders headers = headersBuilder.build();
 
         addRequestBodyToQueue(body, q);
         streams.put(1, q);
@@ -534,7 +570,7 @@
             }
         }
         boolean endStreamReceived = endStream;
-        HttpHeadersImpl headers = decodeHeaders(frames);
+        HttpHeaders headers = decodeHeaders(frames);
 
         // Strict to assert Client correctness. Not all servers are as strict,
         // but some are known to be.
@@ -558,7 +594,7 @@
     // for this stream/request delivered on Q
 
     @SuppressWarnings({"rawtypes","unchecked"})
-    void handleRequest(HttpHeadersImpl headers,
+    void handleRequest(HttpHeaders headers,
                        Queue queue,
                        int streamid,
                        boolean endStreamReceived)
@@ -572,7 +608,6 @@
         String authority = headers.firstValue(":authority").orElse("");
         //System.out.println("authority = " + authority);
         System.err.printf("TestServer: %s %s\n", method, path);
-        HttpHeadersImpl rspheaders = createNewResponseHeaders();
         int winsize = clientSettings.getParameter(
                 SettingsFrame.INITIAL_WINDOW_SIZE);
         //System.err.println ("Stream window size = " + winsize);
@@ -592,8 +627,9 @@
             String us = scheme + "://" + authority + path;
             URI uri = new URI(us);
             boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1;
+            HttpHeadersBuilder rspheadersBuilder = createNewHeadersBuilder();
             Http2TestExchange exchange = exchangeSupplier.get(streamid, method,
-                    headers, rspheaders, uri, bis, getSSLSession(),
+                    headers, rspheadersBuilder, uri, bis, getSSLSession(),
                     bos, this, pushAllowed);
 
             // give to user
@@ -620,8 +656,8 @@
         }
     }
 
-    protected HttpHeadersImpl createNewResponseHeaders() {
-        return new HttpHeadersImpl();
+    protected HttpHeadersBuilder createNewHeadersBuilder() {
+        return new HttpHeadersBuilder();
     }
 
     private SSLSession getSSLSession() {
@@ -710,7 +746,8 @@
         }
     }
 
-    List<ByteBuffer> encodeHeaders(HttpHeadersImpl headers) {
+    /** Encodes an group of headers, without any ordering guarantees. */
+    List<ByteBuffer> encodeHeaders(HttpHeaders headers) {
         List<ByteBuffer> buffers = new LinkedList<>();
 
         ByteBuffer buf = getBuffer();
@@ -735,6 +772,30 @@
         return buffers;
     }
 
+    /** Encodes an ordered list of headers. */
+    List<ByteBuffer> encodeHeadersOrdered(List<Map.Entry<String,String>> headers) {
+        List<ByteBuffer> buffers = new LinkedList<>();
+
+        ByteBuffer buf = getBuffer();
+        boolean encoded;
+        for (Map.Entry<String, String> entry : headers) {
+            String value = entry.getValue();
+            String key = entry.getKey().toLowerCase();
+            do {
+                hpackOut.header(key, value);
+                encoded = hpackOut.encode(buf);
+                if (!encoded) {
+                    buf.flip();
+                    buffers.add(buf);
+                    buf = getBuffer();
+                }
+            } while (!encoded);
+        }
+        buf.flip();
+        buffers.add(buf);
+        return buffers;
+    }
+
     static void closeIgnore(Closeable c) {
         try {
             c.close();
@@ -812,9 +873,9 @@
     // returns a minimal response with status 200
     // that is the response to the push promise just sent
     private ResponseHeaders getPushResponse(int streamid) {
-        HttpHeadersImpl h = createNewResponseHeaders();
-        h.addHeader(":status", "200");
-        ResponseHeaders oh = new ResponseHeaders(h);
+        HttpHeadersBuilder hb = createNewHeadersBuilder();
+        hb.addHeader(":status", "200");
+        ResponseHeaders oh = new ResponseHeaders(hb.build());
         oh.streamid(streamid);
         oh.setFlag(HeaderFrame.END_HEADERS);
         return oh;
@@ -1047,9 +1108,9 @@
     // for the hashmap.
 
     static class ResponseHeaders extends Http2Frame {
-        HttpHeadersImpl headers;
+        HttpHeaders headers;
 
-        ResponseHeaders(HttpHeadersImpl headers) {
+        ResponseHeaders(HttpHeaders headers) {
             super(0, 0);
             this.headers = headers;
         }
--- a/test/jdk/java/net/httpclient/http2/server/OutgoingPushPromise.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/OutgoingPushPromise.java	Thu Jun 21 09:53:50 2018 -0700
@@ -21,22 +21,22 @@
  * questions.
  */
 
-import java.io.*;
-import java.net.*;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.http.HttpHeaders;
 import jdk.internal.net.http.frame.Http2Frame;
 
 // will be converted to a PushPromiseFrame in the writeLoop
 // a thread is then created to produce the DataFrames from the InputStream
 class OutgoingPushPromise extends Http2Frame {
-    final HttpHeadersImpl headers;
+    final HttpHeaders headers;
     final URI uri;
     final InputStream is;
     final int parentStream; // not the pushed streamid
 
     public OutgoingPushPromise(int parentStream,
                                URI uri,
-                               HttpHeadersImpl headers,
+                               HttpHeaders headers,
                                InputStream is) {
         super(0,0);
         this.uri = uri;
--- a/test/jdk/java/net/httpclient/http2/server/PushHandler.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/http2/server/PushHandler.java	Thu Jun 21 09:53:50 2018 -0700
@@ -23,11 +23,16 @@
 
 import java.io.*;
 import java.net.*;
+import java.net.http.HttpHeaders;
 import java.nio.file.*;
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiPredicate;
 
 public class PushHandler implements Http2Handler {
 
+    static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
     final Path tempFile;
     final int loops;
     final long file_size;
@@ -50,8 +55,8 @@
                 for (int i=0; i<loops; i++) {
                     InputStream is = new FileInputStream(tempFile.toFile());
                     URI u = requestURI.resolve("/x/y/z/" + Integer.toString(i));
-                    HttpHeadersImpl h = new HttpHeadersImpl();
-                    h.addHeader("X-foo", "bar");
+                    HttpHeaders h = HttpHeaders.of(Map.of("X-foo", List.of("bar")),
+                                                   ACCEPT_ALL);
                     ee.serverPush(u, h, is);
                 }
                 System.err.println ("Server: sent all pushes");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/noPermissions.policy	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+//
+// This code is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 2 only, as
+// published by the Free Software Foundation.
+//
+// This code is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// version 2 for more details (a copy is included in the LICENSE file that
+// accompanied this code).
+//
+// You should have received a copy of the GNU General Public License version
+// 2 along with this work; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+// or visit www.oracle.com if you need additional information or have any
+// questions.
+//
+
+grant codeBase "file:${test.classes}/*" { };
--- a/test/jdk/java/net/httpclient/offline/FixedHttpHeaders.java	Wed Jun 20 11:12:48 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.TreeMap;
-import java.net.http.HttpHeaders;
-
-/**
- * An HttpHeaders consisting of the given name value pairs.
- */
-public class FixedHttpHeaders extends HttpHeaders {
-
-    private final Map<String, List<String>> map =
-            new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-
-    @Override
-    public Map<String, List<String>> map() {
-        return map;
-    }
-
-    /**
-     * Creates an HttpHeaders of the given name value pairs.
-     */
-    public static HttpHeaders of(String... params) {
-        Objects.requireNonNull(params);
-        if ((params.length & 0x1) != 0)
-            throw new IllegalArgumentException("odd number of params");
-        FixedHttpHeaders headers = new FixedHttpHeaders();
-        for (int i = 0; i < params.length; i += 2) {
-            String name = params[i];
-            String value = params[i + 1];
-            headers.map.computeIfAbsent(name, k -> new ArrayList<>(1))
-                       .add(value);
-        }
-        return headers;
-    }
-}
--- a/test/jdk/java/net/httpclient/offline/OfflineTesting.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/offline/OfflineTesting.java	Thu Jun 21 09:53:50 2018 -0700
@@ -24,19 +24,26 @@
 /*
  * @test
  * @summary Demonstrates how to achieve testing without network connections
- * @build FixedHttpHeaders DelegatingHttpClient FixedHttpResponse FixedResponseHttpClient
+ * @build DelegatingHttpClient FixedHttpResponse FixedResponseHttpClient
  * @run testng/othervm OfflineTesting
  */
 
 import java.io.IOException;
 import java.net.URI;
 import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
 import java.net.http.HttpRequest.BodyPublishers;
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiPredicate;
 import org.testng.annotations.Test;
+import static java.lang.String.format;
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
@@ -49,8 +56,8 @@
         return FixedResponseHttpClient.createClientFrom(
                 HttpClient.newBuilder(),
                 200,
-                FixedHttpHeaders.of("Server",  "nginx",
-                                    "Content-Type", "text/html"),
+                headersOf("Server", "nginx",
+                          "Content-Type", "text/html"),
                 "A response message");
     }
 
@@ -94,11 +101,11 @@
         HttpClient client = FixedResponseHttpClient.createClientFrom(
                 HttpClient.newBuilder(),
                 404,
-                FixedHttpHeaders.of("Connection",  "keep-alive",
-                                    "Content-Length", "162",
-                                    "Content-Type", "text/html",
-                                    "Date", "Mon, 15 Jan 2018 15:01:16 GMT",
-                                    "Server", "nginx"),
+                headersOf("Connection",  "keep-alive",
+                          "Content-Length", "162",
+                          "Content-Type", "text/html",
+                          "Date", "Mon, 15 Jan 2018 15:01:16 GMT",
+                          "Server", "nginx"),
                 "<html>\n" +
                 "<head><title>404 Not Found</title></head>\n" +
                 "<body bgcolor=\"white\">\n" +
@@ -126,7 +133,7 @@
         HttpClient client = FixedResponseHttpClient.createEchoClient(
                 HttpClient.newBuilder(),
                 200,
-                FixedHttpHeaders.of("Connection",  "keep-alive"));
+                headersOf("Connection",  "keep-alive"));
 
         HttpRequest request = HttpRequest.newBuilder()
                 .uri(URI.create("http://openjdk.java.net/echo"))
@@ -146,7 +153,7 @@
         HttpClient client = FixedResponseHttpClient.createEchoClient(
                 HttpClient.newBuilder(),
                 200,
-                FixedHttpHeaders.of("Connection",  "keep-alive"));
+                headersOf("Connection",  "keep-alive"));
 
         HttpRequest request = HttpRequest.newBuilder()
                 .uri(URI.create("http://openjdk.java.net/echo"))
@@ -158,4 +165,26 @@
         assertEquals(response.statusCode(), 200);
         assertEquals(response.body(), "Hello chegar!!");
     }
+
+    // ---
+
+    public static IllegalArgumentException newIAE(String message, Object... args) {
+        return new IllegalArgumentException(format(message, args));
+    }
+
+    static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
+    static HttpHeaders headersOf(String... params) {
+        Map<String,List<String>> map = new HashMap<>();
+        requireNonNull(params);
+        if (params.length == 0 || params.length % 2 != 0) {
+            throw newIAE("wrong number, %d, of parameters", params.length);
+        }
+        for (int i = 0; i < params.length; i += 2) {
+            String name  = params[i];
+            String value = params[i + 1];
+            map.put(name, List.of(value));
+        }
+        return HttpHeaders.of(map, ACCEPT_ALL);
+    }
 }
--- a/test/jdk/java/net/httpclient/ssltest/CertificateTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/ssltest/CertificateTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -22,6 +22,7 @@
  */
 
 import java.io.File;
+import java.io.IOException;
 import java.net.URI;
 import java.net.http.HttpClient;
 import java.net.http.HttpResponse.BodyHandlers;
@@ -30,6 +31,7 @@
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLParameters;
+import static java.net.http.HttpClient.Builder.NO_PROXY;
 
 /*
  * @test
@@ -112,6 +114,7 @@
         Exception exception = null;
         System.out.println("Making request to " + uri_s);
         HttpClient client = HttpClient.newBuilder()
+                .proxy(NO_PROXY)
                 .sslContext(ctx)
                 .sslParameters(params)
                 .build();
@@ -128,7 +131,9 @@
                 error = "Test failed: good: status should be 200";
             else if (!expectSuccess)
                 error = "Test failed: bad: status should not be 200";
-        } catch (SSLException e) {
+        } catch (IOException e) {
+            // there must be an SSLException as the exception or cause
+            checkExceptionOrCause(SSLException.class, e);
             System.err.println("Caught Exception " + e + ". expectSuccess = " + expectSuccess);
             exception = e;
             if (expectSuccess)
@@ -137,4 +142,16 @@
         if (error != null)
             throw new RuntimeException(error, exception);
     }
+
+    static void checkExceptionOrCause(Class<? extends Throwable> clazz, Throwable t) {
+        final Throwable original = t;
+        do {
+            if (clazz.isInstance(t)) {
+                System.out.println("Found expected exception/cause: " + t);
+                return; // found
+            }
+        } while ((t = t.getCause()) != null);
+        original.printStackTrace(System.out);
+        throw new RuntimeException("Expected " + clazz + "in " + original);
+    }
 }
--- a/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java	Thu Jun 21 09:53:50 2018 -0700
@@ -87,6 +87,11 @@
             listener = new MockListener() {
 
                 @Override
+                protected void onOpen0(WebSocket webSocket) {
+                    /* do nothing */
+                }
+
+                @Override
                 protected void replenish(WebSocket webSocket) {
                     /* do nothing */
                 }
--- a/test/jdk/java/net/httpclient/websocket/MockListener.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/websocket/MockListener.java	Thu Jun 21 09:53:50 2018 -0700
@@ -39,11 +39,15 @@
     private final Predicate<? super Invocation> collectUntil;
 
     public MockListener() {
-        this(i -> i instanceof OnClose || i instanceof OnError);
+        this(1, MockListener::closeOrError);
+    }
+
+    public MockListener(long bufferSize) {
+        this(bufferSize, MockListener::closeOrError);
     }
 
     public MockListener(Predicate<? super Invocation> collectUntil) {
-        this(2, collectUntil);
+        this(1, collectUntil);
     }
 
     /*
@@ -59,6 +63,10 @@
         this.collectUntil = collectUntil;
     }
 
+    private static boolean closeOrError(Invocation i) {
+        return i instanceof OnClose || i instanceof OnError;
+    }
+
     @Override
     public void onOpen(WebSocket webSocket) {
         System.out.printf("onOpen(%s)%n", webSocket);
@@ -73,7 +81,9 @@
     }
 
     protected void onOpen0(WebSocket webSocket) {
-        replenish(webSocket);
+        count = bufferSize - bufferSize / 2;
+        System.out.printf("request(%d)%n", bufferSize);
+        webSocket.request(bufferSize);
     }
 
     @Override
@@ -209,8 +219,9 @@
     protected void replenish(WebSocket webSocket) {
         if (--count <= 0) {
             count = bufferSize - bufferSize / 2;
+            webSocket.request(count);
+            System.out.printf("request(%d)%n", count);
         }
-        webSocket.request(count);
     }
 
     public abstract static class Invocation {
--- a/test/jdk/java/net/httpclient/websocket/WebSocketTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/websocket/WebSocketTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,11 +25,11 @@
  * @test
  * @build DummyWebSocketServer
  * @run testng/othervm
- *      -Djdk.internal.httpclient.websocket.debug=true
  *       WebSocketTest
  */
 
 import org.testng.annotations.AfterTest;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import java.io.IOException;
@@ -41,7 +41,10 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
+
 import static java.net.http.HttpClient.Builder.NO_PROXY;
 import static java.net.http.HttpClient.newBuilder;
 import static java.net.http.WebSocket.NORMAL_CLOSURE;
@@ -197,6 +200,126 @@
         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(0)));
     }
 
+    @DataProvider(name = "sequence")
+    public Object[][] data1() {
+        int[] CLOSE = {
+                0x81, 0x00, // ""
+                0x82, 0x00, // []
+                0x89, 0x00, // <PING>
+                0x8a, 0x00, // <PONG>
+                0x88, 0x00, // <CLOSE>
+        };
+        int[] ERROR = {
+                0x81, 0x00, // ""
+                0x82, 0x00, // []
+                0x89, 0x00, // <PING>
+                0x8a, 0x00, // <PONG>
+                0x8b, 0x00, // 0xB control frame (causes an error)
+        };
+        return new Object[][]{
+                {CLOSE, 1},
+                {CLOSE, 3},
+                {CLOSE, 4},
+                {CLOSE, Long.MAX_VALUE},
+                {ERROR, 1},
+                {ERROR, 3},
+                {ERROR, 4},
+                {ERROR, Long.MAX_VALUE},
+        };
+    }
+
+    @Test(dataProvider = "sequence")
+    public void listenerSequentialOrder(int[] binary, long requestSize)
+            throws IOException
+    {
+
+        server = Support.serverWithCannedData(binary);
+        server.open();
+
+        CompletableFuture<Void> violation = new CompletableFuture<>();
+
+        MockListener listener = new MockListener(requestSize) {
+
+            final AtomicBoolean guard = new AtomicBoolean();
+
+            private <T> T checkRunExclusively(Supplier<T> action) {
+                if (guard.getAndSet(true)) {
+                    violation.completeExceptionally(new RuntimeException());
+                }
+                try {
+                    return action.get();
+                } finally {
+                    if (!guard.getAndSet(false)) {
+                        violation.completeExceptionally(new RuntimeException());
+                    }
+                }
+            }
+
+            @Override
+            public void onOpen(WebSocket webSocket) {
+                checkRunExclusively(() -> {
+                    super.onOpen(webSocket);
+                    return null;
+                });
+            }
+
+            @Override
+            public CompletionStage<?> onText(WebSocket webSocket,
+                                             CharSequence data,
+                                             boolean last) {
+                return checkRunExclusively(
+                        () -> super.onText(webSocket, data, last));
+            }
+
+            @Override
+            public CompletionStage<?> onBinary(WebSocket webSocket,
+                                               ByteBuffer data,
+                                               boolean last) {
+                return checkRunExclusively(
+                        () -> super.onBinary(webSocket, data, last));
+            }
+
+            @Override
+            public CompletionStage<?> onPing(WebSocket webSocket,
+                                             ByteBuffer message) {
+                return checkRunExclusively(
+                        () -> super.onPing(webSocket, message));
+            }
+
+            @Override
+            public CompletionStage<?> onPong(WebSocket webSocket,
+                                             ByteBuffer message) {
+                return checkRunExclusively(
+                        () -> super.onPong(webSocket, message));
+            }
+
+            @Override
+            public CompletionStage<?> onClose(WebSocket webSocket,
+                                              int statusCode,
+                                              String reason) {
+                return checkRunExclusively(
+                        () -> super.onClose(webSocket, statusCode, reason));
+            }
+
+            @Override
+            public void onError(WebSocket webSocket, Throwable error) {
+                checkRunExclusively(() -> {
+                    super.onError(webSocket, error);
+                    return null;
+                });
+            }
+        };
+
+        webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
+                .buildAsync(server.getURI(), listener)
+                .join();
+
+
+        listener.invocations();
+        violation.complete(null); // won't affect if completed exceptionally
+        violation.join();
+    }
+
     @Test
     public void sendMethodsThrowIOE2() throws Exception {
         server = Support.serverWithCannedData(0x88, 0x00);
--- a/test/jdk/java/net/httpclient/whitebox/ConnectionPoolTestDriver.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/whitebox/ConnectionPoolTestDriver.java	Thu Jun 21 09:53:50 2018 -0700
@@ -31,5 +31,8 @@
   *         java.management
  * @run main/othervm
  *       --add-reads java.net.http=java.management
- *       java.net.http/jdk.internal.net.http.ConnectionPoolTest
+ *       java.net.http/jdk.internal.net.http.ConnectionPoolTest testCacheCleaners
+ * @run main/othervm
+ *       --add-reads java.net.http=java.management
+ *       java.net.http/jdk.internal.net.http.ConnectionPoolTest testPoolSize
  */
--- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -23,7 +23,7 @@
 
 package jdk.internal.net.http;
 
-import jdk.internal.net.http.common.HttpHeadersImpl;
+import jdk.internal.net.http.common.HttpHeadersBuilder;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import org.testng.annotations.AfterClass;
@@ -35,17 +35,19 @@
 import java.net.ProxySelector;
 import java.net.URI;
 import java.net.URL;
-import java.net.http.HttpClient;
 import java.net.http.HttpHeaders;
 import java.net.http.HttpResponse;
 import java.net.http.HttpResponse.BodyHandlers;
 import java.security.AccessController;
 import java.util.Arrays;
 import java.util.Base64;
+import java.util.Collections;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.net.http.HttpClient.Version;
+import java.util.function.BiPredicate;
 
 import static java.lang.String.format;
 import static java.lang.System.out;
@@ -163,6 +165,8 @@
         });
     }
 
+    static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;
+
     private void doTestAuthentication(String uri, Version v, String proxy) throws Exception {
         int colon = proxy == null ? -1 : proxy.lastIndexOf(":");
         ProxySelector ps = proxy == null ? NO_PROXY
@@ -197,8 +201,9 @@
         Exchange<?> exchange = new Exchange<>(req, multi);
         out.println("\nSimulating unauthenticated request to " + uri);
         filter.request(req, multi);
-        assertFalse(req.getSystemHeaders().firstValue(authorization(true)).isPresent());
-        assertFalse(req.getSystemHeaders().firstValue(authorization(false)).isPresent());
+        HttpHeaders hdrs = req.getSystemHeadersBuilder().build();
+        assertFalse(hdrs.firstValue(authorization(true)).isPresent());
+        assertFalse(hdrs.firstValue(authorization(false)).isPresent());
         assertEquals(authenticator.COUNTER.get(), 0);
 
         // Creates the Response to the first request, and call filter.response
@@ -207,9 +212,10 @@
         // credentials, and will also cache the credentials in the multi exchange.
         // The credentials shouldn't be put in the cache until the 200 response
         // for that request arrives.
-        HttpHeadersImpl headers = new HttpHeadersImpl();
-        headers.addHeader(authenticate(proxy!=null),
-                "Basic realm=\"earth\"");
+        HttpHeadersBuilder headersBuilder = new HttpHeadersBuilder();
+        headersBuilder.addHeader(authenticate(proxy!=null),
+                                "Basic realm=\"earth\"");
+        HttpHeaders headers = headersBuilder.build();
         Response response = new Response(req, exchange, headers, null, unauthorized, v);
         out.println("Simulating " + unauthorized
                 + " response from " + uri);
@@ -218,7 +224,7 @@
         out.println("Checking filter's response to "
                 + unauthorized + " from " + uri);
         assertTrue(next != null, "next should not be null");
-        String[] up = check(reqURI, next.getSystemHeaders(), proxy);
+        String[] up = check(reqURI, next.getSystemHeadersBuilder().build(), proxy);
         assertEquals(authenticator.COUNTER.get(), 1);
 
         // Now simulate a new successful exchange to get the credentials in the cache
@@ -230,10 +236,12 @@
         exchange = new Exchange<>(next, multi);
         filter.request(next, multi);
         out.println("Checking credentials in request header after filter for " + uri);
-        check(reqURI, next.getSystemHeaders(), proxy);
-        check(next.uri(), next.getSystemHeaders(), proxy);
+        hdrs = next.getSystemHeadersBuilder().build();
+        check(reqURI, hdrs, proxy);
+        check(next.uri(), hdrs, proxy);
         out.println("Simulating  successful response 200 from " + uri);
-        response = new Response(next, exchange, new HttpHeadersImpl(), null, 200, v);
+        HttpHeaders h = HttpHeaders.of(Collections.emptyMap(), ACCEPT_ALL);
+        response = new Response(next, exchange,h, null, 200, v);
         next = filter.response(response);
         assertTrue(next == null, "next should be null");
         assertEquals(authenticator.COUNTER.get(), 1);
@@ -263,7 +271,7 @@
         filter.request(req2, multi2);
         out.println("Check that filter has added credentials from cache for " + reqURI2
                 + " with proxy " + req2.proxy());
-        String[] up2 = check(reqURI, req2.getSystemHeaders(), proxy);
+        String[] up2 = check(reqURI, req2.getSystemHeadersBuilder().build(), proxy);
         assertTrue(Arrays.deepEquals(up, up2), format("%s:%s != %s:%s", up2[0], up2[1], up[0], up[1]));
         assertEquals(authenticator.COUNTER.get(), 1);
 
@@ -293,24 +301,25 @@
                 HttpResponse.BodyHandlers.replacing(null),
                 null, AccessController.getContext());
         filter.request(req3, multi3);
+        HttpHeaders h3 = req3.getSystemHeadersBuilder().build();
         if (proxy == null) {
             out.println("Check that filter has not added proxy credentials from cache for " + reqURI3);
-            assert !req3.getSystemHeaders().firstValue(authorization(true)).isPresent()
+            assert !h3.firstValue(authorization(true)).isPresent()
                     : format("Unexpected proxy credentials found: %s",
-                    java.util.stream.Stream.of(getAuthorization(req3.getSystemHeaders(), true))
+                    java.util.stream.Stream.of(getAuthorization(req3.getSystemHeadersBuilder().build(), true))
                             .collect(joining(":")));
-            assertFalse(req3.getSystemHeaders().firstValue(authorization(true)).isPresent());
+            assertFalse(h3.firstValue(authorization(true)).isPresent());
         } else {
             out.println("Check that filter has added proxy credentials from cache for " + reqURI3);
-            String[] up3 = check(reqURI, req3.getSystemHeaders(), proxy);
+            String[] up3 = check(reqURI, h3, proxy);
             assertTrue(Arrays.deepEquals(up, up3), format("%s:%s != %s:%s", up3[0], up3[1], up[0], up[1]));
         }
         out.println("Check that filter has not added server credentials from cache for " + reqURI3);
-        assert !req3.getSystemHeaders().firstValue(authorization(false)).isPresent()
+        assert !h3.firstValue(authorization(false)).isPresent()
                 : format("Unexpected server credentials found: %s",
-                java.util.stream.Stream.of(getAuthorization(req3.getSystemHeaders(), false))
+                java.util.stream.Stream.of(getAuthorization(h3, false))
                         .collect(joining(":")));
-        assertFalse(req3.getSystemHeaders().firstValue(authorization(false)).isPresent());
+        assertFalse(h3.firstValue(authorization(false)).isPresent());
         assertEquals(authenticator.COUNTER.get(), 1);
 
         // Now we will verify that credentials for proxies are not used for servers and
@@ -341,23 +350,24 @@
         filter.request(req4, multi4);
         out.println("Check that filter has not added proxy credentials from cache for "
                 + reqURI4 + " (proxy: " + req4.proxy()  + ")");
-        assert !req4.getSystemHeaders().firstValue(authorization(true)).isPresent()
+        HttpHeaders h4 = req4.getSystemHeadersBuilder().build();
+        assert !h4.firstValue(authorization(true)).isPresent()
                 : format("Unexpected proxy credentials found: %s",
-                java.util.stream.Stream.of(getAuthorization(req4.getSystemHeaders(), true))
+                java.util.stream.Stream.of(getAuthorization(h4, true))
                         .collect(joining(":")));
-        assertFalse(req4.getSystemHeaders().firstValue(authorization(true)).isPresent());
+        assertFalse(h4.firstValue(authorization(true)).isPresent());
         if (proxy != null) {
             out.println("Check that filter has not added server credentials from cache for "
                     + reqURI4 + " (proxy: " + req4.proxy()  + ")");
-            assert !req4.getSystemHeaders().firstValue(authorization(false)).isPresent()
+            assert !h4.firstValue(authorization(false)).isPresent()
                     : format("Unexpected server credentials found: %s",
-                    java.util.stream.Stream.of(getAuthorization(req4.getSystemHeaders(), false))
+                    java.util.stream.Stream.of(getAuthorization(h4, false))
                             .collect(joining(":")));
-            assertFalse(req4.getSystemHeaders().firstValue(authorization(false)).isPresent());
+            assertFalse(h4.firstValue(authorization(false)).isPresent());
         } else {
             out.println("Check that filter has added server credentials from cache for "
                     + reqURI4 + " (proxy: " + req4.proxy()  + ")");
-            String[] up4 = check(reqURI, req4.getSystemHeaders(), proxy);
+            String[] up4 = check(reqURI, h4, proxy);
             assertTrue(Arrays.deepEquals(up, up4),  format("%s:%s != %s:%s", up4[0], up4[1], up[0], up[1]));
         }
         assertEquals(authenticator.COUNTER.get(), 1);
@@ -381,24 +391,26 @@
             filter.request(req5, multi5);
             out.println("Check that filter has not added server credentials from cache for "
                     + reqURI + " (proxy: " + req5.proxy()  + ")");
-            assert !req5.getSystemHeaders().firstValue(authorization(false)).isPresent()
+            HttpHeaders h5 = req5.getSystemHeadersBuilder().build();
+            assert !h5.firstValue(authorization(false)).isPresent()
                     : format("Unexpected server credentials found: %s",
-                    java.util.stream.Stream.of(getAuthorization(req5.getSystemHeaders(), false))
+                    java.util.stream.Stream.of(getAuthorization(h5, false))
                             .collect(joining(":")));
-            assertFalse(req5.getSystemHeaders().firstValue(authorization(false)).isPresent());
+            assertFalse(h5.firstValue(authorization(false)).isPresent());
             out.println("Check that filter has not added proxy credentials from cache for "
                     + reqURI + " (proxy: " + req5.proxy()  + ")");
-            assert !req5.getSystemHeaders().firstValue(authorization(true)).isPresent()
+            assert !h5.firstValue(authorization(true)).isPresent()
                     : format("Unexpected proxy credentials found: %s",
-                    java.util.stream.Stream.of(getAuthorization(req5.getSystemHeaders(), true))
+                    java.util.stream.Stream.of(getAuthorization(h5, true))
                             .collect(joining(":")));
-            assertFalse(req5.getSystemHeaders().firstValue(authorization(true)).isPresent());
+            assertFalse(h5.firstValue(authorization(true)).isPresent());
             assertEquals(authenticator.COUNTER.get(), 1);
 
             // Now simulate a 401 response from the server
-            HttpHeadersImpl headers5 = new HttpHeadersImpl();
-            headers5.addHeader(authenticate(false),
-                    "Basic realm=\"earth\"");
+            HttpHeadersBuilder headers5Builder = new HttpHeadersBuilder();
+            headers5Builder.addHeader(authenticate(false),
+                               "Basic realm=\"earth\"");
+            HttpHeaders headers5 = headers5Builder.build();
             unauthorized = 401;
             Response response5 = new Response(req5, exchange5, headers5, null, unauthorized, v);
             out.println("Simulating " + unauthorized
@@ -409,12 +421,13 @@
             out.println("Checking filter's response to "
                     + unauthorized + " from " + uri);
             assertTrue(next5 != null, "next5 should not be null");
-            String[] up5 = check(reqURI, next5.getSystemHeaders(), null);
+            String[] up5 = check(reqURI, next5.getSystemHeadersBuilder().build(), null);
 
             // now simulate a 200 response from the server
             exchange5 = new Exchange<>(next5, multi5);
             filter.request(next5, multi5);
-            response5 = new Response(next5, exchange5, new HttpHeadersImpl(), null, 200, v);
+            h = HttpHeaders.of(Map.of(), ACCEPT_ALL);
+            response5 = new Response(next5, exchange5, h, null, 200, v);
             filter.response(response5);
             assertEquals(authenticator.COUNTER.get(), 2);
 
@@ -432,10 +445,11 @@
             filter.request(req6, multi6);
             out.println("Check that filter has added server credentials from cache for "
                     + reqURI + " (proxy: " + req6.proxy()  + ")");
-            check(reqURI, req6.getSystemHeaders(), null);
+            HttpHeaders h6 = req6.getSystemHeadersBuilder().build();
+            check(reqURI, h6, null);
             out.println("Check that filter has added proxy credentials from cache for "
                     + reqURI + " (proxy: " + req6.proxy()  + ")");
-            String[] up6 = check(reqURI, req6.getSystemHeaders(), proxy);
+            String[] up6 = check(reqURI, h6, proxy);
             assertTrue(Arrays.deepEquals(up, up6), format("%s:%s != %s:%s", up6[0], up6[1], up[0], up[1]));
             assertEquals(authenticator.COUNTER.get(), 2);
         }
@@ -456,18 +470,19 @@
             out.println("Check that filter has not added server credentials from cache for "
                     + reqURI7 + " (proxy: " + req7.proxy()  + ") [resolved uri: "
                     + reqURI7.resolve(".") + " should not match " + reqURI.resolve(".") + "]");
-            assert !req7.getSystemHeaders().firstValue(authorization(false)).isPresent()
+            HttpHeaders h7 = req7.getSystemHeadersBuilder().build();
+            assert !h7.firstValue(authorization(false)).isPresent()
                     : format("Unexpected server credentials found: %s",
-                    java.util.stream.Stream.of(getAuthorization(req7.getSystemHeaders(), false))
+                    java.util.stream.Stream.of(getAuthorization(h7, false))
                             .collect(joining(":")));
-            assertFalse(req7.getSystemHeaders().firstValue(authorization(false)).isPresent());
+            assertFalse(h7.firstValue(authorization(false)).isPresent());
             out.println("Check that filter has not added proxy credentials from cache for "
                     + reqURI7 + " (proxy: " + req7.proxy()  + ")");
-            assert !req7.getSystemHeaders().firstValue(authorization(true)).isPresent()
+            assert !h7.firstValue(authorization(true)).isPresent()
                     : format("Unexpected proxy credentials found: %s",
-                    java.util.stream.Stream.of(getAuthorization(req7.getSystemHeaders(), true))
+                    java.util.stream.Stream.of(getAuthorization(h7, true))
                             .collect(joining(":")));
-            assertFalse(req7.getSystemHeaders().firstValue(authorization(true)).isPresent());
+            assertFalse(h7.firstValue(authorization(true)).isPresent());
             assertEquals(authenticator.COUNTER.get(), 1);
 
         }
--- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -31,6 +31,7 @@
 import java.net.ProxySelector;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.Random;
@@ -67,14 +68,24 @@
     }
 
     public static void main(String[] args) throws Exception {
-        testCacheCleaners();
+        if (args.length == 0) {
+            args = new String[] {"testCacheCleaners"};
+        }
+        for (String arg : args) {
+            if ("testCacheCleaners".equals(arg)) {
+                testCacheCleaners();
+            } else if ("testPoolSize".equals(arg)) {
+                assert args.length == 1 : "testPoolSize should be run in its own VM";
+                testPoolSize();
+            }
+        }
     }
 
     public static void testCacheCleaners() throws Exception {
         ConnectionPool pool = new ConnectionPool(666);
         HttpClient client = new HttpClientStub(pool);
         InetSocketAddress proxy = InetSocketAddress.createUnresolved("bar", 80);
-        System.out.println("Adding 10 connections to pool");
+        System.out.println("Adding 20 connections to pool");
         Random random = new Random();
 
         final int count = 20;
@@ -146,6 +157,74 @@
         }
     }
 
+    public static void testPoolSize() throws Exception {
+        final int MAX_POOL_SIZE = 10;
+        System.setProperty("jdk.httpclient.connectionPoolSize",
+                String.valueOf(MAX_POOL_SIZE));
+        ConnectionPool pool = new ConnectionPool(666);
+        HttpClient client = new HttpClientStub(pool);
+        InetSocketAddress proxy = InetSocketAddress.createUnresolved("bar", 80);
+        System.out.println("Adding 20 connections to pool");
+        Random random = new Random();
+
+        final int count = 20;
+        Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
+        int[] keepAlives = new int[count];
+        HttpConnectionStub[] connections = new HttpConnectionStub[count];
+        long purge = pool.purgeExpiredConnectionsAndReturnNextDeadline(now);
+        long expected = 0;
+        if (purge != expected) {
+            throw new RuntimeException("Bad purge delay: " + purge
+                    + ", expected " + expected);
+        }
+        expected = Long.MAX_VALUE;
+        int previous = 0;
+        for (int i=0; i<count; i++) {
+            InetSocketAddress addr = InetSocketAddress.createUnresolved("foo"+i, 80);
+            keepAlives[i] = random.nextInt(10) * 10  + 5 + previous;
+            previous = keepAlives[i];
+            connections[i] = new HttpConnectionStub(client, addr, proxy, true);
+            System.out.println("Adding connection: " + now
+                    + " keepAlive: " + keepAlives[i]
+                    + " /" + connections[i]);
+            pool.returnToPool(connections[i], now, keepAlives[i]);
+            if (i < MAX_POOL_SIZE) {
+                expected = Math.min(expected, keepAlives[i] * 1000);
+            } else {
+                expected = keepAlives[i-MAX_POOL_SIZE+1] * 1000;
+                if (pool.contains(connections[i-MAX_POOL_SIZE])) {
+                    throw new RuntimeException("Connection[" + i + "]/"
+                            + connections[i] + " should have been removed");
+                }
+            }
+            purge = pool.purgeExpiredConnectionsAndReturnNextDeadline(now);
+            if (purge != expected) {
+                throw new RuntimeException("Bad purge delay for " + i + ": "
+                        + purge + ", expected " + expected);
+            }
+        }
+
+        long opened = java.util.stream.Stream.of(connections)
+                .filter(HttpConnectionStub::connected).count();
+        if (opened != MAX_POOL_SIZE) {
+            throw new RuntimeException("Opened: expected "
+                    + count + " got " + opened);
+        }
+        for (int i=0 ; i<count; i++) {
+            boolean closed = (i < count - MAX_POOL_SIZE);
+            if (connections[i].closed != closed) {
+                throw new RuntimeException("connection[" + i + "] should be "
+                        + (closed ? "closed" : "opened"));
+            }
+            if (pool.contains(connections[i]) == closed) {
+                throw new RuntimeException("Connection[" + i + "]/"
+                        + connections[i] + " should "
+                        + (closed ? "" : "not ")
+                        + "have been removed");
+            }
+        }
+    }
+
     static <T> T error() {
         throw new InternalError("Should not reach here: wrong test assumptions!");
     }
--- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/Http1HeaderParserTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/Http1HeaderParserTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -32,6 +32,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.IntStream;
 import sun.net.www.MessageHeader;
 import org.testng.annotations.Test;
@@ -132,6 +134,11 @@
               "Connection: keep-alive\r\n\r\n"
             };
         Arrays.stream(basic).forEach(responses::add);
+        // add some tests where some of the CRLF are replaced
+        // by a single LF
+        Arrays.stream(basic)
+                .map(Http1HeaderParserTest::mixedCRLF)
+                .forEach(responses::add);
 
         String[] foldingTemplate =
            {  "HTTP/1.1 200 OK\r\n" +
@@ -187,6 +194,12 @@
             for (String template : foldingTemplate)
                 responses.add(template.replace("$NEWLINE", newLineChar));
         }
+        // add some tests where some of the CRLF are replaced
+        // by a single LF
+        for (String newLineChar : new String[] { "\n", "\r", "\r\n" }) {
+            for (String template : foldingTemplate)
+                responses.add(mixedCRLF(template).replace("$NEWLINE", newLineChar));
+        }
 
         String[] bad = // much of this is to retain parity with legacy MessageHeaders
            { "HTTP/1.1 200 OK\r\n" +
@@ -237,20 +250,77 @@
         return responses.stream().map(p -> new Object[] { p }).toArray(Object[][]::new);
     }
 
+    static final AtomicInteger index = new AtomicInteger();
+    static final AtomicInteger limit = new AtomicInteger(1);
+    static final AtomicBoolean useCRLF = new AtomicBoolean();
+    // A small method to replace part of the CRLF present in a string
+    // with simple LF. The method uses a deterministic algorithm based
+    // on current values of static index/limit/useCRLF counters.
+    // These counters are used to produce a stream of substitutes that
+    // looks like this:
+    // LF CRLF LF LF CRLF CRLF LF LF LF CRLF CRLF CRLF (then repeat from start)
+    static final String mixedCRLF(String headers) {
+        int next;
+        int start = 0;
+        int last = headers.lastIndexOf("\r\n");
+        String prev = "";
+        StringBuilder res = new StringBuilder();
+        while ((next = headers.indexOf("\r\n", start)) > 0) {
+            res.append(headers.substring(start, next));
+            if ("\n".equals(prev) && next == last) {
+                // for some reason the legacy MessageHeader parser will
+                // not consume the final LF if the headers are terminated
+                // by <LF><CRLF> instead of <CRLF><CRLF>. It consume
+                // <LF><CR> but leaves the last <LF> in the stream.
+                // Here we just make sure to avoid using <LF><CRLF>
+                // as that would cause the legacy parser to consume
+                // 1 byte less than the Http1HeadersParser - which
+                // does consume the last <LF>, as it should.
+                // if this is the last CRLF and the previous one
+                // was replaced by LF then use LF.
+                res.append(prev);
+            } else {
+                prev = useCRLF.get() ? "\r\n" : "\n";
+                res.append(prev);
+            }
+            // skip CRLF
+            start = next + 2;
+
+            // The idea is to substitute some of the CRLF with LF.
+            // Rather than doing this randomly, always use the following
+            // sequence:
+            // LF CRLF LF LF CRLF CRLF LF LF LF CRLF CRLF CRLF
+            index.incrementAndGet();
+            if (index.get() == limit.get()) {
+                index.set(0);
+                if (useCRLF.get()) limit.incrementAndGet();
+                if (limit.get() > 3) limit.set(1);
+                useCRLF.set(!useCRLF.get());
+            }
+        }
+        res.append(headers.substring(start));
+        return res.toString();
+    }
+
+
     @Test(dataProvider = "responses")
     public void verifyHeaders(String respString) throws Exception {
+        System.out.println("\ntesting:\n\t" + respString
+                .replace("\r\n", "<CRLF>")
+                .replace("\r", "<CR>")
+                .replace("\n","<LF>")
+                .replace("LF>", "LF>\n\t"));
         byte[] bytes = respString.getBytes(US_ASCII);
         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
         MessageHeader m = new MessageHeader(bais);
         Map<String,List<String>> messageHeaderMap = m.getHeaders();
-        int available = bais.available();
+        int availableBytes = bais.available();
 
         Http1HeaderParser decoder = new Http1HeaderParser();
         ByteBuffer b = ByteBuffer.wrap(bytes);
         decoder.parse(b);
+        System.out.printf("Http1HeaderParser parsed %d bytes out of %d%n", b.position(), bytes.length);
         Map<String,List<String>> decoderMap1 = decoder.headers().map();
-        assertEquals(available, b.remaining(),
-                     "stream available not equal to remaining");
 
         // assert status-line
         String statusLine1 = messageHeaderMap.get(null).get(0);
@@ -273,6 +343,9 @@
         assertHeadersEqual(messageHeaderMap, decoderMap1,
                           "messageHeaderMap not equal to decoderMap1");
 
+        assertEquals(availableBytes, b.remaining(),
+                String.format("stream available (%d) not equal to remaining (%d)",
+                        availableBytes, b.remaining()));
         // byte at a time
         decoder = new Http1HeaderParser();
         List<ByteBuffer> buffers = IntStream.range(0, bytes.length)
@@ -280,9 +353,10 @@
                 .collect(toList());
         while (decoder.parse(buffers.remove(0)) != true);
         Map<String,List<String>> decoderMap2 = decoder.headers().map();
-        assertEquals(available, buffers.size(),
+        assertEquals(availableBytes, buffers.size(),
                      "stream available not equals to remaining buffers");
         assertEquals(decoderMap1, decoderMap2, "decoder maps not equal");
+
     }
 
     @DataProvider(name = "errors")
--- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -47,6 +47,7 @@
 import jdk.internal.net.http.websocket.WebSocketRequest;
 import org.testng.annotations.Test;
 import static java.net.http.HttpResponse.BodyHandlers.discarding;
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.testng.Assert.assertEquals;
 
 /*
@@ -104,6 +105,7 @@
             // tell the server we have read the initial bytes, so
             // that it makes sure there is something for us to
             // read next in case the initialBytes have already drained the
+
             // channel dry.
             initialReadStall.countDown();
 
@@ -210,11 +212,19 @@
         HttpRequest req = HttpRequest.newBuilder(uri).build();
         // Switch on isWebSocket flag to prevent the connection from
         // being returned to the pool.
-        ((WebSocketRequest)req).isWebSocket(true);
         HttpClient client = HttpClient.newHttpClient();
+        HttpClientImpl clientImpl = ((HttpClientFacade)client).impl;
+        HttpRequestImpl requestImpl = new HttpRequestImpl(req, null);
+        requestImpl.isWebSocket(true);
         try {
-            HttpResponse<?> r = client.send(req, discarding());
-            r.body();
+            MultiExchange<Void> mex = new MultiExchange<>(req,
+                    requestImpl,
+                    clientImpl,
+                    discarding(),
+                    null,
+                    null);
+            HttpResponse<?> r = mex.responseAsync(clientImpl.theExecutor())
+                                   .get(30, SECONDS);
             return ((HttpResponseImpl) r).rawChannel();
         } finally {
            // Need to hold onto the client until the RawChannel is
--- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SelectorTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SelectorTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -30,7 +30,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import org.testng.annotations.Test;
 import jdk.internal.net.http.websocket.RawChannel;
@@ -150,11 +149,11 @@
     static RawChannel getARawChannel(int port) throws Exception {
         URI uri = URI.create("http://localhost:" + port + "/");
         out.println("client connecting to " + uri.toString());
-        HttpRequest req = HttpRequest.newBuilder(uri).build();
+        HttpRequestImpl req = new HttpRequestBuilderImpl(uri).buildForWebSocket();
         // Otherwise HttpClient will think this is an ordinary connection and
         // thus all ordinary procedures apply to it, e.g. it must be put into
         // the cache
-        ((HttpRequestImpl) req).isWebSocket(true);
+        req.isWebSocket(true);
         HttpResponse<?> r = defaultClient().send(req, discarding());
         r.body();
         return ((HttpResponseImpl) r).rawChannel();
--- a/test/jdk/java/util/Collection/MOAT.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/Collection/MOAT.java	Thu Jun 21 09:53:50 2018 -0700
@@ -415,6 +415,7 @@
         equal(c.toString(),"[]");
         equal(c.toArray().length, 0);
         equal(c.toArray(new Object[0]).length, 0);
+        equal(c.toArray(Object[]::new).length, 0);
         check(c.toArray(new Object[]{42})[0] == null);
 
         Object[] a = new Object[1]; a[0] = Boolean.TRUE;
@@ -690,6 +691,13 @@
                 check(a.getClass() == Integer[].class);
             }
 
+            {
+                Integer[] a = c.toArray(Integer[]::new);
+                equal(c.size(), a.length);
+                check(a.getClass() == Integer[].class);
+                check(Arrays.equals(c.toArray(new Integer[0]), a));
+            }
+
             check(c.equals(c));
             if (c instanceof Serializable) {
                 //System.out.printf("Serializing %s%n", c.getClass().getName());
--- a/test/jdk/java/util/List/ListFactories.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/List/ListFactories.java	Thu Jun 21 09:53:50 2018 -0700
@@ -48,7 +48,7 @@
 
 /*
  * @test
- * @bug 8048330
+ * @bug 8048330 8203184
  * @summary Test convenience static factory methods on List.
  * @run testng ListFactories
  */
@@ -330,6 +330,24 @@
         assertSame(copy1, copy2);
     }
 
+    @Test
+    public void copyOfSubList() {
+        List<Integer> orig = List.of(0, 1, 2, 3);
+        List<Integer> sub = orig.subList(0, 3);
+        List<Integer> copy = List.copyOf(sub);
+
+        assertNotSame(sub, copy);
+    }
+
+    @Test
+    public void copyOfSubSubList() {
+        List<Integer> orig = List.of(0, 1, 2, 3);
+        List<Integer> sub = orig.subList(0, 3).subList(0, 2);
+        List<Integer> copy = List.copyOf(sub);
+
+        assertNotSame(sub, copy);
+    }
+
     @Test(expectedExceptions=NullPointerException.class)
     public void copyOfRejectsNullCollection() {
         List<Integer> list = List.copyOf(null);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/Locale/LSRDataTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8204938
+ * @summary Checks the IANA language subtag registry data update
+ *          with Locale.LanguageRange parse method.
+ * @run main LSRDataTest
+ */
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Locale;
+import java.util.Locale.LanguageRange;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.Locale.LanguageRange.MAX_WEIGHT;
+import static java.util.Locale.LanguageRange.MIN_WEIGHT;
+
+public class LSRDataTest {
+
+    private static final char HYPHEN = '-';
+    private static final Map<String, String> singleLangEquivMap = new HashMap<>();
+    private static final Map<String, List<String>> multiLangEquivsMap = new HashMap<>();
+    private static final Map<String, String> regionVariantEquivMap = new HashMap<>();
+
+    // path to the lsr file from the make folder, this test relies on the
+    // relative path to the file in the make folder, considering
+    // test and make will always exist in the same jdk layout
+    private static final String LSR_FILE_PATH = System.getProperty("test.src", ".")
+                + "/../../../../../make/data/lsrdata/language-subtag-registry.txt";
+
+    public static void main(String[] args) throws IOException {
+
+        loadLSRData(Paths.get(LSR_FILE_PATH).toRealPath());
+
+        // checking the tags with weight
+        String ranges = "Accept-Language: aam, adp, aue, bcg, cqu, ema,"
+                + " en-gb-oed, gti, koj, kwq, kxe, lii, lmm, mtm, ngv,"
+                + " oyb, phr, pub, suj, taj;q=0.9, yug;q=0.5, gfx;q=0.4";
+        List<LanguageRange> expected = parse(ranges);
+        List<LanguageRange> actual = LanguageRange.parse(ranges);
+        checkEquality(actual, expected);
+
+        // checking all language ranges
+        ranges = generateLangRanges();
+        expected = parse(ranges);
+        actual = LanguageRange.parse(ranges);
+        checkEquality(actual, expected);
+
+        // checking all region/variant ranges
+        ranges = generateRegionRanges();
+        expected = parse(ranges);
+        actual = LanguageRange.parse(ranges);
+        checkEquality(actual, expected);
+
+    }
+
+    // generate range string containing all equiv language tags
+    private static String generateLangRanges() {
+        return Stream.concat(singleLangEquivMap.keySet().stream(), multiLangEquivsMap
+                .keySet().stream()).collect(Collectors.joining(","));
+    }
+
+    // generate range string containing all equiv region tags
+    private static String generateRegionRanges() {
+        return regionVariantEquivMap.keySet().stream()
+                .map(r -> "en".concat(r)).collect(Collectors.joining(", "));
+    }
+
+    // load LSR data from the file
+    private static void loadLSRData(Path path) throws IOException {
+        String type = null;
+        String tag = null;
+        String preferred;
+
+        for (String line : Files.readAllLines(path, Charset.forName("UTF-8"))) {
+            line = line.toLowerCase(Locale.ROOT);
+            int index = line.indexOf(' ') + 1;
+            if (line.startsWith("type:")) {
+                type = line.substring(index);
+            } else if (line.startsWith("tag:") || line.startsWith("subtag:")) {
+                tag = line.substring(index);
+            } else if (line.startsWith("preferred-value:") && !type.equals("extlang")) {
+                preferred = line.substring(index);
+                processDataAndGenerateMaps(type, tag, preferred);
+            } else if (line.equals("%%")) {
+                type = null;
+                tag = null;
+            }
+        }
+    }
+
+    private static void processDataAndGenerateMaps(String type,
+            String tag,
+            String preferred) {
+        StringBuilder sb;
+        if (type.equals("region") || type.equals("variant")) {
+            if (!regionVariantEquivMap.containsKey(preferred)) {
+                String tPref = HYPHEN + preferred;
+                String tTag = HYPHEN + tag;
+                regionVariantEquivMap.put(tPref, tTag);
+                regionVariantEquivMap.put(tTag, tPref);
+            } else {
+                throw new RuntimeException("New case, need implementation."
+                        + " A region/variant subtag \"" + preferred
+                        + "\" is registered for more than one subtags.");
+            }
+        } else { // language, grandfathered, and redundant
+            if (!singleLangEquivMap.containsKey(preferred)
+                    && !multiLangEquivsMap.containsKey(preferred)) {
+                // new entry add it into single equiv map
+                singleLangEquivMap.put(preferred, tag);
+                singleLangEquivMap.put(tag, preferred);
+            } else if (singleLangEquivMap.containsKey(preferred)
+                    && !multiLangEquivsMap.containsKey(preferred)) {
+                String value = singleLangEquivMap.get(preferred);
+                List<String> subtags = List.of(preferred, value, tag);
+                // remove from single eqiv map before adding to multi equiv
+                singleLangEquivMap.keySet().removeAll(subtags);
+                addEntriesToMultiEquivsMap(subtags);
+            } else if (multiLangEquivsMap.containsKey(preferred)
+                    && !singleLangEquivMap.containsKey(preferred)) {
+                List<String> subtags = multiLangEquivsMap.get(preferred);
+                // should use the order preferred, subtags, tag to keep the
+                // expected order same as the JDK API in multi equivalent maps
+                subtags.add(0, preferred);
+                subtags.add(tag);
+                addEntriesToMultiEquivsMap(subtags);
+            }
+        }
+    }
+
+    // Add entries into the multi equivalent map from the given subtags
+    private static void addEntriesToMultiEquivsMap(List<String> subtags) {
+        // for each subtag within the given subtags, add an entry in multi
+        // equivalent language map with subtag as the key and the value
+        // as the list of all subtags excluding the one which is getting
+        // traversed
+        subtags.forEach(subtag -> multiLangEquivsMap.put(subtag, subtags.stream()
+                .filter(t -> !t.equals(subtag))
+                .collect(Collectors.toList())));
+    }
+
+    private static List<LanguageRange> parse(String ranges) {
+        ranges = ranges.replace(" ", "").toLowerCase(Locale.ROOT);
+        if (ranges.startsWith("accept-language:")) {
+            ranges = ranges.substring(16);
+        }
+        String[] langRanges = ranges.split(",");
+        List<LanguageRange> priorityList = new ArrayList<>(langRanges.length);
+        int numOfRanges = 0;
+        for (String range : langRanges) {
+            int wIndex = range.indexOf(";q=");
+            String tag;
+            double weight = 0.0;
+            if (wIndex == -1) {
+                tag = range;
+                weight = MAX_WEIGHT;
+            } else {
+                tag = range.substring(0, wIndex);
+                try {
+                    weight = Double.parseDouble(range.substring(wIndex + 3));
+                } catch (RuntimeException ex) {
+                    throw new IllegalArgumentException("weight= " + weight + " for"
+                            + " language range \"" + tag + "\", should be"
+                            + " represented as a double");
+                }
+
+                if (weight < MIN_WEIGHT || weight > MAX_WEIGHT) {
+                    throw new IllegalArgumentException("weight=" + weight
+                            + " for language range \"" + tag
+                            + "\", must be between " + MIN_WEIGHT
+                            + " and " + MAX_WEIGHT + ".");
+                }
+            }
+
+            LanguageRange entry = new LanguageRange(tag, weight);
+            if (!priorityList.contains(entry)) {
+
+                int index = numOfRanges;
+                // find the index in the list to add the current range at the
+                // correct index sorted by the descending order of weight
+                for (int i = 0; i < priorityList.size(); i++) {
+                    if (priorityList.get(i).getWeight() < weight) {
+                        index = i;
+                        break;
+                    }
+                }
+                priorityList.add(index, entry);
+                numOfRanges++;
+
+                String equivalent = getEquivalentForRegionAndVariant(tag);
+                if (equivalent != null) {
+                    LanguageRange equivRange = new LanguageRange(equivalent, weight);
+                    if (!priorityList.contains(equivRange)) {
+                        priorityList.add(index + 1, equivRange);
+                        numOfRanges++;
+                    }
+                }
+
+                List<String> equivalents = getEquivalentsForLanguage(tag);
+                if (equivalents != null) {
+                    for (String equiv : equivalents) {
+                        LanguageRange equivRange = new LanguageRange(equiv, weight);
+                        if (!priorityList.contains(equivRange)) {
+                            priorityList.add(index + 1, equivRange);
+                            numOfRanges++;
+                        }
+
+                        equivalent = getEquivalentForRegionAndVariant(equiv);
+                        if (equivalent != null) {
+                            equivRange = new LanguageRange(equivalent, weight);
+                            if (!priorityList.contains(equivRange)) {
+                                priorityList.add(index + 1, equivRange);
+                                numOfRanges++;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return priorityList;
+    }
+
+    /**
+     * A faster alternative approach to String.replaceFirst(), if the given
+     * string is a literal String, not a regex.
+     */
+    private static String replaceFirstSubStringMatch(String range,
+            String substr, String replacement) {
+        int pos = range.indexOf(substr);
+        if (pos == -1) {
+            return range;
+        } else {
+            return range.substring(0, pos) + replacement
+                    + range.substring(pos + substr.length());
+        }
+    }
+
+    private static List<String> getEquivalentsForLanguage(String range) {
+        String r = range;
+
+        while (r.length() > 0) {
+            if (singleLangEquivMap.containsKey(r)) {
+                String equiv = singleLangEquivMap.get(r);
+                // Return immediately for performance if the first matching
+                // subtag is found.
+                return List.of(replaceFirstSubStringMatch(range, r, equiv));
+            } else if (multiLangEquivsMap.containsKey(r)) {
+                List<String> equivs = multiLangEquivsMap.get(r);
+                List<String> result = new ArrayList(equivs.size());
+                for (int i = 0; i < equivs.size(); i++) {
+                    result.add(i, replaceFirstSubStringMatch(range,
+                            r, equivs.get(i)));
+                }
+                return result;
+            }
+
+            // Truncate the last subtag simply.
+            int index = r.lastIndexOf(HYPHEN);
+            if (index == -1) {
+                break;
+            }
+            r = r.substring(0, index);
+        }
+
+        return null;
+    }
+
+    private static String getEquivalentForRegionAndVariant(String range) {
+        int extensionKeyIndex = getExtentionKeyIndex(range);
+
+        for (String subtag : regionVariantEquivMap.keySet()) {
+            int index;
+            if ((index = range.indexOf(subtag)) != -1) {
+                // Check if the matching text is a valid region or variant.
+                if (extensionKeyIndex != Integer.MIN_VALUE
+                        && index > extensionKeyIndex) {
+                    continue;
+                }
+
+                int len = index + subtag.length();
+                if (range.length() == len || range.charAt(len) == HYPHEN) {
+                    return replaceFirstSubStringMatch(range, subtag,
+                            regionVariantEquivMap.get(subtag));
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private static int getExtentionKeyIndex(String s) {
+        char[] c = s.toCharArray();
+        int index = Integer.MIN_VALUE;
+        for (int i = 1; i < c.length; i++) {
+            if (c[i] == HYPHEN) {
+                if (i - index == 2) {
+                    return index;
+                } else {
+                    index = i;
+                }
+            }
+        }
+        return Integer.MIN_VALUE;
+    }
+
+    private static void checkEquality(List<LanguageRange> expected,
+            List<LanguageRange> actual) {
+
+        int expectedSize = expected.size();
+        int actualSize = actual.size();
+
+        if (expectedSize != actualSize) {
+            throw new RuntimeException("[FAILED: Size of the priority list"
+                    + " does not match, Expected size=" + expectedSize + "]");
+        } else {
+            for (int i = 0; i < expectedSize; i++) {
+                LanguageRange lr1 = expected.get(i);
+                LanguageRange lr2 = actual.get(i);
+
+                if (!lr1.getRange().equals(lr2.getRange())
+                        || lr1.getWeight() != lr2.getWeight()) {
+                    throw new RuntimeException("[FAILED: Ranges at index "
+                            + i + " do not match Expected: range=" + lr1.getRange()
+                            + ", weight=" + lr1.getWeight() + ", Actual: range="
+                            + lr2.getRange() + ", weight=" + lr2.getWeight() + "]");
+                }
+            }
+        }
+    }
+}
--- a/test/jdk/java/util/concurrent/tck/ArrayDequeTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/ArrayDequeTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -772,7 +772,7 @@
         ArrayDeque l = new ArrayDeque();
         l.add(new Object());
         try {
-            l.toArray(null);
+            l.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
--- a/test/jdk/java/util/concurrent/tck/BlockingQueueTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/BlockingQueueTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -161,7 +161,7 @@
     public void testToArray_NullArray() {
         final Collection q = emptyCollection();
         try {
-            q.toArray(null);
+            q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
--- a/test/jdk/java/util/concurrent/tck/Collection8Test.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/Collection8Test.java	Thu Jun 21 09:53:50 2018 -0700
@@ -209,7 +209,7 @@
             () -> c.iterator().forEachRemaining(null),
             () -> c.spliterator().forEachRemaining(null),
             () -> c.spliterator().tryAdvance(null),
-            () -> c.toArray(null));
+            () -> c.toArray((Object[])null));
 
         if (!impl.permitsNulls()) {
             assertThrows(
--- a/test/jdk/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -712,7 +712,7 @@
     public void testToArray_NullArg() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
         try {
-            q.toArray(null);
+            q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
--- a/test/jdk/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -439,7 +439,7 @@
     public void testToArray_NullArg() {
         ConcurrentLinkedQueue q = populatedQueue(SIZE);
         try {
-            q.toArray(null);
+            q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
--- a/test/jdk/java/util/concurrent/tck/LinkedListTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/LinkedListTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -409,7 +409,7 @@
         LinkedList l = new LinkedList();
         l.add(new Object());
         try {
-            l.toArray(null);
+            l.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
--- a/test/jdk/java/util/concurrent/tck/SynchronousQueueTest.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/java/util/concurrent/tck/SynchronousQueueTest.java	Thu Jun 21 09:53:50 2018 -0700
@@ -464,7 +464,7 @@
     public void testToArray_null(boolean fair) {
         final SynchronousQueue q = new SynchronousQueue(fair);
         try {
-            Object[] o = q.toArray(null);
+            Object[] o = q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
--- a/test/jdk/jdk/jfr/event/runtime/TestThreadCpuTimeEvent.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/jdk/jfr/event/runtime/TestThreadCpuTimeEvent.java	Thu Jun 21 09:53:50 2018 -0700
@@ -160,26 +160,48 @@
         return totalTime;
     }
 
-    static void testSimple() throws Throwable {
-        Recording recording = new Recording();
+    static List<RecordedEvent> generateEvents(int minimumEventCount, CyclicBarrier barrier) throws Throwable {
+        int retryCount = 0;
+
+        while (true) {
+            Recording recording = new Recording();
+
+            // Default period is once per chunk
+            recording.enable(EventNames.ThreadCPULoad).withPeriod(Duration.ofMillis(eventPeriodMillis));
+            recording.start();
+
+            // Run a single pass
+            barrier.await();
+            barrier.await();
+
+            recording.stop();
+            List<RecordedEvent> events = Events.fromRecording(recording);
 
-        // Default period is once per chunk
-        recording.enable(EventNames.ThreadCPULoad).withPeriod(Duration.ofMillis(eventPeriodMillis));
-        recording.start();
+            long numEvents = events.stream()
+                    .filter(e -> e.getThread().getJavaName().equals(cpuConsumerThreadName))
+                    .count();
 
+            // If the JFR periodicals thread is really starved, we may not get enough events.
+            // In that case, we simply retry the operation.
+            if (numEvents < minimumEventCount) {
+                System.out.println("Not enough events recorded, trying again...");
+                if (retryCount++ > 10) {
+                    Asserts.fail("Retry count exceeded");
+                    throw new RuntimeException();
+                }
+            } else {
+                return events;
+            }
+        }
+    }
+
+    static void testSimple() throws Throwable {
         Duration testRunTime = Duration.ofMillis(eventPeriodMillis * cpuConsumerRunFactor);
         CyclicBarrier barrier = new CyclicBarrier(2);
         CpuConsumingThread thread = new CpuConsumingThread(testRunTime, barrier);
+        thread.start();
 
-        // Run a single pass
-        thread.start();
-        barrier.await();
-        barrier.await();
-
-        recording.stop();
-        List<RecordedEvent> events = Events.fromRecording(recording);
-
-        Events.hasEvents(events);
+        List<RecordedEvent> events = generateEvents(1, barrier);
         verifyPerThreadInvariant(events, cpuConsumerThreadName);
 
         thread.interrupt();
@@ -187,23 +209,12 @@
     }
 
     static void testCompareWithMXBean() throws Throwable {
-        Recording recording = new Recording();
-
-        recording.enable(EventNames.ThreadCPULoad).withPeriod(Duration.ofMillis(eventPeriodMillis));
-        recording.start();
-
         Duration testRunTime = Duration.ofMillis(eventPeriodMillis * cpuConsumerRunFactor);
         CyclicBarrier barrier = new CyclicBarrier(2);
         CpuConsumingThread thread = new CpuConsumingThread(testRunTime, barrier);
+        thread.start();
 
-        // Run a single pass
-        thread.start();
-        barrier.await();
-        barrier.await();
-
-        recording.stop();
-        List<RecordedEvent> beforeEvents = Events.fromRecording(recording);
-
+        List<RecordedEvent> beforeEvents = generateEvents(2, barrier);
         verifyPerThreadInvariant(beforeEvents, cpuConsumerThreadName);
 
         // Run a second single pass
--- a/test/jdk/jdk/jfr/jvm/TestLogOutput.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/jdk/jfr/jvm/TestLogOutput.java	Thu Jun 21 09:53:50 2018 -0700
@@ -42,7 +42,7 @@
     public static void main(String[] args) throws Exception {
         final String fileName = "jfr_trace.txt";
         final List<String>findWhat = new ArrayList<>();
-        findWhat.add("Starting up Jfr startup recording");
+        findWhat.add("Starting a recording");
         findWhat.add("Flight Recorder initialized");
         boolean passed = false;
         List<String> matches = new ArrayList<String>(findWhat);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/jfr/startupargs/TestMultipleStartupRecordings.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jfr.startupargs;
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @key jfr
+ *
+ * @library /test/lib
+ *
+ * @run main jdk.jfr.startupargs.TestMultipleStartupRecordings
+ */
+public class TestMultipleStartupRecordings {
+
+    private static final String START_FLIGHT_RECORDING = "-XX:StartFlightRecording";
+    private static final String FLIGHT_RECORDER_OPTIONS = "-XX:FlightRecorderOptions";
+
+    static class MainClass {
+        public static void main(String[] args) {
+        }
+    }
+
+    private static void test(ProcessBuilder pb, String... expectedOutputs) throws Exception {
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        for (String s : expectedOutputs) {
+            output.shouldContain(s);
+        }
+    }
+
+    private static void launchUnary(String options) throws Exception {
+        String recording1 = START_FLIGHT_RECORDING + (options != null ? options : "");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, recording1, MainClass.class.getName());
+        test(pb, "Started recording 1");
+    }
+
+    private static void launchBinary(String options1, String options2) throws Exception {
+        String recording1 = START_FLIGHT_RECORDING + (options1 != null ? options1 : "");
+        String recording2 = START_FLIGHT_RECORDING + (options2 != null ? options2 : "");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, recording1, recording2, MainClass.class.getName());
+        test(pb, "Started recording 1", "Started recording 2");
+    }
+
+    private static void launchTernary(String options1, String options2, String options3) throws Exception {
+        String recording1 = START_FLIGHT_RECORDING + (options1 != null ? options1 : "");
+        String recording2 = START_FLIGHT_RECORDING + (options2 != null ? options2 : "");
+        String recording3 = START_FLIGHT_RECORDING + (options3 != null ? options3 : "");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, recording1, recording2, recording3, MainClass.class.getName());
+        test(pb, "Started recording 1", "Started recording 2", "Started recording 3");
+    }
+
+    private static void testDefault() throws Exception {
+        System.out.println("testDefault");
+        launchUnary(null);
+        launchBinary(null, null);
+        launchTernary(null, null, null);
+    }
+
+    private static void testColonDelimited() throws Exception {
+        launchBinary(":name=myrecording1,filename=myrecording1.jfr", ":filename=myrecording2.jfr,name=myrecording2");
+    }
+
+    private static void testMixed() throws Exception {
+        launchTernary(":maxage=2d,maxsize=5GB", "=dumponexit=true,maxage=10m,", ":name=myrecording,maxage=10m,filename=myrecording.jfr,disk=false");
+    }
+
+    private static void testWithFlightRecorderOptions() throws Exception {
+        System.out.println("testWithFlightRecorderOptions");
+        String flightRecorderOptions = FLIGHT_RECORDER_OPTIONS + "=maxchunksize=8m";
+        String recording1 = START_FLIGHT_RECORDING + "=filename=recording1.jfr";
+        String recording2 = START_FLIGHT_RECORDING + "=name=myrecording,filename=recording2.jfr";
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, flightRecorderOptions, recording1, recording2, MainClass.class.getName());
+        test(pb, "Started recording 1", "Started recording 2");
+    }
+
+    public static void main(String[] args) throws Exception {
+        testDefault();
+        testColonDelimited();
+        testMixed();
+        testWithFlightRecorderOptions();
+    }
+}
Binary file test/jdk/lib/testlibrary/jdk/testlibrary/testkeys has changed
--- a/test/jdk/sun/tools/jstatd/JstatGCUtilParser.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/jdk/sun/tools/jstatd/JstatGCUtilParser.java	Thu Jun 21 09:53:50 2018 -0700
@@ -25,16 +25,14 @@
 
 import jdk.testlibrary.Utils;
 import static jdk.testlibrary.Asserts.*;
+import java.text.NumberFormat;
 
 /**
  * The helper class for parsing following output from command 'jstat -gcutil':
  *
- *  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
- *  100.00   0.00  64.68  13.17  73.39  33.46      2    0.003     1    0.156    0.158
- *  100.00   0.00  76.54  13.17  73.39  33.46      2    0.003     1    0.156    0.158
- *  100.00   0.00  83.49  13.17  73.39  33.46      2    0.003     1    0.156    0.158
- *  100.00   0.00  84.53  13.17  73.39  33.46      2    0.003     1    0.156    0.158
- *  100.00   0.00  85.57  13.17  73.39  33.46      2    0.003     1    0.156    0.158
+ *  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT
+ *  0.00   0.00  86.67   0.00   -      -      0      0.000     0    0.000     0    0.000    0.000
+ *  0.00   0.00  86.67   0.00   -      -      0      0.000     0    0.000     0    0.000    0.000
  *
  *  It will be verified that numerical values have defined types and are reasonable,
  *  for example percentage should fit within 0-100 interval.
@@ -50,7 +48,7 @@
         S1(GcStatisticsType.PERCENTAGE),
         E(GcStatisticsType.PERCENTAGE),
         O(GcStatisticsType.PERCENTAGE),
-        M(GcStatisticsType.PERCENTAGE),
+        M(GcStatisticsType.PERCENTAGE_OR_DASH),
         CCS(GcStatisticsType.PERCENTAGE_OR_DASH),
         YGC(GcStatisticsType.INTEGER),
         YGCT(GcStatisticsType.DOUBLE),
@@ -97,18 +95,18 @@
                 GcStatisticsType type = values()[i].getType();
                 String value = valueArray[i].trim();
                 if (type.equals(GcStatisticsType.INTEGER)) {
-                    Integer.parseInt(value);
+                    NumberFormat.getInstance().parse(value).intValue();
                     break;
                 }
                 if (type.equals(GcStatisticsType.DOUBLE)) {
-                    Double.parseDouble(value);
+                    NumberFormat.getInstance().parse(value).doubleValue();
                     break;
                 }
                 if (type.equals(GcStatisticsType.PERCENTAGE_OR_DASH) &&
                         value.equals("-")) {
                     break;
                 }
-                double percentage = Double.parseDouble(value);
+                double percentage = NumberFormat.getInstance().parse(value).doubleValue();
                 assertTrue(0 <= percentage && percentage <= 100,
                         "Not a percentage: " + value);
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testEnumConstructor/TestEnumConstructor.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8202624
+ * @summary javadoc generates references to enum constructors, which are not documented
+ * @library /tools/lib ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester
+ * @run main TestEnumConstructor
+ */
+
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.ToolBox;
+
+public class TestEnumConstructor extends JavadocTester {
+
+    final ToolBox tb;
+
+    public static void main(String... args) throws Exception {
+        TestEnumConstructor tester = new TestEnumConstructor();
+        tester.runTests(m -> new Object[]{Paths.get(m.getName())});
+    }
+
+    TestEnumConstructor() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    void test1(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        createEnum(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-private",
+                "-sourcepath", srcDir.toString(),
+                "pkg");
+
+        checkExit(Exit.OK);
+        checkOrder("pkg/TestEnum.html",
+                "Constructor Summary",
+                "Modifier", "Constructor",
+                "private", "<a href=\"#%3Cinit%3E(int)\">TestEnum</a></span>&#8203;(int&nbsp;val)");
+        checkOutput("index-all.html", true,
+                "<a href=\"pkg/TestEnum.html#%3Cinit%3E(int)\">TestEnum(int)</a>");
+
+    }
+
+    @Test
+    void test2(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        createEnum(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-package",
+                "-sourcepath", srcDir.toString(),
+                "pkg");
+
+        checkExit(Exit.OK);
+        checkOutput("pkg/TestEnum.html", false, "Constructor Summary");
+        checkOutput("index-all.html", false,
+                "<a href=\"pkg/TestEnum.html#%3Cinit%3E(int)\">TestEnum(int)</a>");
+    }
+
+    void createEnum(Path srcDir) throws Exception {
+        tb.writeJavaFiles(srcDir,
+                "package pkg;\n"
+                + "public enum TestEnum{\n"
+                + "CONST1(100),CONST2(50),CONST3(10);\n"
+                + "private int val;\n"
+                + "TestEnum(int val){this.val=val;}\n"
+                + "}");
+    }
+}
--- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Thu Jun 21 09:53:50 2018 -0700
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 8072945 8081854 8141492 8148985 8150188 4649116 8173707 8151743 8169819 8183037 8182765 8196202
+ *      8202624
  * @summary Test the version of HTML generated by the javadoc tool.
  * @author bpatel
  * @library ../lib
@@ -41,7 +42,6 @@
 
     @Test
     void test1() {
-        setAutomaticCheckLinks(false); // @ignore JDK-8202624
         javadoc("-d", "out-1",
                 "-private",
                 "-linksource",
@@ -49,7 +49,6 @@
                 "-sourcepath", testSrc,
                 "-use",
                 "pkg", "pkg1", "pkg2", "pkg3");
-        setAutomaticCheckLinks(true); // @ignore JDK-8202624
         checkExit(Exit.OK);
 
         html5Output();
@@ -58,7 +57,6 @@
 
     @Test
     void test2() {
-        setAutomaticCheckLinks(false); // @ignore JDK-8202624
         javadoc("-d", "out-2",
                 "-html4",
                 "-private",
@@ -67,7 +65,6 @@
                 "-sourcepath", testSrc,
                 "-use",
                 "pkg", "pkg1", "pkg2", "pkg3");
-        setAutomaticCheckLinks(true); // @ignore JDK-8202624
         checkExit(Exit.OK);
 
         html4Output();
@@ -76,7 +73,6 @@
 
     @Test
     void test3() {
-        setAutomaticCheckLinks(false); // @ignore JDK-8202624
         javadoc("-d", "out-3",
                 "-html4",
                 "-private",
@@ -85,7 +81,6 @@
                 "-sourcepath", testSrc,
                 "-use",
                 "pkg", "pkg1", "pkg2", "pkg3");
-        setAutomaticCheckLinks(true); // @ignore JDK-8202624
         checkExit(Exit.OK);
 
         html4Output();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/LambdaReturnUnboxing.java	Thu Jun 21 09:53:50 2018 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8203338
+ * @summary Unboxing in return from lambda miscompiled to throw ClassCastException
+ */
+
+import java.util.*;
+
+public class LambdaReturnUnboxing {
+    interface C {
+        Character get(Character c);
+    }
+    static <T> T c(T t, int... i) { return t; }
+
+    static Character d() { return List.of('d').get(0); }
+
+    public static void main(String... args) {
+        List.of('x', 'y').stream().max((a, b) -> List.of(a).get(0));
+        List.of('x', 'y').stream().max((a, b) -> { return List.of(a).get(0); });
+
+        C c = LambdaReturnUnboxing::c;
+        int i = c.get('c');
+
+        i = d();
+    }
+}
--- a/test/langtools/tools/javac/lvti/ParserTest.out	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/langtools/tools/javac/lvti/ParserTest.out	Thu Jun 21 09:53:50 2018 -0700
@@ -1,9 +1,9 @@
-ParserTest.java:14:18: compiler.err.var.not.allowed: var
-ParserTest.java:16:22: compiler.err.var.not.allowed: var
-ParserTest.java:20:19: compiler.err.var.not.allowed: var
-ParserTest.java:24:14: compiler.err.var.not.allowed: var
-ParserTest.java:28:20: compiler.err.var.not.allowed: var
-ParserTest.java:36:27: compiler.err.var.not.allowed: var
+ParserTest.java:14:18: compiler.err.var.not.allowed
+ParserTest.java:16:22: compiler.err.var.not.allowed
+ParserTest.java:20:19: compiler.err.var.not.allowed
+ParserTest.java:24:14: compiler.err.var.not.allowed
+ParserTest.java:28:20: compiler.err.var.not.allowed
+ParserTest.java:36:27: compiler.err.var.not.allowed
 ParserTest.java:38:5: compiler.err.var.not.allowed.here
 ParserTest.java:41:15: compiler.err.var.not.allowed.array
 ParserTest.java:42:13: compiler.err.var.not.allowed.array
@@ -11,7 +11,7 @@
 ParserTest.java:44:13: compiler.err.var.not.allowed.array
 ParserTest.java:45:15: compiler.err.var.not.allowed.array
 ParserTest.java:46:13: compiler.err.var.not.allowed.array
-ParserTest.java:49:13: compiler.err.var.not.allowed.compound
+ParserTest.java:49:24: compiler.err.var.not.allowed.compound
 ParserTest.java:54:5: compiler.err.var.not.allowed.here
 ParserTest.java:58:16: compiler.err.var.not.allowed.here
 ParserTest.java:59:14: compiler.err.var.not.allowed.here
--- a/test/langtools/tools/javac/lvti/ParserTest9.out	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/langtools/tools/javac/lvti/ParserTest9.out	Thu Jun 21 09:53:50 2018 -0700
@@ -4,4 +4,28 @@
 ParserTest.java:24:14: compiler.warn.var.not.allowed
 ParserTest.java:28:20: compiler.warn.var.not.allowed
 ParserTest.java:36:27: compiler.warn.var.not.allowed
-6 warnings
+ParserTest.java:38:5: compiler.warn.var.not.allowed
+ParserTest.java:41:15: compiler.warn.var.not.allowed
+ParserTest.java:42:13: compiler.warn.var.not.allowed
+ParserTest.java:43:17: compiler.warn.var.not.allowed
+ParserTest.java:44:13: compiler.warn.var.not.allowed
+ParserTest.java:45:15: compiler.warn.var.not.allowed
+ParserTest.java:46:13: compiler.warn.var.not.allowed
+ParserTest.java:47:23: compiler.warn.var.not.allowed
+ParserTest.java:48:13: compiler.warn.var.not.allowed
+ParserTest.java:49:13: compiler.warn.var.not.allowed
+ParserTest.java:50:23: compiler.warn.var.not.allowed
+ParserTest.java:51:23: compiler.warn.var.not.allowed
+ParserTest.java:54:5: compiler.warn.var.not.allowed
+ParserTest.java:58:16: compiler.warn.var.not.allowed
+ParserTest.java:59:14: compiler.warn.var.not.allowed
+ParserTest.java:60:24: compiler.warn.var.not.allowed
+ParserTest.java:61:22: compiler.warn.var.not.allowed
+ParserTest.java:63:22: compiler.warn.var.not.allowed
+ParserTest.java:63:40: compiler.warn.var.not.allowed
+ParserTest.java:64:18: compiler.warn.var.not.allowed
+ParserTest.java:68:35: compiler.warn.var.not.allowed
+ParserTest.java:69:22: compiler.warn.var.not.allowed
+ParserTest.java:73:24: compiler.warn.var.not.allowed
+ParserTest.java:74:18: compiler.warn.var.not.allowed
+30 warnings
--- a/test/langtools/tools/javac/lvti/badTypeReference/BadTypeReference.out	Wed Jun 20 11:12:48 2018 -0700
+++ b/test/langtools/tools/javac/lvti/badTypeReference/BadTypeReference.out	Thu Jun 21 09:53:50 2018 -0700
@@ -1,3 +1,3 @@
-BadTypeReference.java:39:9: compiler.err.illegal.ref.to.var.type: var
-BadTypeReference.java:40:21: compiler.err.illegal.ref.to.var.type: var
+BadTypeReference.java:39:9: compiler.err.illegal.ref.to.var.type
+BadTypeReference.java:40:21: compiler.err.illegal.ref.to.var.type
 2 errors