Merge metal-prototype-branch
authoraghaisas
Mon, 08 Jul 2019 16:04:25 +0530
branchmetal-prototype-branch
changeset 57457 95604ec1205d
parent 57441 ee34e24af607 (current diff)
parent 55607 5919b273def6 (diff)
child 57458 3a7c29ba6b1c
Merge
src/hotspot/share/gc/z/zOopClosures.cpp
src/hotspot/share/jfr/leakprofiler/emitEventOperation.cpp
src/hotspot/share/jfr/leakprofiler/emitEventOperation.hpp
--- a/.hgtags	Fri Jun 28 15:22:18 2019 +0530
+++ b/.hgtags	Mon Jul 08 16:04:25 2019 +0530
@@ -569,3 +569,5 @@
 43627549a488b7d0b4df8fad436e36233df89877 jdk-14+2
 b7f68ddec66f996ae3aad03291d129ca9f02482d jdk-13+27
 e64383344f144217c36196c3c8a2df8f588a2af3 jdk-14+3
+1e95931e7d8fa7e3899340a9c7cb28dbea50c10c jdk-13+28
+19d0b382f0869f72d4381b54fa129f1c74b6e766 jdk-14+4
--- a/make/autoconf/flags-cflags.m4	Fri Jun 28 15:22:18 2019 +0530
+++ b/make/autoconf/flags-cflags.m4	Mon Jul 08 16:04:25 2019 +0530
@@ -576,8 +576,9 @@
 
   elif test "x$TOOLCHAIN_TYPE" = xxlc; then
     # Suggested additions: -qsrcmsg to get improved error reporting
-    TOOLCHAIN_CFLAGS_JDK="-qchars=signed -qfullpath -qsaveopt -qstackprotect"  # add on both CFLAGS
-    TOOLCHAIN_CFLAGS_JVM="-qtune=balanced \
+    # set -qtbtable=full for a better traceback table/better stacks in hs_err when xlc16 is used
+    TOOLCHAIN_CFLAGS_JDK="-qtbtable=full -qchars=signed -qfullpath -qsaveopt -qstackprotect"  # add on both CFLAGS
+    TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced \
         -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \
         -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno -qstackprotect"
   elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractCommandNode.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractCommandNode.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,8 +30,8 @@
 class AbstractCommandNode extends AbstractNamedNode {
 
     void document(PrintWriter writer) {
-        writer.println("<h5 id=\"" + context.whereC + "\">" + name +
-                       " Command (" + nameNode.value() + ")</h5>");
+        writer.println("<h3 id=\"" + context.whereC + "\">" + name +
+                       " Command (" + nameNode.value() + ")</h3>");
         writer.println(comment());
         writer.println("<dl>");
         for (Node node : components) {
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractNamedNode.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractNamedNode.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,8 +62,8 @@
     }
 
     void document(PrintWriter writer) {
-        writer.println("<h4 id=\"" + name + "\">" + name +
-                       " Command Set</h4>");
+        writer.println("<h2 id=\"" + name + "\">" + name +
+                       " Command Set</h2>");
         for (Node node : components) {
             node.document(writer);
         }
--- a/make/jdk/src/classes/build/tools/jdwpgen/CommandSetNode.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/make/jdk/src/classes/build/tools/jdwpgen/CommandSetNode.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -38,9 +38,9 @@
     }
 
     void document(PrintWriter writer) {
-        writer.println("<h4 id=\"" + context.whereC + "\">" + name +
+        writer.println("<h2 id=\"" + context.whereC + "\">" + name +
                        " Command Set (" +
-                       nameNode.value() + ")</h4>");
+                       nameNode.value() + ")</h2>");
         writer.println(comment());
         for (Node node : components) {
             node.document(writer);
--- a/make/jdk/src/classes/build/tools/jdwpgen/ConstantSetNode.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/make/jdk/src/classes/build/tools/jdwpgen/ConstantSetNode.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -54,8 +54,8 @@
     }
 
     void document(PrintWriter writer) {
-        writer.println("<h4 id=\"" + context.whereC + "\">" + name +
-                       " Constants</h4>");
+        writer.println("<h2 id=\"" + context.whereC + "\">" + name +
+                       " Constants</h2>");
         writer.println(comment());
         writer.println("<table><tr>");
         writer.println("<th style=\"width: 20%\"><th style=\"width: 5%\"><th style=\"width:  65%\">");
--- a/make/jdk/src/classes/build/tools/jdwpgen/RootNode.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/make/jdk/src/classes/build/tools/jdwpgen/RootNode.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,11 +52,16 @@
         writer.println("</style>");
         writer.println("</head>");
         writer.println("<body>");
-        writer.println("<ul role=\"navigation\">");
+        writer.println("<div class=\"centered\" role=\"banner\">");
+        writer.println("<h1 id=\"Protocol Details\">Java Debug Wire Protocol Details</h1>");
+        writer.println("</div>");
+        writer.println("<nav>");
+        writer.println("<ul>");
         for (Node node : components) {
             node.documentIndex(writer);
         }
         writer.println("</ul>");
+        writer.println("</nav>");
         writer.println("<div role=\"main\">");
         for (Node node : components) {
             node.document(writer);
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Mon Jul 08 16:04:25 2019 +0530
@@ -1761,6 +1761,17 @@
   // branch if we need to invalidate the method later
   __ nop();
 
+  if (C->clinit_barrier_on_entry()) {
+    assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
+
+    Label L_skip_barrier;
+
+    __ mov_metadata(rscratch2, C->method()->holder()->constant_encoding());
+    __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
+    __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+    __ bind(L_skip_barrier);
+  }
+  
   int bangsize = C->bang_size_in_bytes();
   if (C->need_stack_bang(bangsize) && UseStackBanging)
     __ generate_stack_overflow_check(bangsize);
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -317,7 +317,15 @@
 }
 
 void LIR_Assembler::clinit_barrier(ciMethod* method) {
-  ShouldNotReachHere(); // not implemented
+  assert(VM_Version::supports_fast_class_init_checks(), "sanity");
+  assert(!method->holder()->is_not_initialized(), "initialization should have been started");
+
+  Label L_skip_barrier;
+
+  __ mov_metadata(rscratch2, method->holder()->constant_encoding());
+  __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier /*L_fast_path*/);
+  __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+  __ bind(L_skip_barrier);
 }
 
 void LIR_Assembler::jobject2reg(jobject o, Register reg) {
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -331,11 +331,6 @@
 
 
 void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
-  // If we have to make this method not-entrant we'll overwrite its
-  // first instruction with a jump.  For this action to be legal we
-  // must ensure that this first instruction is a B, BL, NOP, BKPT,
-  // SVC, HVC, or SMC.  Make it a NOP.
-  nop();
   assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
   // Make sure there is enough stack space for this method's activation.
   // Note that we do this before doing an enter().
@@ -355,6 +350,11 @@
 
 
 void C1_MacroAssembler::verified_entry() {
+  // If we have to make this method not-entrant we'll overwrite its
+  // first instruction with a jump.  For this action to be legal we
+  // must ensure that this first instruction is a B, BL, NOP, BKPT,
+  // SVC, HVC, or SMC.  Make it a NOP.
+  nop();
 }
 
 void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) {
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -47,7 +47,7 @@
                                                        Register src, Register dst, Register count, RegSet saved_regs) {
   if (is_oop) {
     bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
-    if (ShenandoahSATBBarrier && !dest_uninitialized && !ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc()) {
+    if (ShenandoahSATBBarrier && !dest_uninitialized) {
 
       Label done;
 
--- a/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/z/z_aarch64.ad	Mon Jul 08 16:04:25 2019 +0530
@@ -61,7 +61,7 @@
 //
 // Execute ZGC load barrier (strong) slow path
 //
-instruct loadBarrierSlowReg(iRegP dst, memory mem, rFlagsReg cr,
+instruct loadBarrierSlowReg(iRegP dst, memory src, rFlagsReg cr,
     vRegD_V0 v0, vRegD_V1 v1, vRegD_V2 v2, vRegD_V3 v3, vRegD_V4 v4,
     vRegD_V5 v5, vRegD_V6 v6, vRegD_V7 v7, vRegD_V8 v8, vRegD_V9 v9,
     vRegD_V10 v10, vRegD_V11 v11, vRegD_V12 v12, vRegD_V13 v13, vRegD_V14 v14,
@@ -69,20 +69,22 @@
     vRegD_V20 v20, vRegD_V21 v21, vRegD_V22 v22, vRegD_V23 v23, vRegD_V24 v24,
     vRegD_V25 v25, vRegD_V26 v26, vRegD_V27 v27, vRegD_V28 v28, vRegD_V29 v29,
     vRegD_V30 v30, vRegD_V31 v31) %{
-  match(Set dst (LoadBarrierSlowReg mem));
+  match(Set dst (LoadBarrierSlowReg src dst));
   predicate(!n->as_LoadBarrierSlowReg()->is_weak());
 
-  effect(DEF dst, KILL cr,
+  effect(KILL cr,
      KILL v0, KILL v1, KILL v2, KILL v3, KILL v4, KILL v5, KILL v6, KILL v7,
      KILL v8, KILL v9, KILL v10, KILL v11, KILL v12, KILL v13, KILL v14,
      KILL v15, KILL v16, KILL v17, KILL v18, KILL v19, KILL v20, KILL v21,
      KILL v22, KILL v23, KILL v24, KILL v25, KILL v26, KILL v27, KILL v28,
      KILL v29, KILL v30, KILL v31);
 
-  format %{"LoadBarrierSlowReg $dst, $mem" %}
+  format %{ "lea $dst, $src\n\t"
+            "call #ZLoadBarrierSlowPath" %}
+
   ins_encode %{
-    z_load_barrier_slow_reg(_masm, $dst$$Register, $mem$$base$$Register,
-                            $mem$$index, $mem$$scale, $mem$$disp, false);
+    z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$base$$Register,
+                            $src$$index, $src$$scale, $src$$disp, false);
   %}
   ins_pipe(pipe_slow);
 %}
@@ -90,7 +92,7 @@
 //
 // Execute ZGC load barrier (weak) slow path
 //
-instruct loadBarrierWeakSlowReg(iRegP dst, memory mem, rFlagsReg cr,
+instruct loadBarrierWeakSlowReg(iRegP dst, memory src, rFlagsReg cr,
     vRegD_V0 v0, vRegD_V1 v1, vRegD_V2 v2, vRegD_V3 v3, vRegD_V4 v4,
     vRegD_V5 v5, vRegD_V6 v6, vRegD_V7 v7, vRegD_V8 v8, vRegD_V9 v9,
     vRegD_V10 v10, vRegD_V11 v11, vRegD_V12 v12, vRegD_V13 v13, vRegD_V14 v14,
@@ -98,20 +100,22 @@
     vRegD_V20 v20, vRegD_V21 v21, vRegD_V22 v22, vRegD_V23 v23, vRegD_V24 v24,
     vRegD_V25 v25, vRegD_V26 v26, vRegD_V27 v27, vRegD_V28 v28, vRegD_V29 v29,
     vRegD_V30 v30, vRegD_V31 v31) %{
-  match(Set dst (LoadBarrierSlowReg mem));
+  match(Set dst (LoadBarrierSlowReg src dst));
   predicate(n->as_LoadBarrierSlowReg()->is_weak());
 
-  effect(DEF dst, KILL cr,
+  effect(KILL cr,
      KILL v0, KILL v1, KILL v2, KILL v3, KILL v4, KILL v5, KILL v6, KILL v7,
      KILL v8, KILL v9, KILL v10, KILL v11, KILL v12, KILL v13, KILL v14,
      KILL v15, KILL v16, KILL v17, KILL v18, KILL v19, KILL v20, KILL v21,
      KILL v22, KILL v23, KILL v24, KILL v25, KILL v26, KILL v27, KILL v28,
      KILL v29, KILL v30, KILL v31);
 
-  format %{"LoadBarrierWeakSlowReg $dst, $mem" %}
+  format %{ "lea $dst, $src\n\t"
+            "call #ZLoadBarrierSlowPath" %}
+
   ins_encode %{
-    z_load_barrier_slow_reg(_masm, $dst$$Register, $mem$$base$$Register,
-                            $mem$$index, $mem$$scale, $mem$$disp, true);
+    z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$base$$Register,
+                            $src$$index, $src$$scale, $src$$disp, true);
   %}
   ins_pipe(pipe_slow);
 %}
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -288,6 +288,18 @@
   ldr(klass, Address(klass, Array<Klass*>::base_offset_in_bytes()));
 }
 
+void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no,
+                                                              Register method,
+                                                              Register cache) {
+  const int method_offset = in_bytes(
+    ConstantPoolCache::base_offset() +
+      ((byte_no == TemplateTable::f2_byte)
+       ? ConstantPoolCacheEntry::f2_offset()
+       : ConstantPoolCacheEntry::f1_offset()));
+
+  ldr(method, Address(cache, method_offset)); // get f1 Method*
+}
+
 // Generate a subtype check: branch to ok_is_subtype if sub_klass is a
 // subtype of super_klass.
 //
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -124,6 +124,8 @@
   // load cpool->resolved_klass_at(index);
   void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp);
 
+  void load_resolved_method_at_index(int byte_no, Register method, Register cache);
+
   void pop_ptr(Register r = r0);
   void pop_i(Register r = r0);
   void pop_l(Register r = r0);
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1307,6 +1307,35 @@
   bind(L_fallthrough);
 }
 
+void MacroAssembler::clinit_barrier(Register klass, Register scratch, Label* L_fast_path, Label* L_slow_path) {
+  assert(L_fast_path != NULL || L_slow_path != NULL, "at least one is required");
+  assert_different_registers(klass, rthread, scratch);
+
+  Label L_fallthrough, L_tmp;
+  if (L_fast_path == NULL) {
+    L_fast_path = &L_fallthrough;
+  } else if (L_slow_path == NULL) {
+    L_slow_path = &L_fallthrough;
+  }
+  // Fast path check: class is fully initialized
+  ldrb(scratch, Address(klass, InstanceKlass::init_state_offset()));
+  subs(zr, scratch, InstanceKlass::fully_initialized);
+  br(Assembler::EQ, *L_fast_path);
+
+  // Fast path check: current thread is initializer thread
+  ldr(scratch, Address(klass, InstanceKlass::init_thread_offset()));
+  cmp(rthread, scratch);
+
+  if (L_slow_path == &L_fallthrough) {
+    br(Assembler::EQ, *L_fast_path);
+    bind(*L_slow_path);
+  } else if (L_fast_path == &L_fallthrough) {
+    br(Assembler::NE, *L_slow_path);
+    bind(*L_fast_path);
+  } else {
+    Unimplemented();
+  }
+}
 
 void MacroAssembler::verify_oop(Register reg, const char* s) {
   if (!VerifyOops) return;
@@ -3683,6 +3712,12 @@
   bs->obj_equals(this, obj1, obj2);
 }
 
+void MacroAssembler::load_method_holder(Register holder, Register method) {
+  ldr(holder, Address(method, Method::const_offset()));                      // ConstMethod*
+  ldr(holder, Address(holder, ConstMethod::constants_offset()));             // ConstantPool*
+  ldr(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes())); // InstanceKlass*
+}
+
 void MacroAssembler::load_klass(Register dst, Register src) {
   if (UseCompressedClassPointers) {
     ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -788,6 +788,8 @@
   // C 'boolean' to Java boolean: x == 0 ? 0 : 1
   void c2bool(Register x);
 
+  void load_method_holder(Register holder, Register method);
+
   // oop manipulations
   void load_klass(Register dst, Register src);
   void store_klass(Register dst, Register src);
@@ -926,6 +928,11 @@
                            Register temp_reg,
                            Label& L_success);
 
+  void clinit_barrier(Register klass,
+                      Register thread,
+                      Label* L_fast_path = NULL,
+                      Label* L_slow_path = NULL);
+
   Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
 
 
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -799,6 +799,22 @@
   }
 #endif
 
+  // Class initialization barrier for static methods
+  if (VM_Version::supports_fast_class_init_checks()) {
+    Label L_skip_barrier;
+
+    { // Bypass the barrier for non-static methods
+      __ ldrw(rscratch1, Address(rmethod, Method::access_flags_offset()));
+      __ andsw(zr, rscratch1, JVM_ACC_STATIC);
+      __ br(Assembler::EQ, L_skip_barrier); // non-static
+    }
+
+    __ load_method_holder(rscratch2, rmethod);
+    __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
+    __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+    __ bind(L_skip_barrier);
+  }
+
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
 
   __ flush();
@@ -1580,6 +1596,15 @@
   // SVC, HVC, or SMC.  Make it a NOP.
   __ nop();
 
+  if (VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) {
+    Label L_skip_barrier;
+    __ mov_metadata(rscratch2, method->method_holder()); // InstanceKlass*
+    __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
+    __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+
+    __ bind(L_skip_barrier);
+  }
+
   // Generate stack overflow check
   if (UseStackBanging) {
     __ bang_stack_with_offset(JavaThread::stack_shadow_zone_size());
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -2323,7 +2323,7 @@
   const Register temp = r19;
   assert_different_registers(Rcache, index, temp);
 
-  Label resolved;
+  Label resolved, clinit_barrier_slow;
 
   Bytecodes::Code code = bytecode();
   switch (code) {
@@ -2338,6 +2338,8 @@
   __ br(Assembler::EQ, resolved);
 
   // resolve first time through
+  // Class initialization barrier slow path lands here as well.
+  __ bind(clinit_barrier_slow);
   address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
   __ mov(temp, (int) code);
   __ call_VM(noreg, entry, temp);
@@ -2347,6 +2349,13 @@
   // n.b. unlike x86 Rcache is now rcpool plus the indexed offset
   // so all clients ofthis method must be modified accordingly
   __ bind(resolved);
+
+  // Class initialization barrier for static methods
+  if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
+    __ load_resolved_method_at_index(byte_no, temp, Rcache);
+    __ load_method_holder(temp, temp);
+    __ clinit_barrier(temp, rscratch1, NULL, &clinit_barrier_slow);
+  }
 }
 
 // The Rcache and index registers must be set before call
@@ -3418,9 +3427,8 @@
   __ profile_virtual_call(r3, r13, r19);
 
   // Get declaring interface class from method, and itable index
-  __ ldr(r0, Address(rmethod, Method::const_offset()));
-  __ ldr(r0, Address(r0, ConstMethod::constants_offset()));
-  __ ldr(r0, Address(r0, ConstantPool::pool_holder_offset_in_bytes()));
+
+  __ load_method_holder(r0, rmethod);
   __ ldrw(rmethod, Address(rmethod, Method::itable_index_offset()));
   __ subw(rmethod, rmethod, Method::itable_index_max);
   __ negw(rmethod, rmethod);
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -124,6 +124,7 @@
   static int dcache_line_size() {
     return (1 << ((_psr_info.ctr_el0 >> 16) & 0x0f)) * 4;
   }
+  static bool supports_fast_class_init_checks() { return true; }
 };
 
 #endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -69,7 +69,7 @@
     }
 #endif
 
-    if (ShenandoahSATBBarrier && !dest_uninitialized && !ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc()) {
+    if (ShenandoahSATBBarrier && !dest_uninitialized) {
       Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
       assert_different_registers(dst, count, thread); // we don't care about src here?
 #ifndef _LP64
--- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad	Mon Jul 08 16:04:25 2019 +0530
@@ -45,32 +45,31 @@
 
 // For XMM and YMM enabled processors
 instruct zLoadBarrierSlowRegXmmAndYmm(rRegP dst, memory src, rFlagsReg cr,
-                                      rxmm0 x0, rxmm1 x1, rxmm2 x2,rxmm3 x3,
+                                      rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
                                       rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
                                       rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
                                       rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15) %{
+  match(Set dst (LoadBarrierSlowReg src dst));
+  predicate(UseAVX <= 2 && !n->as_LoadBarrierSlowReg()->is_weak());
 
-  match(Set dst (LoadBarrierSlowReg src));
-  predicate((UseAVX <= 2) && !n->as_LoadBarrierSlowReg()->is_weak());
-
-  effect(DEF dst, KILL cr,
+  effect(KILL cr,
          KILL x0, KILL x1, KILL x2, KILL x3,
          KILL x4, KILL x5, KILL x6, KILL x7,
          KILL x8, KILL x9, KILL x10, KILL x11,
          KILL x12, KILL x13, KILL x14, KILL x15);
 
-  format %{ "zLoadBarrierSlowRegXmmAndYmm $dst, $src" %}
+  format %{ "lea $dst, $src\n\t"
+            "call #ZLoadBarrierSlowPath" %}
 
   ins_encode %{
     z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, false /* weak */);
   %}
-
   ins_pipe(pipe_slow);
 %}
 
 // For ZMM enabled processors
 instruct zLoadBarrierSlowRegZmm(rRegP dst, memory src, rFlagsReg cr,
-                                rxmm0 x0, rxmm1 x1, rxmm2 x2,rxmm3 x3,
+                                rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
                                 rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
                                 rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
                                 rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15,
@@ -79,10 +78,10 @@
                                 rxmm24 x24, rxmm25 x25, rxmm26 x26, rxmm27 x27,
                                 rxmm28 x28, rxmm29 x29, rxmm30 x30, rxmm31 x31) %{
 
-  match(Set dst (LoadBarrierSlowReg src));
-  predicate((UseAVX == 3) && !n->as_LoadBarrierSlowReg()->is_weak());
+  match(Set dst (LoadBarrierSlowReg src dst));
+  predicate(UseAVX == 3 && !n->as_LoadBarrierSlowReg()->is_weak());
 
-  effect(DEF dst, KILL cr,
+  effect(KILL cr,
          KILL x0, KILL x1, KILL x2, KILL x3,
          KILL x4, KILL x5, KILL x6, KILL x7,
          KILL x8, KILL x9, KILL x10, KILL x11,
@@ -92,43 +91,42 @@
          KILL x24, KILL x25, KILL x26, KILL x27,
          KILL x28, KILL x29, KILL x30, KILL x31);
 
-  format %{ "zLoadBarrierSlowRegZmm $dst, $src" %}
+  format %{ "lea $dst, $src\n\t"
+            "call #ZLoadBarrierSlowPath" %}
 
   ins_encode %{
     z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, false /* weak */);
   %}
-
   ins_pipe(pipe_slow);
 %}
 
 // For XMM and YMM enabled processors
 instruct zLoadBarrierWeakSlowRegXmmAndYmm(rRegP dst, memory src, rFlagsReg cr,
-                                          rxmm0 x0, rxmm1 x1, rxmm2 x2,rxmm3 x3,
+                                          rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
                                           rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
                                           rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
                                           rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15) %{
+  match(Set dst (LoadBarrierSlowReg src dst));
+  predicate(UseAVX <= 2 && n->as_LoadBarrierSlowReg()->is_weak());
 
-  match(Set dst (LoadBarrierSlowReg src));
-  predicate((UseAVX <= 2) && n->as_LoadBarrierSlowReg()->is_weak());
-
-  effect(DEF dst, KILL cr,
+  effect(KILL cr,
          KILL x0, KILL x1, KILL x2, KILL x3,
          KILL x4, KILL x5, KILL x6, KILL x7,
          KILL x8, KILL x9, KILL x10, KILL x11,
          KILL x12, KILL x13, KILL x14, KILL x15);
 
-  format %{ "zLoadBarrierWeakSlowRegXmmAndYmm $dst, $src" %}
+  format %{ "lea $dst, $src\n\t"
+            "call #ZLoadBarrierSlowPath" %}
 
   ins_encode %{
     z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, true /* weak */);
   %}
-
   ins_pipe(pipe_slow);
 %}
 
 // For ZMM enabled processors
 instruct zLoadBarrierWeakSlowRegZmm(rRegP dst, memory src, rFlagsReg cr,
-                                    rxmm0 x0, rxmm1 x1, rxmm2 x2,rxmm3 x3,
+                                    rxmm0 x0, rxmm1 x1, rxmm2 x2, rxmm3 x3,
                                     rxmm4 x4, rxmm5 x5, rxmm6 x6, rxmm7 x7,
                                     rxmm8 x8, rxmm9 x9, rxmm10 x10, rxmm11 x11,
                                     rxmm12 x12, rxmm13 x13, rxmm14 x14, rxmm15 x15,
@@ -137,10 +135,10 @@
                                     rxmm24 x24, rxmm25 x25, rxmm26 x26, rxmm27 x27,
                                     rxmm28 x28, rxmm29 x29, rxmm30 x30, rxmm31 x31) %{
 
-  match(Set dst (LoadBarrierSlowReg src));
-  predicate((UseAVX == 3) && n->as_LoadBarrierSlowReg()->is_weak());
+  match(Set dst (LoadBarrierSlowReg src dst));
+  predicate(UseAVX == 3 && n->as_LoadBarrierSlowReg()->is_weak());
 
-  effect(DEF dst, KILL cr,
+  effect(KILL cr,
          KILL x0, KILL x1, KILL x2, KILL x3,
          KILL x4, KILL x5, KILL x6, KILL x7,
          KILL x8, KILL x9, KILL x10, KILL x11,
@@ -150,12 +148,12 @@
          KILL x24, KILL x25, KILL x26, KILL x27,
          KILL x28, KILL x29, KILL x30, KILL x31);
 
-  format %{ "zLoadBarrierWeakSlowRegZmm $dst, $src" %}
+  format %{ "lea $dst, $src\n\t"
+            "call #ZLoadBarrierSlowPath" %}
 
   ins_encode %{
     z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$Address, true /* weak */);
   %}
-
   ins_pipe(pipe_slow);
 %}
 
--- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -156,9 +156,11 @@
     StubRoutines::_oop_arraycopy             = ShouldNotCallThisStub();
 
     StubRoutines::_checkcast_arraycopy       = ShouldNotCallThisStub();
-    StubRoutines::_unsafe_arraycopy          = ShouldNotCallThisStub();
     StubRoutines::_generic_arraycopy         = ShouldNotCallThisStub();
 
+    // Shared code tests for "NULL" to discover the stub is not generated.
+    StubRoutines::_unsafe_arraycopy          = NULL;
+
     // We don't generate specialized code for HeapWord-aligned source
     // arrays, so just use the code we've already generated
     StubRoutines::_arrayof_jbyte_disjoint_arraycopy =
--- a/src/hotspot/os/aix/os_aix.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/aix/os_aix.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -37,11 +37,6 @@
 #include <sys/ioctl.h>
 #include <netdb.h>
 
-// File names are case-insensitive on windows only.
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/bsd/os_bsd.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/bsd/os_bsd.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -35,11 +35,6 @@
 #include <poll.h>
 #include <netdb.h>
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/linux/os_linux.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/linux/os_linux.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -84,6 +84,7 @@
 # include <sys/select.h>
 # include <pthread.h>
 # include <signal.h>
+# include <endian.h>
 # include <errno.h>
 # include <dlfcn.h>
 # include <stdio.h>
@@ -1747,11 +1748,26 @@
     return NULL;
   }
 
+  if (elf_head.e_ident[EI_DATA] != LITTLE_ENDIAN_ONLY(ELFDATA2LSB) BIG_ENDIAN_ONLY(ELFDATA2MSB)) {
+    // handle invalid/out of range endianness values
+    if (elf_head.e_ident[EI_DATA] == 0 || elf_head.e_ident[EI_DATA] > 2) {
+      return NULL;
+    }
+
+#if defined(VM_LITTLE_ENDIAN)
+    // VM is LE, shared object BE
+    elf_head.e_machine = be16toh(elf_head.e_machine);
+#else
+    // VM is BE, shared object LE
+    elf_head.e_machine = le16toh(elf_head.e_machine);
+#endif
+  }
+
   typedef struct {
     Elf32_Half    code;         // Actual value as defined in elf.h
     Elf32_Half    compat_class; // Compatibility of archs at VM's sense
     unsigned char elf_class;    // 32 or 64 bit
-    unsigned char endianess;    // MSB or LSB
+    unsigned char endianness;   // MSB or LSB
     char*         name;         // String representation
   } arch_t;
 
@@ -1778,8 +1794,9 @@
     {EM_PPC64,       EM_PPC64,   ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
     {EM_SH,          EM_SH,      ELFCLASS32, ELFDATA2MSB, (char*)"SuperH BE"},
 #endif
-    {EM_ARM,         EM_ARM,     ELFCLASS32,   ELFDATA2LSB, (char*)"ARM"},
-    {EM_S390,        EM_S390,    ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"},
+    {EM_ARM,         EM_ARM,     ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
+    // we only support 64 bit z architecture
+    {EM_S390,        EM_S390,    ELFCLASS64, ELFDATA2MSB, (char*)"IBM System/390"},
     {EM_ALPHA,       EM_ALPHA,   ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"},
     {EM_MIPS_RS3_LE, EM_MIPS_RS3_LE, ELFCLASS32, ELFDATA2LSB, (char*)"MIPSel"},
     {EM_MIPS,        EM_MIPS,    ELFCLASS32, ELFDATA2MSB, (char*)"MIPS"},
@@ -1825,7 +1842,7 @@
         AARCH64, ALPHA, ARM, AMD64, IA32, IA64, M68K, MIPS, MIPSEL, PARISC, __powerpc__, __powerpc64__, S390, SH, __sparc
 #endif
 
-  // Identify compatability class for VM's architecture and library's architecture
+  // Identify compatibility class for VM's architecture and library's architecture
   // Obtain string descriptions for architectures
 
   arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
@@ -1849,29 +1866,35 @@
     return NULL;
   }
 
-  if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
-    ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
-    return NULL;
-  }
-
-#ifndef S390
-  if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
-    ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)");
-    return NULL;
-  }
-#endif // !S390
-
   if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
-    if (lib_arch.name!=NULL) {
+    if (lib_arch.name != NULL) {
       ::snprintf(diag_msg_buf, diag_msg_max_length-1,
-                 " (Possible cause: can't load %s-bit .so on a %s-bit platform)",
+                 " (Possible cause: can't load %s .so on a %s platform)",
                  lib_arch.name, arch_array[running_arch_index].name);
     } else {
       ::snprintf(diag_msg_buf, diag_msg_max_length-1,
-                 " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)",
-                 lib_arch.code,
-                 arch_array[running_arch_index].name);
+                 " (Possible cause: can't load this .so (machine code=0x%x) on a %s platform)",
+                 lib_arch.code, arch_array[running_arch_index].name);
     }
+    return NULL;
+  }
+
+  if (lib_arch.endianness != arch_array[running_arch_index].endianness) {
+    ::snprintf(diag_msg_buf, diag_msg_max_length-1, " (Possible cause: endianness mismatch)");
+    return NULL;
+  }
+
+  // ELF file class/capacity : 0 - invalid, 1 - 32bit, 2 - 64bit
+  if (lib_arch.elf_class > 2 || lib_arch.elf_class < 1) {
+    ::snprintf(diag_msg_buf, diag_msg_max_length-1, " (Possible cause: invalid ELF file class)");
+    return NULL;
+  }
+
+  if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
+    ::snprintf(diag_msg_buf, diag_msg_max_length-1,
+               " (Possible cause: architecture word width mismatch, can't load %d-bit .so on a %d-bit platform)",
+               (int) lib_arch.elf_class * 32, arch_array[running_arch_index].elf_class * 32);
+    return NULL;
   }
 
   return NULL;
--- a/src/hotspot/os/linux/os_linux.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/linux/os_linux.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -35,11 +35,6 @@
 #include <poll.h>
 #include <netdb.h>
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/posix/os_posix.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/posix/os_posix.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1450,6 +1450,30 @@
   return path;
 }
 
+bool os::same_files(const char* file1, const char* file2) {
+  if (strcmp(file1, file2) == 0) {
+    return true;
+  }
+
+  bool is_same = false;
+  struct stat st1;
+  struct stat st2;
+
+  if (os::stat(file1, &st1) < 0) {
+    return false;
+  }
+
+  if (os::stat(file2, &st2) < 0) {
+    return false;
+  }
+
+  if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
+    // same files
+    is_same = true;
+  }
+  return is_same;
+}
+
 // Check minimum allowable stack sizes for thread creation and to initialize
 // the java system classes, including StackOverflowError - depends on page
 // size.
--- a/src/hotspot/os/solaris/os_solaris.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1520,6 +1520,13 @@
   }
 }
 
+static void change_endianness(Elf32_Half& val) {
+  unsigned char *ptr = (unsigned char *)&val;
+  unsigned char swp = ptr[0];
+  ptr[0] = ptr[1];
+  ptr[1] = swp;
+}
+
 // Loads .dll/.so and
 // in case of error it checks if .dll/.so was built for the
 // same architecture as Hotspot is running on
@@ -1570,6 +1577,14 @@
     return NULL;
   }
 
+  if (elf_head.e_ident[EI_DATA] != LITTLE_ENDIAN_ONLY(ELFDATA2LSB) BIG_ENDIAN_ONLY(ELFDATA2MSB)) {
+    // handle invalid/out of range endianness values
+    if (elf_head.e_ident[EI_DATA] == 0 || elf_head.e_ident[EI_DATA] > 2) {
+      return NULL;
+    }
+    change_endianness(elf_head.e_machine);
+  }
+
   typedef struct {
     Elf32_Half    code;         // Actual value as defined in elf.h
     Elf32_Half    compat_class; // Compatibility of archs at VM's sense
@@ -1588,7 +1603,10 @@
     {EM_SPARCV9,     EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
     {EM_PPC,         EM_PPC,     ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
     {EM_PPC64,       EM_PPC64,   ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
-    {EM_ARM,         EM_ARM,     ELFCLASS32, ELFDATA2LSB, (char*)"ARM 32"}
+    {EM_ARM,         EM_ARM,     ELFCLASS32, ELFDATA2LSB, (char*)"ARM"},
+    // we only support 64 bit z architecture
+    {EM_S390,        EM_S390,    ELFCLASS64, ELFDATA2MSB, (char*)"IBM System/390"},
+    {EM_AARCH64,     EM_AARCH64, ELFCLASS64, ELFDATA2LSB, (char*)"AARCH64"}
   };
 
 #if  (defined IA32)
@@ -1612,7 +1630,7 @@
        IA32, AMD64, IA64, __sparc, __powerpc__, ARM, ARM
 #endif
 
-  // Identify compatability class for VM's architecture and library's architecture
+  // Identify compatibility class for VM's architecture and library's architecture
   // Obtain string descriptions for architectures
 
   arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
@@ -1636,29 +1654,37 @@
     return NULL;
   }
 
+  if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
+    if (lib_arch.name != NULL) {
+      ::snprintf(diag_msg_buf, diag_msg_max_length-1,
+                 " (Possible cause: can't load %s .so on a %s platform)",
+                 lib_arch.name, arch_array[running_arch_index].name);
+    } else {
+      ::snprintf(diag_msg_buf, diag_msg_max_length-1,
+                 " (Possible cause: can't load this .so (machine code=0x%x) on a %s platform)",
+                 lib_arch.code, arch_array[running_arch_index].name);
+    }
+    return NULL;
+  }
+
   if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
     ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
     return NULL;
   }
 
+  // ELF file class/capacity : 0 - invalid, 1 - 32bit, 2 - 64bit
+  if (lib_arch.elf_class > 2 || lib_arch.elf_class < 1) {
+    ::snprintf(diag_msg_buf, diag_msg_max_length-1, " (Possible cause: invalid ELF file class)");
+    return NULL;
+  }
+
   if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
-    ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)");
+    ::snprintf(diag_msg_buf, diag_msg_max_length-1,
+               " (Possible cause: architecture word width mismatch, can't load %d-bit .so on a %d-bit platform)",
+               (int) lib_arch.elf_class * 32, arch_array[running_arch_index].elf_class * 32);
     return NULL;
   }
 
-  if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
-    if (lib_arch.name!=NULL) {
-      ::snprintf(diag_msg_buf, diag_msg_max_length-1,
-                 " (Possible cause: can't load %s-bit .so on a %s-bit platform)",
-                 lib_arch.name, arch_array[running_arch_index].name);
-    } else {
-      ::snprintf(diag_msg_buf, diag_msg_max_length-1,
-                 " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)",
-                 lib_arch.code,
-                 arch_array[running_arch_index].name);
-    }
-  }
-
   return NULL;
 }
 
--- a/src/hotspot/os/solaris/os_solaris.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/solaris/os_solaris.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -37,11 +37,6 @@
 #include <netdb.h>
 #include <setjmp.h>
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/windows/attachListener_windows.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/windows/attachListener_windows.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -272,23 +272,13 @@
 
 // open the pipe to the client
 HANDLE Win32AttachOperation::open_pipe() {
-  HANDLE hPipe;
-
-  hPipe = ::CreateFile( pipe(),  // pipe name
+  HANDLE hPipe = ::CreateFile( pipe(),  // pipe name
                         GENERIC_WRITE,   // write only
                         0,              // no sharing
                         NULL,           // default security attributes
                         OPEN_EXISTING,  // opens existing pipe
                         0,              // default attributes
                         NULL);          // no template file
-
-  if (hPipe != INVALID_HANDLE_VALUE) {
-    // shouldn't happen as there is a pipe created per operation
-    if (::GetLastError() == ERROR_PIPE_BUSY) {
-      ::CloseHandle(hPipe);
-      return INVALID_HANDLE_VALUE;
-    }
-  }
   return hPipe;
 }
 
@@ -307,8 +297,7 @@
     }
     buf += nwrote;
     len -= nwrote;
-  }
-  while (len > 0);
+  } while (len > 0);
   return TRUE;
 }
 
@@ -326,6 +315,7 @@
   // java_suspend_self() via check_and_wait_while_suspended()
 
   HANDLE hPipe = open_pipe();
+  int lastError = (int)::GetLastError();
   if (hPipe != INVALID_HANDLE_VALUE) {
     BOOL fSuccess;
 
@@ -337,6 +327,7 @@
     if (fSuccess) {
       fSuccess = write_pipe(hPipe, (char*)result_stream->base(), (int)(result_stream->size()));
     }
+    lastError = (int)::GetLastError();
 
     // Need to flush buffers
     FlushFileBuffers(hPipe);
@@ -345,10 +336,10 @@
     if (fSuccess) {
       log_debug(attach)("wrote result of attach operation %s to pipe %s", name(), pipe());
     } else {
-      log_error(attach)("failure writing result of operation %s to pipe %s", name(), pipe());
+      log_error(attach)("failure (%d) writing result of operation %s to pipe %s", lastError, name(), pipe());
     }
   } else {
-    log_error(attach)("could not open pipe %s to send result of operation %s", pipe(), name());
+    log_error(attach)("could not open (%d) pipe %s to send result of operation %s", lastError, pipe(), name());
   }
 
   DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
--- a/src/hotspot/os/windows/os_windows.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/windows/os_windows.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -4367,6 +4367,88 @@
   return ret;
 }
 
+static HANDLE create_read_only_file_handle(const char* file) {
+  if (file == NULL) {
+    return INVALID_HANDLE_VALUE;
+  }
+
+  char* nativepath = (char*)os::strdup(file, mtInternal);
+  if (nativepath == NULL) {
+    errno = ENOMEM;
+    return INVALID_HANDLE_VALUE;
+  }
+  os::native_path(nativepath);
+
+  size_t len = strlen(nativepath);
+  HANDLE handle = INVALID_HANDLE_VALUE;
+
+  if (len < MAX_PATH) {
+    handle = ::CreateFile(nativepath, 0, FILE_SHARE_READ,
+                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  } else {
+    errno_t err = ERROR_SUCCESS;
+    wchar_t* wfile = create_unc_path(nativepath, err);
+    if (err != ERROR_SUCCESS) {
+      if (wfile != NULL) {
+        destroy_unc_path(wfile);
+      }
+      os::free(nativepath);
+      return INVALID_HANDLE_VALUE;
+    }
+    handle = ::CreateFileW(wfile, 0, FILE_SHARE_READ,
+                           NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    destroy_unc_path(wfile);
+  }
+
+  os::free(nativepath);
+  return handle;
+}
+
+bool os::same_files(const char* file1, const char* file2) {
+
+  if (file1 == NULL && file2 == NULL) {
+    return true;
+  }
+
+  if (file1 == NULL || file2 == NULL) {
+    return false;
+  }
+
+  if (strcmp(file1, file2) == 0) {
+    return true;
+  }
+
+  HANDLE handle1 = create_read_only_file_handle(file1);
+  HANDLE handle2 = create_read_only_file_handle(file2);
+  bool result = false;
+
+  // if we could open both paths...
+  if (handle1 != INVALID_HANDLE_VALUE && handle2 != INVALID_HANDLE_VALUE) {
+    BY_HANDLE_FILE_INFORMATION fileInfo1;
+    BY_HANDLE_FILE_INFORMATION fileInfo2;
+    if (::GetFileInformationByHandle(handle1, &fileInfo1) &&
+      ::GetFileInformationByHandle(handle2, &fileInfo2)) {
+      // the paths are the same if they refer to the same file (fileindex) on the same volume (volume serial number)
+      if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&
+        fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&
+        fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) {
+        result = true;
+      }
+    }
+  }
+
+  //free the handles
+  if (handle1 != INVALID_HANDLE_VALUE) {
+    ::CloseHandle(handle1);
+  }
+
+  if (handle2 != INVALID_HANDLE_VALUE) {
+    ::CloseHandle(handle2);
+  }
+
+  return result;
+}
+
 
 #define FT2INT64(ft) \
   ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))
--- a/src/hotspot/os/windows/os_windows.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os/windows/os_windows.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -32,11 +32,6 @@
 
 inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;}
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s, const char* t, size_t num) {
-  return _strnicmp(s, t, num);
-}
-
 inline void  os::dll_unload(void *lib) {
   ::FreeLibrary((HMODULE)lib);
 }
--- a/src/hotspot/os_cpu/linux_x86/orderAccess_linux_x86.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/os_cpu/linux_x86/orderAccess_linux_x86.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -57,7 +57,13 @@
 
 inline void OrderAccess::cross_modify_fence() {
   int idx = 0;
+#ifdef AMD64
   __asm__ volatile ("cpuid " : "+a" (idx) : : "ebx", "ecx", "edx", "memory");
+#else
+  // On some x86 systems EBX is a reserved register that cannot be
+  // clobbered, so we must protect it around the CPUID.
+  __asm__ volatile ("xchg %%esi, %%ebx; cpuid; xchg %%esi, %%ebx " : "+a" (idx) : : "esi", "ecx", "edx", "memory");
+#endif
 }
 
 template<>
--- a/src/hotspot/share/adlc/formssel.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/adlc/formssel.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -3513,7 +3513,7 @@
     "GetAndSetB", "GetAndSetS", "GetAndAddI", "GetAndSetI", "GetAndSetP",
     "GetAndAddB", "GetAndAddS", "GetAndAddL", "GetAndSetL", "GetAndSetN",
 #if INCLUDE_ZGC
-    "LoadBarrierSlowReg", "ZGetAndSetP", "ZCompareAndSwapP", "ZCompareAndExchangeP", "ZWeakCompareAndSwapP",
+    "ZGetAndSetP", "ZCompareAndSwapP", "ZCompareAndExchangeP", "ZWeakCompareAndSwapP",
 #endif
     "ClearArray"
   };
--- a/src/hotspot/share/c1/c1_Runtime1.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -294,6 +294,12 @@
     if (entry == entry_for((StubID)id)) return name_for((StubID)id);
   }
 
+  BarrierSetC1* bsc1 = BarrierSet::barrier_set()->barrier_set_c1();
+  const char* name = bsc1->rtcall_name_for_address(entry);
+  if (name != NULL) {
+    return name;
+  }
+
 #define FUNCTION_CASE(a, f) \
   if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f))  return #f
 
--- a/src/hotspot/share/classfile/classLoader.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoader.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -292,11 +292,13 @@
   return NULL;
 }
 
-ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append) : ClassPathEntry() {
+ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name,
+                                     bool is_boot_append, bool from_class_path_attr) : ClassPathEntry() {
   _zip = zip;
   char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
   strcpy(copy, zip_name);
   _zip_name = copy;
+  _from_class_path_attr = from_class_path_attr;
 }
 
 ClassPathZipEntry::~ClassPathZipEntry() {
@@ -577,7 +579,7 @@
     strncpy(path, &class_path[start], end - start);
     path[end - start] = '\0';
 
-    update_class_path_entry_list(path, false, false);
+    update_class_path_entry_list(path, false, false, false);
 
     while (class_path[end] == os::path_separator()[0]) {
       end++;
@@ -612,7 +614,7 @@
   // File or directory found
   ClassPathEntry* new_entry = NULL;
   new_entry = create_class_path_entry(path, &st, true /* throw_exception */,
-                                      false /*is_boot_append */, CHECK);
+                                      false /*is_boot_append */, false /* from_class_path_attr */, CHECK);
   if (new_entry == NULL) {
     return;
   }
@@ -668,7 +670,7 @@
       struct stat st;
       if (os::stat(path, &st) == 0) {
         // File or directory found
-        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, false, CHECK);
         // If the path specification is valid, enter it into this module's list
         if (new_entry != NULL) {
           module_cpl->add_to_list(new_entry);
@@ -737,7 +739,7 @@
       struct stat st;
       if (os::stat(path, &st) == 0) {
         // Directory found
-        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, false, CHECK);
 
         // Check for a jimage
         if (Arguments::has_jimage()) {
@@ -754,7 +756,7 @@
     } else {
       // Every entry on the system boot class path after the initial base piece,
       // which is set by os::set_boot_path(), is considered an appended entry.
-      update_class_path_entry_list(path, false, true);
+      update_class_path_entry_list(path, false, true, false);
     }
 
     while (class_path[end] == os::path_separator()[0]) {
@@ -782,7 +784,7 @@
   struct stat st;
   if (os::stat(path, &st) == 0) {
     // Directory found
-    ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+    ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, false, CHECK);
 
     // If the path specification is valid, enter it into this module's list.
     // There is no need to check for duplicate modules in the exploded entry list,
@@ -802,7 +804,9 @@
 
 ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
                                                      bool throw_exception,
-                                                     bool is_boot_append, TRAPS) {
+                                                     bool is_boot_append,
+                                                     bool from_class_path_attr,
+                                                     TRAPS) {
   JavaThread* thread = JavaThread::current();
   ClassPathEntry* new_entry = NULL;
   if ((st->st_mode & S_IFMT) == S_IFREG) {
@@ -832,7 +836,7 @@
         zip = (*ZipOpen)(canonical_path, &error_msg);
       }
       if (zip != NULL && error_msg == NULL) {
-        new_entry = new ClassPathZipEntry(zip, path, is_boot_append);
+        new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr);
       } else {
         char *msg;
         if (error_msg == NULL) {
@@ -882,7 +886,7 @@
         }
         if (zip != NULL && error_msg == NULL) {
           // create using canonical path
-          return new ClassPathZipEntry(zip, canonical_path, is_boot_append);
+          return new ClassPathZipEntry(zip, canonical_path, is_boot_append, false);
         }
       }
     }
@@ -956,13 +960,14 @@
 bool ClassLoader::update_class_path_entry_list(const char *path,
                                                bool check_for_duplicates,
                                                bool is_boot_append,
+                                               bool from_class_path_attr,
                                                bool throw_exception) {
   struct stat st;
   if (os::stat(path, &st) == 0) {
     // File or directory found
     ClassPathEntry* new_entry = NULL;
     Thread* THREAD = Thread::current();
-    new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, CHECK_(false));
+    new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, from_class_path_attr, CHECK_(false));
     if (new_entry == NULL) {
       return false;
     }
--- a/src/hotspot/share/classfile/classLoader.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoader.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -53,6 +53,8 @@
   void set_next(ClassPathEntry* next);
   virtual bool is_modules_image() const = 0;
   virtual bool is_jar_file() const = 0;
+  // Is this entry created from the "Class-path" attribute from a JAR Manifest?
+  virtual bool from_class_path_attr() const = 0;
   virtual const char* name() const = 0;
   virtual JImageFile* jimage() const = 0;
   virtual void close_jimage() = 0;
@@ -73,6 +75,7 @@
  public:
   bool is_modules_image() const { return false; }
   bool is_jar_file() const { return false;  }
+  bool from_class_path_attr() const { return false; }
   const char* name() const { return _dir; }
   JImageFile* jimage() const { return NULL; }
   void close_jimage() {}
@@ -99,13 +102,15 @@
  private:
   jzfile* _zip;              // The zip archive
   const char*   _zip_name;   // Name of zip archive
+  bool _from_class_path_attr; // From the "Class-path" attribute of a jar file
  public:
   bool is_modules_image() const { return false; }
   bool is_jar_file() const { return true;  }
+  bool from_class_path_attr() const { return _from_class_path_attr; }
   const char* name() const { return _zip_name; }
   JImageFile* jimage() const { return NULL; }
   void close_jimage() {}
-  ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
+  ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append, bool from_class_path_attr);
   virtual ~ClassPathZipEntry();
   u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
   ClassFileStream* open_stream(const char* name, TRAPS);
@@ -122,6 +127,7 @@
 public:
   bool is_modules_image() const;
   bool is_jar_file() const { return false; }
+  bool from_class_path_attr() const { return false; }
   bool is_open() const { return _jimage != NULL; }
   const char* name() const { return _name == NULL ? "" : _name; }
   JImageFile* jimage() const { return _jimage; }
@@ -257,7 +263,8 @@
  public:
   static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
                                                  bool throw_exception,
-                                                 bool is_boot_append, TRAPS);
+                                                 bool is_boot_append,
+                                                 bool from_class_path_attr, TRAPS);
 
   // If the package for the fully qualified class name is in the boot
   // loader's package entry table then add_package() sets the classpath_index
@@ -281,6 +288,7 @@
   static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
                                            bool is_boot_append,
+                                           bool from_class_path_attr,
                                            bool throw_exception=true);
   CDS_ONLY(static void update_module_path_entry_list(const char *path, TRAPS);)
   static void print_bootclasspath();
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -266,6 +266,19 @@
 }
 #endif // PRODUCT
 
+void ClassLoaderData::clear_claim(int claim) {
+  for (;;) {
+    int old_claim = Atomic::load(&_claim);
+    if ((old_claim & claim) == 0) {
+      return;
+    }
+    int new_claim = old_claim & ~claim;
+    if (Atomic::cmpxchg(new_claim, &_claim, old_claim) == old_claim) {
+      return;
+    }
+  }
+}
+
 bool ClassLoaderData::try_claim(int claim) {
   for (;;) {
     int old_claim = Atomic::load(&_claim);
--- a/src/hotspot/share/classfile/classLoaderData.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoaderData.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -206,16 +206,17 @@
 
   // The "claim" is typically used to check if oops_do needs to be applied on
   // the CLD or not. Most GCs only perform strong marking during the marking phase.
-  enum {
-    _claim_none        = 0,
-    _claim_finalizable = 2,
-    _claim_strong      = 3
+  enum Claim {
+    _claim_none         = 0,
+    _claim_finalizable  = 2,
+    _claim_strong       = 3,
+    _claim_other        = 4
   };
   void clear_claim() { _claim = 0; }
+  void clear_claim(int claim);
   bool claimed() const { return _claim != 0; }
+  bool claimed(int claim) const { return (_claim & claim) == claim; }
   bool try_claim(int claim);
-  int get_claim() const { return _claim; }
-  void set_claim(int claim) { _claim = claim; }
 
   // Computes if the CLD is alive or not. This is safe to call in concurrent
   // contexts.
--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -64,6 +64,11 @@
   }
 }
 
+void ClassLoaderDataGraph::clear_claimed_marks(int claim) {
+ for (ClassLoaderData* cld = OrderAccess::load_acquire(&_head); cld != NULL; cld = cld->next()) {
+    cld->clear_claim(claim);
+  }
+}
 // Class iterator used by the compiler.  It gets some number of classes at
 // a safepoint to decay invocation counters on the methods.
 class ClassLoaderDataGraphKlassIteratorStatic {
@@ -471,7 +476,7 @@
   // The CLDs in [_head, _saved_head] were all added during last call to remember_new_clds(true);
   ClassLoaderData* curr = _head;
   while (curr != _saved_head) {
-    if (!curr->claimed()) {
+    if (!curr->claimed(ClassLoaderData::_claim_strong)) {
       array->push(curr);
       LogTarget(Debug, class, loader, data) lt;
       if (lt.is_enabled()) {
--- a/src/hotspot/share/classfile/classLoaderDataGraph.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -68,6 +68,7 @@
   static void clean_module_and_package_info();
   static void purge();
   static void clear_claimed_marks();
+  static void clear_claimed_marks(int claim);
   // Iteration through CLDG inside a safepoint; GC support
   static void cld_do(CLDClosure* cl);
   static void cld_unloading_do(CLDClosure* cl);
--- a/src/hotspot/share/classfile/classLoaderExt.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -213,7 +213,7 @@
         int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
         assert((size_t)n == libname_len, "Unexpected number of characters in string");
         trace_class_path("library = ", libname);
-        ClassLoader::update_class_path_entry_list(libname, true, false);
+        ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */);
       }
 
       file_start = file_end;
@@ -339,7 +339,7 @@
   }
   ClassPathEntry* new_entry = NULL;
 
-  new_entry = create_class_path_entry(path, &st, false, false, CHECK_NULL);
+  new_entry = create_class_path_entry(path, &st, false, false, false, CHECK_NULL);
   if (new_entry == NULL) {
     return NULL;
   }
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -153,83 +153,10 @@
   return true;
 }
 
-char* skip_first_path_entry(const char* path) {
-  size_t path_sep_len = strlen(os::path_separator());
-  char* p = strstr((char*)path, os::path_separator());
-  if (p != NULL) {
-    debug_only( {
-      size_t image_name_len = strlen(MODULES_IMAGE_NAME);
-      assert(strncmp(p - image_name_len, MODULES_IMAGE_NAME, image_name_len) == 0,
-             "first entry must be the modules image");
-    } );
-    p += path_sep_len;
-  } else {
-    debug_only( {
-      assert(ClassLoader::string_ends_with(path, MODULES_IMAGE_NAME),
-             "first entry must be the modules image");
-    } );
-  }
-  return p;
-}
-
 bool SharedPathsMiscInfo::check(jint type, const char* path, bool is_static) {
   assert(UseSharedSpaces, "runtime only");
   switch (type) {
   case BOOT_PATH:
-    {
-      //
-      // - Archive contains boot classes only - relaxed boot path check:
-      //   Extra path elements appended to the boot path at runtime are allowed.
-      //
-      // - Archive contains application or platform classes - strict boot path check:
-      //   Validate the entire runtime boot path, which must be compactible
-      //   with the dump time boot path. Appending boot path at runtime is not
-      //   allowed.
-      //
-
-      // The first entry in boot path is the modules_image (guaranteed by
-      // ClassLoader::setup_boot_search_path()). Skip the first entry. The
-      // path of the runtime modules_image may be different from the dump
-      // time path (e.g. the JDK image is copied to a different location
-      // after generating the shared archive), which is acceptable. For most
-      // common cases, the dump time boot path might contain modules_image only.
-      char* runtime_boot_path = Arguments::get_sysclasspath();
-      char* rp = skip_first_path_entry(runtime_boot_path);
-      char* dp = skip_first_path_entry(path);
-
-      bool relaxed_check = is_static ?
-                             !FileMapInfo::current_info()->header()->has_platform_or_app_classes() :
-                             !FileMapInfo::dynamic_info()->header()->has_platform_or_app_classes();
-      if (dp == NULL && rp == NULL) {
-        break;   // ok, both runtime and dump time boot paths have modules_images only
-      } else if (dp == NULL && rp != NULL && relaxed_check) {
-        break;   // ok, relaxed check, runtime has extra boot append path entries
-      } else if (dp != NULL && rp != NULL) {
-        size_t num;
-        size_t dp_len = strlen(dp);
-        size_t rp_len = strlen(rp);
-        if (rp_len >= dp_len) {
-          if (relaxed_check) {
-            // only check the leading entries in the runtime boot path, up to
-            // the length of the dump time boot path
-            num = dp_len;
-          } else {
-            // check the full runtime boot path, must match with dump time
-            num = rp_len;
-          }
-
-          if (os::file_name_strncmp(dp, rp, num) == 0) {
-            // make sure it is the end of an entry in the runtime boot path
-            if (rp[dp_len] == '\0' || rp[dp_len] == os::path_separator()[0]) {
-              break; // ok, runtime and dump time paths match
-            }
-          }
-        }
-      }
-
-      // The paths are different
-      return fail("[BOOT classpath mismatch, actual =", runtime_boot_path);
-    }
     break;
   case NON_EXIST:
     {
@@ -242,22 +169,6 @@
     }
     break;
   case APP_PATH:
-    {
-      size_t len = strlen(path);
-      const char *appcp = Arguments::get_appclasspath();
-      assert(appcp != NULL, "NULL app classpath");
-      size_t appcp_len = strlen(appcp);
-      if (appcp_len < len) {
-        return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
-      }
-      // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
-      if (os::file_name_strncmp(path, appcp, len) != 0) {
-        return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
-      }
-      if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) {
-        return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp);
-      }
-    }
     break;
   default:
     return fail("Corrupted archive file header");
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -2142,7 +2142,7 @@
     // See whether biased locking is enabled and if so set it for this
     // klass.
     // Note that this must be done past the last potential blocking
-    // point / safepoint. We enable biased locking lazily using a
+    // point / safepoint. We might enable biased locking lazily using a
     // VM_Operation to iterate the SystemDictionary and installing the
     // biasable mark word into each InstanceKlass's prototype header.
     // To avoid race conditions where we accidentally miss enabling the
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1088,6 +1088,7 @@
                                                                                                                         \
   /* support for Unsafe */                                                                                              \
   do_class(jdk_internal_misc_Unsafe,               "jdk/internal/misc/Unsafe")                                          \
+  do_class(sun_misc_Unsafe,                        "sun/misc/Unsafe")                                                   \
                                                                                                                         \
   do_intrinsic(_allocateInstance,         jdk_internal_misc_Unsafe,     allocateInstance_name, allocateInstance_signature, F_RN) \
    do_name(     allocateInstance_name,                                  "allocateInstance")                                      \
--- a/src/hotspot/share/code/nmethod.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/code/nmethod.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1774,10 +1774,9 @@
   }
 }
 
-void nmethod::oops_do(OopClosure* f, bool allow_zombie) {
+void nmethod::oops_do(OopClosure* f, bool allow_dead) {
   // make sure the oops ready to receive visitors
-  assert(allow_zombie || !is_zombie(), "should not call follow on zombie nmethod");
-  assert(!is_unloaded(), "should not call follow on unloaded nmethod");
+  assert(allow_dead || is_alive(), "should not call follow on dead nmethod");
 
   // Prevent extra code cache walk for platforms that don't have immediate oops.
   if (relocInfo::mustIterateImmediateOopsInCode()) {
--- a/src/hotspot/share/code/nmethod.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/code/nmethod.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -473,7 +473,7 @@
 
  public:
   void oops_do(OopClosure* f) { oops_do(f, false); }
-  void oops_do(OopClosure* f, bool allow_zombie);
+  void oops_do(OopClosure* f, bool allow_dead);
 
   bool test_set_oops_do_mark();
   static void oops_do_marking_prologue();
--- a/src/hotspot/share/compiler/disassembler.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/compiler/disassembler.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -315,56 +315,96 @@
   }
 }
 
-decode_env::decode_env(CodeBuffer* code, outputStream* output) {
-  memset(this, 0, sizeof(*this));
-  _output = output ? output : tty;
-  _codeBlob    = NULL;
-  _codeBuffer  = code;
-  _helpPrinted = false;
+decode_env::decode_env(CodeBuffer* code, outputStream* output) :
+  _output(output ? output : tty),
+  _codeBuffer(code),
+  _codeBlob(NULL),
+  _nm(NULL),
+  _strings(),
+  _start(NULL),
+  _end(NULL),
+  _option_buf(),
+  _print_raw(0),
+  _cur_insn(NULL),
+  _bytes_per_line(0),
+  _pre_decode_alignment(0),
+  _post_decode_alignment(0),
+  _print_file_name(false),
+  _print_help(false),
+  _helpPrinted(false) {
 
+  memset(_option_buf, 0, sizeof(_option_buf));
   process_options(_output);
 }
 
-decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) {
-   memset(this, 0, sizeof(*this)); // Beware, this zeroes bits of fields.
-   _output = output ? output : tty;
-  _codeBlob    = code;
-  _codeBuffer  = NULL;
-  _helpPrinted = false;
-  if (_codeBlob != NULL && _codeBlob->is_nmethod()) {
-    _nm = (nmethod*) code;
-  }
+decode_env::decode_env(CodeBlob* code, outputStream* output, CodeStrings c) :
+  _output(output ? output : tty),
+  _codeBuffer(NULL),
+  _codeBlob(code),
+  _nm(_codeBlob != NULL && _codeBlob->is_nmethod() ? (nmethod*) code : NULL),
+  _strings(),
+  _start(NULL),
+  _end(NULL),
+  _option_buf(),
+  _print_raw(0),
+  _cur_insn(NULL),
+  _bytes_per_line(0),
+  _pre_decode_alignment(0),
+  _post_decode_alignment(0),
+  _print_file_name(false),
+  _print_help(false),
+  _helpPrinted(false) {
+
+  memset(_option_buf, 0, sizeof(_option_buf));
   _strings.copy(c);
-
   process_options(_output);
 }
 
-decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) {
-  memset(this, 0, sizeof(*this)); // Beware, this zeroes bits of fields.
-  _output = output ? output : tty;
-  _codeBlob    = NULL;
-  _codeBuffer  = NULL;
-  _nm          = code;
-  _start       = _nm->code_begin();
-  _end         = _nm->code_end();
-  _helpPrinted = false;
+decode_env::decode_env(nmethod* code, outputStream* output, CodeStrings c) :
+  _output(output ? output : tty),
+  _codeBuffer(NULL),
+  _codeBlob(NULL),
+  _nm(code),
+  _strings(),
+  _start(_nm->code_begin()),
+  _end(_nm->code_end()),
+  _option_buf(),
+  _print_raw(0),
+  _cur_insn(NULL),
+  _bytes_per_line(0),
+  _pre_decode_alignment(0),
+  _post_decode_alignment(0),
+  _print_file_name(false),
+  _print_help(false),
+  _helpPrinted(false) {
+
+  memset(_option_buf, 0, sizeof(_option_buf));
   _strings.copy(c);
-
   process_options(_output);
 }
 
 // Constructor for a 'decode_env' to decode a memory range [start, end)
 // of unknown origin, assuming it contains code.
-decode_env::decode_env(address start, address end, outputStream* output) {
+decode_env::decode_env(address start, address end, outputStream* output) :
+  _output(output ? output : tty),
+  _codeBuffer(NULL),
+  _codeBlob(NULL),
+  _nm(NULL),
+  _strings(),
+  _start(start),
+  _end(end),
+  _option_buf(),
+  _print_raw(0),
+  _cur_insn(NULL),
+  _bytes_per_line(0),
+  _pre_decode_alignment(0),
+  _post_decode_alignment(0),
+  _print_file_name(false),
+  _print_help(false),
+  _helpPrinted(false) {
+
   assert(start < end, "Range must have a positive size, [" PTR_FORMAT ".." PTR_FORMAT ").", p2i(start), p2i(end));
-  memset(this, 0, sizeof(*this));
-  _output = output ? output : tty;
-  _codeBlob    = NULL;
-  _codeBuffer  = NULL;
-  _start       = start;
-  _end         = end;
-  _helpPrinted = false;
-
+  memset(_option_buf, 0, sizeof(_option_buf));
   process_options(_output);
 }
 
--- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -35,7 +35,6 @@
   _old_length = g1_heap->old_regions_count();
   _archive_length = g1_heap->archive_regions_count();
   _humongous_length = g1_heap->humongous_regions_count();
-  _metaspace_used_bytes = MetaspaceUtils::used_bytes();
 }
 
 G1HeapTransition::G1HeapTransition(G1CollectedHeap* g1_heap) : _g1_heap(g1_heap), _before(g1_heap) { }
@@ -131,5 +130,5 @@
   log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K",
       usage._humongous_used / K, ((after._humongous_length * HeapRegion::GrainBytes) - usage._humongous_used) / K);
 
-  MetaspaceUtils::print_metaspace_change(_before._metaspace_used_bytes);
+  MetaspaceUtils::print_metaspace_change(_before._meta_sizes);
 }
--- a/src/hotspot/share/gc/g1/g1HeapTransition.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -26,6 +26,7 @@
 #define SHARE_GC_G1_G1HEAPTRANSITION_HPP
 
 #include "gc/shared/plab.hpp"
+#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
 
 class G1CollectedHeap;
 
@@ -36,7 +37,7 @@
     size_t _old_length;
     size_t _archive_length;
     size_t _humongous_length;
-    size_t _metaspace_used_bytes;
+    const metaspace::MetaspaceSizesSnapshot _meta_sizes;
 
     Data(G1CollectedHeap* g1_heap);
   };
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -912,11 +912,20 @@
   Tickspan _rem_set_root_scan_time;
   Tickspan _rem_set_trim_partially_time;
 
-  void scan_memregion(uint region_idx_for_card, MemRegion mr) {
+  // The address to which this thread already scanned (walked the heap) up to during
+  // card scanning (exclusive).
+  HeapWord* _scanned_to;
+
+  HeapWord* scan_memregion(uint region_idx_for_card, MemRegion mr) {
     HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
     G1ScanCardClosure card_cl(_g1h, _pss);
-    card_region->oops_on_card_seq_iterate_careful<true>(mr, &card_cl);
+
+    HeapWord* const scanned_to = card_region->oops_on_memregion_seq_iterate_careful<true>(mr, &card_cl);
+    assert(scanned_to != NULL, "Should be able to scan range");
+    assert(scanned_to >= mr.end(), "Scanned to " PTR_FORMAT " less than range " PTR_FORMAT, p2i(scanned_to), p2i(mr.end()));
+
     _pss->trim_queue_partially();
+    return scanned_to;
   }
 
   void do_claimed_block(uint const region_idx_for_card, size_t const first_card, size_t const num_cards) {
@@ -931,8 +940,12 @@
       return;
     }
 
-    MemRegion mr(card_start, MIN2(card_start + ((size_t)num_cards << BOTConstants::LogN_words), top));
-    scan_memregion(region_idx_for_card, mr);
+    HeapWord* scan_end = MIN2(card_start + (num_cards << BOTConstants::LogN_words), top);
+    if (_scanned_to >= scan_end) {
+      return;
+    }
+    MemRegion mr(MAX2(card_start, _scanned_to), scan_end);
+    _scanned_to = scan_memregion(region_idx_for_card, mr);
 
     _cards_scanned += num_cards;
   }
@@ -951,6 +964,12 @@
 
     G1CardTableChunkClaimer claim(_scan_state, region_idx);
 
+    // Set the current scan "finger" to NULL for every heap region to scan. Since
+    // the claim value is monotonically increasing, the check to not scan below this
+    // will filter out objects spanning chunks within the region too then, as opposed
+    // to resetting this value for every claim.
+    _scanned_to = NULL;
+
     while (claim.has_next()) {
       size_t const region_card_base_idx = ((size_t)region_idx << HeapRegion::LogCardsPerRegion) + claim.value();
       CardTable::CardValue* const base_addr = _ct->byte_for_index(region_card_base_idx);
@@ -994,7 +1013,8 @@
     _blocks_scanned(0),
     _chunks_claimed(0),
     _rem_set_root_scan_time(),
-    _rem_set_trim_partially_time() {
+    _rem_set_trim_partially_time(),
+    _scanned_to(NULL) {
   }
 
   bool do_heap_region(HeapRegion* r) {
@@ -1292,7 +1312,7 @@
   assert(!dirty_region.is_empty(), "sanity");
 
   G1ConcurrentRefineOopClosure conc_refine_cl(_g1h, worker_i);
-  if (r->oops_on_card_seq_iterate_careful<false>(dirty_region, &conc_refine_cl)) {
+  if (r->oops_on_memregion_seq_iterate_careful<false>(dirty_region, &conc_refine_cl) != NULL) {
     _num_conc_refined_cards++; // Unsynchronized update, only used for logging.
     return;
   }
--- a/src/hotspot/share/gc/g1/heapRegion.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -289,14 +289,17 @@
   // for the collection set.
   double _predicted_elapsed_time_ms;
 
-  // Iterate over the references in a humongous objects and apply the given closure
-  // to them.
+  // Iterate over the references covered by the given MemRegion in a humongous
+  // object and apply the given closure to them.
   // Humongous objects are allocated directly in the old-gen. So we need special
   // handling for concurrent processing encountering an in-progress allocation.
+  // Returns the address after the last actually scanned or NULL if the area could
+  // not be scanned (That should only happen when invoked concurrently with the
+  // mutator).
   template <class Closure, bool is_gc_active>
-  inline bool do_oops_on_card_in_humongous(MemRegion mr,
-                                           Closure* cl,
-                                           G1CollectedHeap* g1h);
+  inline HeapWord* do_oops_on_memregion_in_humongous(MemRegion mr,
+                                                     Closure* cl,
+                                                     G1CollectedHeap* g1h);
 
   // Returns the block size of the given (dead, potentially having its class unloaded) object
   // starting at p extending to at most the prev TAMS using the given mark bitmap.
@@ -645,18 +648,16 @@
     }
   }
 
-  // Iterate over the objects overlapping part of a card, applying cl
+  // Iterate over the objects overlapping the given memory region, applying cl
   // to all references in the region.  This is a helper for
   // G1RemSet::refine_card*, and is tightly coupled with them.
-  // mr is the memory region covered by the card, trimmed to the
-  // allocated space for this region.  Must not be empty.
+  // mr must not be empty. Must be trimmed to the allocated/parseable space in this region.
   // This region must be old or humongous.
-  // Returns true if the designated objects were successfully
-  // processed, false if an unparsable part of the heap was
-  // encountered; that only happens when invoked concurrently with the
-  // mutator.
+  // Returns the next unscanned address if the designated objects were successfully
+  // processed, NULL if an unparseable part of the heap was encountered (That should
+  // only happen when invoked concurrently with the mutator).
   template <bool is_gc_active, class Closure>
-  inline bool oops_on_card_seq_iterate_careful(MemRegion mr, Closure* cl);
+  inline HeapWord* oops_on_memregion_seq_iterate_careful(MemRegion mr, Closure* cl);
 
   size_t recorded_rs_length() const        { return _recorded_rs_length; }
   double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; }
--- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -257,9 +257,9 @@
 }
 
 template <class Closure, bool is_gc_active>
-bool HeapRegion::do_oops_on_card_in_humongous(MemRegion mr,
-                                              Closure* cl,
-                                              G1CollectedHeap* g1h) {
+HeapWord* HeapRegion::do_oops_on_memregion_in_humongous(MemRegion mr,
+                                                        Closure* cl,
+                                                        G1CollectedHeap* g1h) {
   assert(is_humongous(), "precondition");
   HeapRegion* sr = humongous_start_region();
   oop obj = oop(sr->bottom());
@@ -271,41 +271,48 @@
   // since the allocating thread could have performed a write to the
   // card that might be missed otherwise.
   if (!is_gc_active && (obj->klass_or_null_acquire() == NULL)) {
-    return false;
+    return NULL;
   }
 
   // We have a well-formed humongous object at the start of sr.
   // Only filler objects follow a humongous object in the containing
   // regions, and we can ignore those.  So only process the one
   // humongous object.
-  if (!g1h->is_obj_dead(obj, sr)) {
-    if (obj->is_objArray() || (sr->bottom() < mr.start())) {
-      // objArrays are always marked precisely, so limit processing
-      // with mr.  Non-objArrays might be precisely marked, and since
-      // it's humongous it's worthwhile avoiding full processing.
-      // However, the card could be stale and only cover filler
-      // objects.  That should be rare, so not worth checking for;
-      // instead let it fall out from the bounded iteration.
-      obj->oop_iterate(cl, mr);
-    } else {
-      // If obj is not an objArray and mr contains the start of the
-      // obj, then this could be an imprecise mark, and we need to
-      // process the entire object.
-      obj->oop_iterate(cl);
-    }
+  if (g1h->is_obj_dead(obj, sr)) {
+    // The object is dead. There can be no other object in this region, so return
+    // the end of that region.
+    return end();
   }
-  return true;
+  if (obj->is_objArray() || (sr->bottom() < mr.start())) {
+    // objArrays are always marked precisely, so limit processing
+    // with mr.  Non-objArrays might be precisely marked, and since
+    // it's humongous it's worthwhile avoiding full processing.
+    // However, the card could be stale and only cover filler
+    // objects.  That should be rare, so not worth checking for;
+    // instead let it fall out from the bounded iteration.
+    obj->oop_iterate(cl, mr);
+    return mr.end();
+  } else {
+    // If obj is not an objArray and mr contains the start of the
+    // obj, then this could be an imprecise mark, and we need to
+    // process the entire object.
+    int size = obj->oop_iterate_size(cl);
+    // We have scanned to the end of the object, but since there can be no objects
+    // after this humongous object in the region, we can return the end of the
+    // region if it is greater.
+    return MAX2((HeapWord*)obj + size, mr.end());
+  }
 }
 
 template <bool is_gc_active, class Closure>
-bool HeapRegion::oops_on_card_seq_iterate_careful(MemRegion mr,
-                                                  Closure* cl) {
+HeapWord* HeapRegion::oops_on_memregion_seq_iterate_careful(MemRegion mr,
+                                                       Closure* cl) {
   assert(MemRegion(bottom(), end()).contains(mr), "Card region not in heap region");
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
   // Special handling for humongous regions.
   if (is_humongous()) {
-    return do_oops_on_card_in_humongous<Closure, is_gc_active>(mr, cl, g1h);
+    return do_oops_on_memregion_in_humongous<Closure, is_gc_active>(mr, cl, g1h);
   }
   assert(is_old() || is_archive(), "Wrongly trying to iterate over region %u type %s", _hrm_index, get_type_str());
 
@@ -334,7 +341,7 @@
 #endif
 
   const G1CMBitMap* const bitmap = g1h->concurrent_mark()->prev_mark_bitmap();
-  do {
+  while (true) {
     oop obj = oop(cur);
     assert(oopDesc::is_oop(obj, true), "Not an oop at " PTR_FORMAT, p2i(cur));
     assert(obj->klass_or_null() != NULL,
@@ -342,6 +349,7 @@
 
     size_t size;
     bool is_dead = is_obj_dead_with_size(obj, bitmap, &size);
+    bool is_precise = false;
 
     cur += size;
     if (!is_dead) {
@@ -355,11 +363,13 @@
         obj->oop_iterate(cl);
       } else {
         obj->oop_iterate(cl, mr);
+        is_precise = true;
       }
     }
-  } while (cur < end);
-
-  return true;
+    if (cur >= end) {
+      return is_precise ? end : cur;
+    }
+  }
 }
 
 #endif // SHARE_GC_G1_HEAPREGION_INLINE_HPP
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -38,6 +38,7 @@
 #include "gc/shared/strongRootsScope.hpp"
 #include "logging/log.hpp"
 #include "memory/metaspace.hpp"
+#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/ostream.hpp"
 
@@ -257,19 +258,18 @@
   PreGCValues(ParallelScavengeHeap* heap) :
       _heap_used(heap->used()),
       _young_gen_used(heap->young_gen()->used_in_bytes()),
-      _old_gen_used(heap->old_gen()->used_in_bytes()),
-      _metadata_used(MetaspaceUtils::used_bytes()) { };
+      _old_gen_used(heap->old_gen()->used_in_bytes()) { }
 
   size_t heap_used() const      { return _heap_used; }
   size_t young_gen_used() const { return _young_gen_used; }
   size_t old_gen_used() const   { return _old_gen_used; }
-  size_t metadata_used() const  { return _metadata_used; }
+  const metaspace::MetaspaceSizesSnapshot& metaspace_sizes() const { return _meta_sizes; }
 
 private:
   size_t _heap_used;
   size_t _young_gen_used;
   size_t _old_gen_used;
-  size_t _metadata_used;
+  const metaspace::MetaspaceSizesSnapshot _meta_sizes;
 };
 
 // Class that can be used to print information about the
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -193,11 +193,7 @@
 
     BiasedLocking::preserve_marks();
 
-    // Capture metadata size before collection for sizing.
-    size_t metadata_prev_used = MetaspaceUtils::used_bytes();
-
-    size_t old_gen_prev_used = old_gen->used_in_bytes();
-    size_t young_gen_prev_used = young_gen->used_in_bytes();
+    const PreGCValues pre_gc_values(heap);
 
     allocate_stacks();
 
@@ -352,9 +348,9 @@
       accumulated_time()->stop();
     }
 
-    young_gen->print_used_change(young_gen_prev_used);
-    old_gen->print_used_change(old_gen_prev_used);
-    MetaspaceUtils::print_metaspace_change(metadata_prev_used);
+    young_gen->print_used_change(pre_gc_values.young_gen_used());
+    old_gen->print_used_change(pre_gc_values.old_gen_used());
+    MetaspaceUtils::print_metaspace_change(pre_gc_values.metaspace_sizes());
 
     // Track memory usage and detect low memory
     MemoryService::track_memory_usage();
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1779,7 +1779,7 @@
   // miscellaneous bookkeeping.
   pre_compact();
 
-  PreGCValues pre_gc_values(heap);
+  const PreGCValues pre_gc_values(heap);
 
   // Get the compaction manager reserved for the VM thread.
   ParCompactionManager* const vmthread_cm =
@@ -1925,7 +1925,7 @@
 
     young_gen->print_used_change(pre_gc_values.young_gen_used());
     old_gen->print_used_change(pre_gc_values.old_gen_used());
-    MetaspaceUtils::print_metaspace_change(pre_gc_values.metadata_used());
+    MetaspaceUtils::print_metaspace_change(pre_gc_values.metaspace_sizes());
 
     // Track memory usage and detect low memory
     MemoryService::track_memory_usage();
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -328,7 +328,7 @@
     reference_processor()->enable_discovery();
     reference_processor()->setup_policy(false);
 
-    PreGCValues pre_gc_values(heap);
+    const PreGCValues pre_gc_values(heap);
 
     // Reset our survivor overflow.
     set_survivor_overflow(false);
@@ -601,7 +601,7 @@
 
     young_gen->print_used_change(pre_gc_values.young_gen_used());
     old_gen->print_used_change(pre_gc_values.old_gen_used());
-    MetaspaceUtils::print_metaspace_change(pre_gc_values.metadata_used());
+    MetaspaceUtils::print_metaspace_change(pre_gc_values.metaspace_sizes());
 
     // Track memory usage and detect low memory
     MemoryService::track_memory_usage();
--- a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -137,6 +137,8 @@
 
   virtual LIR_Opr resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj);
 
+  virtual const char* rtcall_name_for_address(address entry) { return NULL; }
+
   virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob) {}
 };
 
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -267,6 +267,7 @@
   virtual bool has_load_barriers() const { return false; }
   virtual bool is_gc_barrier_node(Node* node) const { return false; }
   virtual Node* step_over_gc_barrier(Node* c) const { return c; }
+  virtual Node* step_over_gc_barrier_ctrl(Node* c) const { return c; }
 
   // Support for macro expanded GC barriers
   virtual void register_potential_barrier_node(Node* node) const { }
--- a/src/hotspot/share/gc/shared/gcBehaviours.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shared/gcBehaviours.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -64,7 +64,7 @@
 bool ClosureIsUnloadingBehaviour::is_unloading(CompiledMethod* cm) const {
   if (cm->is_nmethod()) {
     IsCompiledMethodUnloadingOopClosure cl(_cl);
-    static_cast<nmethod*>(cm)->oops_do(&cl);
+    static_cast<nmethod*>(cm)->oops_do(&cl, true /* allow_dead */);
     return cl.is_unloading();
   } else {
     return false;
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -575,9 +575,6 @@
 
   ClearedAllSoftRefs casr(do_clear_all_soft_refs, soft_ref_policy());
 
-  const size_t metadata_prev_used = MetaspaceUtils::used_bytes();
-
-
   FlagSetting fl(_is_gc_active, true);
 
   bool complete = full && (max_generation == OldGen);
@@ -586,6 +583,7 @@
 
   size_t young_prev_used = _young_gen->used();
   size_t old_prev_used = _old_gen->used();
+  const metaspace::MetaspaceSizesSnapshot prev_meta_sizes;
 
   bool run_verification = total_collections() >= VerifyGCStartAt;
   bool prepared_for_verification = false;
@@ -628,7 +626,7 @@
       _young_gen->compute_new_size();
 
       print_heap_change(young_prev_used, old_prev_used);
-      MetaspaceUtils::print_metaspace_change(metadata_prev_used);
+      MetaspaceUtils::print_metaspace_change(prev_meta_sizes);
 
       // Track memory usage and detect low memory after GC finishes
       MemoryService::track_memory_usage();
@@ -687,7 +685,7 @@
     update_full_collections_completed();
 
     print_heap_change(young_prev_used, old_prev_used);
-    MetaspaceUtils::print_metaspace_change(metadata_prev_used);
+    MetaspaceUtils::print_metaspace_change(prev_meta_sizes);
 
     // Track memory usage and detect low memory after GC finishes
     MemoryService::track_memory_usage();
--- a/src/hotspot/share/gc/shared/oopStorage.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -35,6 +35,7 @@
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/orderAccess.hpp"
+#include "runtime/os.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.hpp"
@@ -414,14 +415,6 @@
 oop* OopStorage::allocate() {
   MutexLocker ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
 
-  // Note: Without this we might never perform cleanup.  As it is,
-  // cleanup is only requested here, when completing a concurrent
-  // iteration, or when someone entirely else wakes up the service
-  // thread, which isn't ideal.  But we can't notify in release().
-  if (reduce_deferred_updates()) {
-    notify_needs_cleanup();
-  }
-
   Block* block = block_for_allocation();
   if (block == NULL) return NULL; // Block allocation failed.
   assert(!block->is_full(), "invariant");
@@ -474,23 +467,20 @@
 
 OopStorage::Block* OopStorage::block_for_allocation() {
   assert_lock_strong(_allocation_mutex);
-
   while (true) {
     // Use the first block in _allocation_list for the allocation.
     Block* block = _allocation_list.head();
     if (block != NULL) {
       return block;
     } else if (reduce_deferred_updates()) {
-      MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
-      notify_needs_cleanup();
+      // Might have added a block to the _allocation_list, so retry.
     } else if (try_add_block()) {
-      block = _allocation_list.head();
-      assert(block != NULL, "invariant");
-      return block;
-    } else if (reduce_deferred_updates()) { // Once more before failure.
-      MutexUnlocker ul(_allocation_mutex, Mutex::_no_safepoint_check_flag);
-      notify_needs_cleanup();
-    } else {
+      // Successfully added a new block to the list, so retry.
+      assert(_allocation_list.chead() != NULL, "invariant");
+    } else if (_allocation_list.chead() != NULL) {
+      // Trying to add a block failed, but some other thread added to the
+      // list while we'd dropped the lock over the new block allocation.
+    } else if (!reduce_deferred_updates()) { // Once more before failure.
       // Attempt to add a block failed, no other thread added a block,
       // and no deferred updated added a block, then allocation failed.
       log_debug(oopstorage, blocks)("%s: failed block allocation", name());
@@ -635,7 +625,14 @@
         if (fetched == head) break; // Successful update.
         head = fetched;             // Retry with updated head.
       }
-      owner->record_needs_cleanup();
+      // Only request cleanup for to-empty transitions, not for from-full.
+      // There isn't any rush to process from-full transitions.  Allocation
+      // will reduce deferrals before allocating new blocks, so may process
+      // some.  And the service thread will drain the entire deferred list
+      // if there are any pending to-empty transitions.
+      if (releasing == old_allocated) {
+        owner->record_needs_cleanup();
+      }
       log_debug(oopstorage, blocks)("%s: deferred update " PTR_FORMAT,
                                     _owner->name(), p2i(this));
     }
@@ -684,7 +681,6 @@
   if (is_empty_bitmask(allocated)) {
     _allocation_list.unlink(*block);
     _allocation_list.push_back(*block);
-    notify_needs_cleanup();
   }
 
   log_debug(oopstorage, blocks)("%s: processed deferred update " PTR_FORMAT,
@@ -734,23 +730,12 @@
   }
 }
 
-const char* dup_name(const char* name) {
-  char* dup = NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtGC);
-  strcpy(dup, name);
-  return dup;
-}
-
-// Possible values for OopStorage::_needs_cleanup.
-const uint needs_cleanup_none = 0;     // No cleanup needed.
-const uint needs_cleanup_marked = 1;   // Requested, but no notification made.
-const uint needs_cleanup_notified = 2; // Requested and Service thread notified.
-
 const size_t initial_active_array_size = 8;
 
 OopStorage::OopStorage(const char* name,
                        Mutex* allocation_mutex,
                        Mutex* active_mutex) :
-  _name(dup_name(name)),
+  _name(os::strdup(name)),
   _active_array(ActiveArray::create(initial_active_array_size)),
   _allocation_list(),
   _deferred_updates(NULL),
@@ -758,7 +743,7 @@
   _active_mutex(active_mutex),
   _allocation_count(0),
   _concurrent_iteration_count(0),
-  _needs_cleanup(needs_cleanup_none)
+  _needs_cleanup(false)
 {
   _active_array->increment_refcount();
   assert(_active_mutex->rank() < _allocation_mutex->rank(),
@@ -793,43 +778,92 @@
     Block::delete_block(*block);
   }
   ActiveArray::destroy(_active_array);
-  FREE_C_HEAP_ARRAY(char, _name);
+  os::free(const_cast<char*>(_name));
 }
 
-// Called by service thread to check for pending work.
-bool OopStorage::needs_delete_empty_blocks() const {
-  return Atomic::load(&_needs_cleanup) != needs_cleanup_none;
+// Managing service thread notifications.
+//
+// We don't want cleanup work to linger indefinitely, but we also don't want
+// to run the service thread too often.  We're also very limited in what we
+// can do in a release operation, where cleanup work is created.
+//
+// When a release operation changes a block's state to empty, it records the
+// need for cleanup in both the associated storage object and in the global
+// request state.  A safepoint cleanup task notifies the service thread when
+// there may be cleanup work for any storage object, based on the global
+// request state.  But that notification is deferred if the service thread
+// has run recently, and we also avoid duplicate notifications.  The service
+// thread updates the timestamp and resets the state flags on every iteration.
+
+// Global cleanup request state.
+static volatile bool needs_cleanup_requested = false;
+
+// Flag for avoiding duplicate notifications.
+static bool needs_cleanup_triggered = false;
+
+// Time after which a notification can be made.
+static jlong cleanup_trigger_permit_time = 0;
+
+// Minimum time since last service thread check before notification is
+// permitted.  The value of 500ms was an arbitrary choice; frequent, but not
+// too frequent.
+const jlong cleanup_trigger_defer_period = 500 * NANOSECS_PER_MILLISEC;
+
+void OopStorage::trigger_cleanup_if_needed() {
+  MonitorLocker ml(Service_lock, Monitor::_no_safepoint_check_flag);
+  if (Atomic::load(&needs_cleanup_requested) &&
+      !needs_cleanup_triggered &&
+      (os::javaTimeNanos() > cleanup_trigger_permit_time)) {
+    needs_cleanup_triggered = true;
+    ml.notify_all();
+  }
+}
+
+bool OopStorage::has_cleanup_work_and_reset() {
+  assert_lock_strong(Service_lock);
+  cleanup_trigger_permit_time =
+    os::javaTimeNanos() + cleanup_trigger_defer_period;
+  needs_cleanup_triggered = false;
+  // Set the request flag false and return its old value.
+  // Needs to be atomic to avoid dropping a concurrent request.
+  // Can't use Atomic::xchg, which may not support bool.
+  return Atomic::cmpxchg(false, &needs_cleanup_requested, true);
 }
 
 // Record that cleanup is needed, without notifying the Service thread.
 // Used by release(), where we can't lock even Service_lock.
 void OopStorage::record_needs_cleanup() {
-  Atomic::cmpxchg(needs_cleanup_marked, &_needs_cleanup, needs_cleanup_none);
-}
-
-// Record that cleanup is needed, and notify the Service thread.
-void OopStorage::notify_needs_cleanup() {
-  // Avoid re-notification if already notified.
-  const uint notified = needs_cleanup_notified;
-  if (Atomic::xchg(notified, &_needs_cleanup) != notified) {
-    MonitorLocker ml(Service_lock, Monitor::_no_safepoint_check_flag);
-    ml.notify_all();
-  }
+  // Set local flag first, else service thread could wake up and miss
+  // the request.  This order may instead (rarely) unnecessarily notify.
+  OrderAccess::release_store(&_needs_cleanup, true);
+  OrderAccess::release_store_fence(&needs_cleanup_requested, true);
 }
 
 bool OopStorage::delete_empty_blocks() {
+  // Service thread might have oopstorage work, but not for this object.
+  // Check for deferred updates even though that's not a service thread
+  // trigger; since we're here, we might as well process them.
+  if (!OrderAccess::load_acquire(&_needs_cleanup) &&
+      (OrderAccess::load_acquire(&_deferred_updates) == NULL)) {
+    return false;
+  }
+
   MutexLocker ml(_allocation_mutex, Mutex::_no_safepoint_check_flag);
 
   // Clear the request before processing.
-  Atomic::store(needs_cleanup_none, &_needs_cleanup);
-  OrderAccess::fence();
+  OrderAccess::release_store_fence(&_needs_cleanup, false);
 
   // Other threads could be adding to the empty block count or the
   // deferred update list while we're working.  Set an upper bound on
   // how many updates we'll process and blocks we'll try to release,
   // so other threads can't cause an unbounded stay in this function.
-  size_t limit = block_count();
-  if (limit == 0) return false; // Empty storage; nothing at all to do.
+  // We add a bit of slop because the reduce_deferred_updates clause
+  // can cause blocks to be double counted.  If there are few blocks
+  // and many of them are deferred and empty, we might hit the limit
+  // and spin the caller without doing very much work.  Otherwise,
+  // we don't normally hit the limit anyway, instead running out of
+  // work to do.
+  size_t limit = block_count() + 10;
 
   for (size_t i = 0; i < limit; ++i) {
     // Process deferred updates, which might make empty blocks available.
@@ -946,8 +980,8 @@
   _storage->relinquish_block_array(_active_array);
   update_concurrent_iteration_count(-1);
   if (_concurrent) {
-    // We may have deferred some work.
-    const_cast<OopStorage*>(_storage)->notify_needs_cleanup();
+    // We may have deferred some cleanup work.
+    const_cast<OopStorage*>(_storage)->record_needs_cleanup();
   }
 }
 
--- a/src/hotspot/share/gc/shared/oopStorage.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shared/oopStorage.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -152,18 +152,26 @@
   template<bool concurrent, bool is_const> class ParState;
 
   // Service thread cleanup support.
-  // Stops deleting if there is an in-progress concurrent iteration.
-  // Locks both the _allocation_mutex and the _active_mutex, and may
-  // safepoint.  Deletion may be throttled, with only some available
-  // work performed, in order to allow other Service thread subtasks
-  // to run.  Returns true if there may be more work to do, false if
-  // nothing to do.
+
+  // Called by the service thread to process any pending cleanups for this
+  // storage object.  Drains the _deferred_updates list, and deletes empty
+  // blocks.  Stops deleting if there is an in-progress concurrent
+  // iteration.  Locks both the _allocation_mutex and the _active_mutex, and
+  // may safepoint.  Deletion may be throttled, with only some available
+  // work performed, in order to allow other Service thread subtasks to run.
+  // Returns true if there may be more work to do, false if nothing to do.
   bool delete_empty_blocks();
 
-  // Service thread cleanup support.
-  // Called by the service thread (while holding Service_lock) to test
-  // whether a call to delete_empty_blocks should be made.
-  bool needs_delete_empty_blocks() const;
+  // Called by safepoint cleanup to notify the service thread (via
+  // Service_lock) that there may be some OopStorage objects with pending
+  // cleanups to process.
+  static void trigger_cleanup_if_needed();
+
+  // Called by the service thread (while holding Service_lock) to to test
+  // for pending cleanup requests, and resets the request state to allow
+  // recognition of new requests.  Returns true if there was a pending
+  // request.
+  static bool has_cleanup_work_and_reset();
 
   // Debugging and logging support.
   const char* name() const;
@@ -232,7 +240,7 @@
   // mutable because this gets set even for const iteration.
   mutable int _concurrent_iteration_count;
 
-  volatile uint _needs_cleanup;
+  volatile bool _needs_cleanup;
 
   bool try_add_block();
   Block* block_for_allocation();
@@ -240,7 +248,6 @@
   Block* find_block_or_null(const oop* ptr) const;
   void delete_empty_block(const Block& block);
   bool reduce_deferred_updates();
-  void notify_needs_cleanup();
 AIX_ONLY(public:)               // xlC 12 on AIX doesn't implement C++ DR45.
   void record_needs_cleanup();
 AIX_ONLY(private:)
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -35,18 +35,7 @@
   ShenandoahHeuristics(),
   _cycle_gap_history(new TruncatedSeq(5)),
   _conc_mark_duration_history(new TruncatedSeq(5)),
-  _conc_uprefs_duration_history(new TruncatedSeq(5)) {
-
-  SHENANDOAH_ERGO_ENABLE_FLAG(ExplicitGCInvokesConcurrent);
-  SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
-
-  // Final configuration checks
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahSATBBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahKeepAliveBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
-}
+  _conc_uprefs_duration_history(new TruncatedSeq(5)) {}
 
 ShenandoahAdaptiveHeuristics::~ShenandoahAdaptiveHeuristics() {}
 
@@ -121,7 +110,7 @@
   } // Else ignore
 }
 
-bool ShenandoahAdaptiveHeuristics::should_start_normal_gc() const {
+bool ShenandoahAdaptiveHeuristics::should_start_gc() const {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
   size_t capacity = heap->max_capacity();
   size_t available = heap->free_set()->available();
@@ -172,7 +161,7 @@
     return true;
   }
 
-  return ShenandoahHeuristics::should_start_normal_gc();
+  return ShenandoahHeuristics::should_start_gc();
 }
 
 bool ShenandoahAdaptiveHeuristics::should_start_update_refs() {
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -47,7 +47,7 @@
 
   virtual void record_phase_time(ShenandoahPhaseTimings::Phase phase, double secs);
 
-  virtual bool should_start_normal_gc() const;
+  virtual bool should_start_gc() const;
 
   virtual bool should_start_update_refs();
 
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -65,7 +65,7 @@
   }
 }
 
-bool ShenandoahAggressiveHeuristics::should_start_normal_gc() const {
+bool ShenandoahAggressiveHeuristics::should_start_gc() const {
   log_info(gc)("Trigger: Start next cycle immediately");
   return true;
 }
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -34,7 +34,7 @@
                                                      RegionData* data, size_t size,
                                                      size_t free);
 
-  virtual bool should_start_normal_gc() const;
+  virtual bool should_start_gc() const;
 
   virtual bool should_process_references();
 
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -49,7 +49,7 @@
   SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
 }
 
-bool ShenandoahCompactHeuristics::should_start_normal_gc() const {
+bool ShenandoahCompactHeuristics::should_start_gc() const {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
 
   size_t capacity = heap->max_capacity();
@@ -77,7 +77,7 @@
     return true;
   }
 
-  return ShenandoahHeuristics::should_start_normal_gc();
+  return ShenandoahHeuristics::should_start_gc();
 }
 
 void ShenandoahCompactHeuristics::choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset,
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -30,7 +30,7 @@
 public:
   ShenandoahCompactHeuristics();
 
-  virtual bool should_start_normal_gc() const;
+  virtual bool should_start_gc() const;
 
   virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset,
                                                      RegionData* data, size_t size,
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahPassiveHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahPassiveHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -29,32 +29,7 @@
 #include "logging/log.hpp"
 #include "logging/logTag.hpp"
 
-ShenandoahPassiveHeuristics::ShenandoahPassiveHeuristics() : ShenandoahHeuristics() {
-  // Do not allow concurrent cycles.
-  FLAG_SET_DEFAULT(ExplicitGCInvokesConcurrent, false);
-  FLAG_SET_DEFAULT(ShenandoahImplicitGCInvokesConcurrent, false);
-
-  // Passive runs with max speed, reacts on allocation failure.
-  FLAG_SET_DEFAULT(ShenandoahPacing, false);
-
-  // No need for evacuation reserve with Full GC, only for Degenerated GC.
-  if (!ShenandoahDegeneratedGC) {
-    SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahEvacReserve, 0);
-  }
-
-  // Disable known barriers by default.
-  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahLoadRefBarrier);
-  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahSATBBarrier);
-  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahKeepAliveBarrier);
-  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValEnqueueBarrier);
-  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCASBarrier);
-  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCloneBarrier);
-
-  // Final configuration checks
-  // No barriers are required to run.
-}
-
-bool ShenandoahPassiveHeuristics::should_start_normal_gc() const {
+bool ShenandoahPassiveHeuristics::should_start_gc() const {
   // Never do concurrent GCs.
   return false;
 }
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -28,9 +28,7 @@
 
 class ShenandoahPassiveHeuristics : public ShenandoahHeuristics {
 public:
-  ShenandoahPassiveHeuristics();
-
-  virtual bool should_start_normal_gc() const;
+   virtual bool should_start_gc() const;
 
   virtual bool should_process_references();
 
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -49,7 +49,7 @@
 
 ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {}
 
-bool ShenandoahStaticHeuristics::should_start_normal_gc() const {
+bool ShenandoahStaticHeuristics::should_start_gc() const {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
 
   size_t capacity = heap->max_capacity();
@@ -61,7 +61,7 @@
                  available / M, threshold_available / M);
     return true;
   }
-  return ShenandoahHeuristics::should_start_normal_gc();
+  return ShenandoahHeuristics::should_start_gc();
 }
 
 void ShenandoahStaticHeuristics::choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset,
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -32,7 +32,7 @@
 
   virtual ~ShenandoahStaticHeuristics();
 
-  virtual bool should_start_normal_gc() const;
+  virtual bool should_start_gc() const;
 
   virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset,
                                                      RegionData* data, size_t size,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalAggressiveHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "gc/shenandoah/heuristics/shenandoahTraversalAggressiveHeuristics.hpp"
+#include "gc/shenandoah/shenandoahCollectionSet.hpp"
+#include "gc/shenandoah/shenandoahFreeSet.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc/shenandoah/shenandoahHeuristics.hpp"
+#include "gc/shenandoah/shenandoahTraversalGC.hpp"
+#include "logging/log.hpp"
+#include "logging/logTag.hpp"
+#include "utilities/quickSort.hpp"
+
+ShenandoahTraversalAggressiveHeuristics::ShenandoahTraversalAggressiveHeuristics() : ShenandoahHeuristics(),
+  _last_cset_select(0) {
+  // Do not shortcut evacuation
+  SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahImmediateThreshold, 100);
+
+  // Aggressive runs with max speed for allocation, to capture races against mutator
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahPacing);
+
+  // Aggressive evacuates everything, so it needs as much evac space as it can get
+  SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahEvacReserveOverflow);
+
+  // If class unloading is globally enabled, aggressive does unloading even with
+  // concurrent cycles.
+  if (ClassUnloading) {
+    SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahUnloadClassesFrequency, 1);
+  }
+
+}
+
+bool ShenandoahTraversalAggressiveHeuristics::is_experimental() {
+  return true;
+}
+
+bool ShenandoahTraversalAggressiveHeuristics::is_diagnostic() {
+  return true;
+}
+
+const char* ShenandoahTraversalAggressiveHeuristics::name() {
+  return "traversal-aggressive";
+}
+
+void ShenandoahTraversalAggressiveHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) {
+  ShenandoahHeap* heap = ShenandoahHeap::heap();
+
+  ShenandoahTraversalGC* traversal_gc = heap->traversal_gc();
+
+  ShenandoahHeapRegionSet* traversal_set = traversal_gc->traversal_set();
+  traversal_set->clear();
+
+  RegionData *data = get_region_data_cache(heap->num_regions());
+  size_t cnt = 0;
+
+  // Step 0. Prepare all regions
+  for (size_t i = 0; i < heap->num_regions(); i++) {
+    ShenandoahHeapRegion* r = heap->get_region(i);
+    if (r->used() > 0) {
+      if (r->is_regular()) {
+        data[cnt]._region = r;
+        data[cnt]._garbage = r->garbage();
+        data[cnt]._seqnum_last_alloc = r->seqnum_last_alloc_mutator();
+        cnt++;
+      }
+      traversal_set->add_region(r);
+    }
+  }
+
+  for (size_t i = 0; i < cnt; i++) {
+    if (data[i]._seqnum_last_alloc > _last_cset_select) continue;
+
+    ShenandoahHeapRegion* r = data[i]._region;
+    assert (r->is_regular(), "should have been filtered before");
+
+   if (r->garbage() > 0) {
+      assert(!collection_set->is_in(r), "must not yet be in cset");
+      collection_set->add_region(r);
+    }
+  }
+
+  // Clear liveness data
+  // TODO: Merge it with step 0, but save live data in RegionData before.
+  for (size_t i = 0; i < heap->num_regions(); i++) {
+    ShenandoahHeapRegion* r = heap->get_region(i);
+    if (r->used() > 0) {
+      r->clear_live_data();
+    }
+  }
+
+  collection_set->update_region_status();
+
+  _last_cset_select = ShenandoahHeapRegion::seqnum_current_alloc();
+}
+
+void ShenandoahTraversalAggressiveHeuristics::choose_collection_set_from_regiondata(ShenandoahCollectionSet* set,
+                                                                                    RegionData* data, size_t data_size,
+                                                                                    size_t free) {
+  ShouldNotReachHere();
+}
+
+bool ShenandoahTraversalAggressiveHeuristics::should_start_gc() const {
+  log_info(gc)("Trigger: Start next cycle immediately");
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalAggressiveHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHTRAVERSALAGGRESSIVEHEURISTICS_HPP
+#define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHTRAVERSALAGGRESSIVEHEURISTICS_HPP
+
+#include "gc/shenandoah/shenandoahHeuristics.hpp"
+
+class ShenandoahTraversalAggressiveHeuristics : public ShenandoahHeuristics {
+private:
+  uint64_t _last_cset_select;
+
+protected:
+  virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set,
+                                                     RegionData* data, size_t data_size,
+                                                     size_t free);
+
+public:
+  ShenandoahTraversalAggressiveHeuristics();
+
+  virtual bool is_experimental();
+
+  virtual bool is_diagnostic();
+
+  virtual const char* name();
+
+  virtual void choose_collection_set(ShenandoahCollectionSet* collection_set);
+  virtual bool should_start_gc() const;
+};
+
+#endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHTRAVERSALAGGRESSIVEHEURISTICS_HPP
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -34,26 +34,7 @@
 #include "utilities/quickSort.hpp"
 
 ShenandoahTraversalHeuristics::ShenandoahTraversalHeuristics() : ShenandoahHeuristics(),
-  _last_cset_select(0)
- {
-  FLAG_SET_DEFAULT(ShenandoahSATBBarrier,            false);
-  FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, true);
-  FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier,       false);
-  FLAG_SET_DEFAULT(ShenandoahAllowMixedAllocs,       false);
-
-  SHENANDOAH_ERGO_ENABLE_FLAG(ExplicitGCInvokesConcurrent);
-  SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
-
-  // Final configuration checks
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValEnqueueBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
-  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
-}
-
-bool ShenandoahTraversalHeuristics::should_start_normal_gc() const {
-  return false;
-}
+  _last_cset_select(0) {}
 
 bool ShenandoahTraversalHeuristics::is_experimental() {
   return true;
@@ -63,10 +44,6 @@
   return false;
 }
 
-bool ShenandoahTraversalHeuristics::can_do_traversal_gc() {
-  return true;
-}
-
 const char* ShenandoahTraversalHeuristics::name() {
   return "traversal";
 }
@@ -202,7 +179,7 @@
   _last_cset_select = ShenandoahHeapRegion::seqnum_current_alloc();
 }
 
-bool ShenandoahTraversalHeuristics::should_start_traversal_gc() {
+bool ShenandoahTraversalHeuristics::should_start_gc() const {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
   assert(!heap->has_forwarded_objects(), "no forwarded objects here");
 
@@ -251,7 +228,7 @@
     log_info(gc, ergo)("Free headroom: " SIZE_FORMAT "M (free) - " SIZE_FORMAT "M (spike) - " SIZE_FORMAT "M (penalties) = " SIZE_FORMAT "M",
                        available / M, spike_headroom / M, penalties / M, allocation_headroom / M);
     return true;
-  } else if (ShenandoahHeuristics::should_start_normal_gc()) {
+  } else if (ShenandoahHeuristics::should_start_gc()) {
     return true;
   }
 
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -38,19 +38,15 @@
 public:
   ShenandoahTraversalHeuristics();
 
-  virtual bool should_start_normal_gc() const;
-
   virtual bool is_experimental();
 
   virtual bool is_diagnostic();
 
-  virtual bool can_do_traversal_gc();
-
   virtual const char* name();
 
   virtual void choose_collection_set(ShenandoahCollectionSet* collection_set);
 
-  virtual bool should_start_traversal_gc();
+  virtual bool should_start_gc() const;
 };
 
 #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHTRAVERSALHEURISTICS_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -170,7 +170,7 @@
       ShenandoahLocker locker(CodeCache_lock->owned_by_self() ? NULL : &_recorded_nms_lock);
 
       ShenandoahNMethodOopDetector detector;
-      nm->oops_do(&detector, /* allow_zombie = */ true);
+      nm->oops_do(&detector, /* allow_dead = */ true);
 
       if (detector.has_oops()) {
         int idx = _recorded_nms->find(nm, ShenandoahNMethod::find_with_nmethod);
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -68,6 +68,10 @@
 void ShenandoahControlThread::run_service() {
   ShenandoahHeap* heap = ShenandoahHeap::heap();
 
+  GCMode default_mode = heap->is_traversal_mode() ?
+                           concurrent_traversal : concurrent_normal;
+  GCCause::Cause default_cause = heap->is_traversal_mode() ?
+                           GCCause::_shenandoah_traversal_gc : GCCause::_shenandoah_concurrent_gc;
   int sleep = ShenandoahControlIntervalMin;
 
   double last_shrink_time = os::elapsedTime();
@@ -123,11 +127,7 @@
 
       if (ExplicitGCInvokesConcurrent) {
         policy->record_explicit_to_concurrent();
-        if (heuristics->can_do_traversal_gc()) {
-          mode = concurrent_traversal;
-        } else {
-          mode = concurrent_normal;
-        }
+        mode = default_mode;
         // Unload and clean up everything
         heap->set_process_references(heuristics->can_process_references());
         heap->set_unload_classes(heuristics->can_unload_classes());
@@ -143,11 +143,7 @@
 
       if (ShenandoahImplicitGCInvokesConcurrent) {
         policy->record_implicit_to_concurrent();
-        if (heuristics->can_do_traversal_gc()) {
-          mode = concurrent_traversal;
-        } else {
-          mode = concurrent_normal;
-        }
+        mode = default_mode;
 
         // Unload and clean up everything
         heap->set_process_references(heuristics->can_process_references());
@@ -158,12 +154,9 @@
       }
     } else {
       // Potential normal cycle: ask heuristics if it wants to act
-      if (heuristics->should_start_traversal_gc()) {
-        mode = concurrent_traversal;
-        cause = GCCause::_shenandoah_traversal_gc;
-      } else if (heuristics->should_start_normal_gc()) {
-        mode = concurrent_normal;
-        cause = GCCause::_shenandoah_concurrent_gc;
+      if (heuristics->should_start_gc()) {
+        mode = default_mode;
+        cause = default_cause;
       }
 
       // Ask policy if this cycle wants to process references or unload classes
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -50,23 +50,20 @@
 #include "gc/shenandoah/shenandoahMemoryPool.hpp"
 #include "gc/shenandoah/shenandoahMetrics.hpp"
 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
+#include "gc/shenandoah/shenandoahNormalMode.hpp"
 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
 #include "gc/shenandoah/shenandoahPacer.inline.hpp"
+#include "gc/shenandoah/shenandoahPassiveMode.hpp"
 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
 #include "gc/shenandoah/shenandoahStringDedup.hpp"
 #include "gc/shenandoah/shenandoahTaskqueue.hpp"
+#include "gc/shenandoah/shenandoahTraversalMode.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
 #include "gc/shenandoah/shenandoahVerifier.hpp"
 #include "gc/shenandoah/shenandoahCodeRoots.hpp"
 #include "gc/shenandoah/shenandoahVMOperations.hpp"
 #include "gc/shenandoah/shenandoahWorkGroup.hpp"
 #include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
-#include "gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp"
-#include "gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.hpp"
-#include "gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp"
-#include "gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp"
-#include "gc/shenandoah/heuristics/shenandoahStaticHeuristics.hpp"
-#include "gc/shenandoah/heuristics/shenandoahTraversalHeuristics.hpp"
 #if INCLUDE_JFR
 #include "gc/shenandoah/shenandoahJfrSupport.hpp"
 #endif
@@ -367,7 +364,7 @@
     _pacer = NULL;
   }
 
-  _traversal_gc = heuristics()->can_do_traversal_gc() ?
+  _traversal_gc = strcmp(ShenandoahGCMode, "traversal") == 0 ?
                   new ShenandoahTraversalGC(this, _num_regions) :
                   NULL;
 
@@ -387,39 +384,34 @@
 }
 
 void ShenandoahHeap::initialize_heuristics() {
-  if (ShenandoahGCHeuristics != NULL) {
-    if (strcmp(ShenandoahGCHeuristics, "aggressive") == 0) {
-      _heuristics = new ShenandoahAggressiveHeuristics();
-    } else if (strcmp(ShenandoahGCHeuristics, "static") == 0) {
-      _heuristics = new ShenandoahStaticHeuristics();
-    } else if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) {
-      _heuristics = new ShenandoahAdaptiveHeuristics();
-    } else if (strcmp(ShenandoahGCHeuristics, "passive") == 0) {
-      _heuristics = new ShenandoahPassiveHeuristics();
-    } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) {
-      _heuristics = new ShenandoahCompactHeuristics();
-    } else if (strcmp(ShenandoahGCHeuristics, "traversal") == 0) {
-      _heuristics = new ShenandoahTraversalHeuristics();
+  if (ShenandoahGCMode != NULL) {
+    if (strcmp(ShenandoahGCMode, "traversal") == 0) {
+      _gc_mode = new ShenandoahTraversalMode();
+    } else if (strcmp(ShenandoahGCMode, "normal") == 0) {
+      _gc_mode = new ShenandoahNormalMode();
+    } else if (strcmp(ShenandoahGCMode, "passive") == 0) {
+      _gc_mode = new ShenandoahPassiveMode();
     } else {
-      vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option");
+      vm_exit_during_initialization("Unknown -XX:ShenandoahGCMode option");
     }
-
-    if (_heuristics->is_diagnostic() && !UnlockDiagnosticVMOptions) {
-      vm_exit_during_initialization(
-              err_msg("Heuristics \"%s\" is diagnostic, and must be enabled via -XX:+UnlockDiagnosticVMOptions.",
-                      _heuristics->name()));
-    }
-    if (_heuristics->is_experimental() && !UnlockExperimentalVMOptions) {
-      vm_exit_during_initialization(
-              err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.",
-                      _heuristics->name()));
-    }
-    log_info(gc, init)("Shenandoah heuristics: %s",
-                       _heuristics->name());
   } else {
-      ShouldNotReachHere();
+    ShouldNotReachHere();
   }
-
+  _gc_mode->initialize_flags();
+  _heuristics = _gc_mode->initialize_heuristics();
+
+  if (_heuristics->is_diagnostic() && !UnlockDiagnosticVMOptions) {
+    vm_exit_during_initialization(
+            err_msg("Heuristics \"%s\" is diagnostic, and must be enabled via -XX:+UnlockDiagnosticVMOptions.",
+                    _heuristics->name()));
+  }
+  if (_heuristics->is_experimental() && !UnlockExperimentalVMOptions) {
+    vm_exit_during_initialization(
+            err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.",
+                    _heuristics->name()));
+  }
+  log_info(gc, init)("Shenandoah heuristics: %s",
+                     _heuristics->name());
 }
 
 #ifdef _MSC_VER
@@ -1704,7 +1696,7 @@
       set_process_references(heuristics()->can_process_references());
       set_unload_classes(heuristics()->can_unload_classes());
 
-      if (heuristics()->can_do_traversal_gc()) {
+      if (is_traversal_mode()) {
         // Not possible to degenerate from here, upgrade to Full GC right away.
         cancel_gc(GCCause::_shenandoah_upgrade_to_full_gc);
         op_degenerated_fail();
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -43,6 +43,7 @@
 class ShenandoahGCStateResetter;
 class ShenandoahHeuristics;
 class ShenandoahMarkingContext;
+class ShenandoahMode;
 class ShenandoahPhaseTimings;
 class ShenandoahHeap;
 class ShenandoahHeapRegion;
@@ -435,6 +436,7 @@
 private:
   ShenandoahControlThread*   _control_thread;
   ShenandoahCollectorPolicy* _shenandoah_policy;
+  ShenandoahMode*            _gc_mode;
   ShenandoahHeuristics*      _heuristics;
   ShenandoahFreeSet*         _free_set;
   ShenandoahConcurrentMark*  _scm;
@@ -454,7 +456,8 @@
   ShenandoahHeuristics*      heuristics()        const { return _heuristics;        }
   ShenandoahFreeSet*         free_set()          const { return _free_set;          }
   ShenandoahConcurrentMark*  concurrent_mark()         { return _scm;               }
-  ShenandoahTraversalGC*     traversal_gc()            { return _traversal_gc;      }
+  ShenandoahTraversalGC*     traversal_gc()      const { return _traversal_gc;      }
+  bool                       is_traversal_mode() const { return _traversal_gc != NULL; }
   ShenandoahPacer*           pacer()             const { return _pacer;             }
 
   ShenandoahPhaseTimings*    phase_timings()     const { return _phase_timings;     }
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -228,7 +228,7 @@
   return _update_refs_early;
 }
 
-bool ShenandoahHeuristics::should_start_normal_gc() const {
+bool ShenandoahHeuristics::should_start_gc() const {
   // Perform GC to cleanup metaspace
   if (has_metaspace_oom()) {
     // Some of vmTestbase/metaspace tests depend on following line to count GC cycles
@@ -245,14 +245,6 @@
   return periodic_gc;
 }
 
-bool ShenandoahHeuristics::should_start_traversal_gc() {
-  return false;
-}
-
-bool ShenandoahHeuristics::can_do_traversal_gc() {
-  return false;
-}
-
 bool ShenandoahHeuristics::should_degenerate_cycle() {
   return _degenerated_cycles_in_a_row <= ShenandoahFullGCThreshold;
 }
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeuristics.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -127,14 +127,10 @@
 
   virtual void record_phase_time(ShenandoahPhaseTimings::Phase phase, double secs);
 
-  virtual bool should_start_normal_gc() const;
+  virtual bool should_start_gc() const;
 
   virtual bool should_start_update_refs();
 
-  virtual bool should_start_traversal_gc();
-
-  virtual bool can_do_traversal_gc();
-
   virtual bool should_degenerate_cycle();
 
   virtual void record_success_concurrent();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMode.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHMODE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHMODE_HPP
+
+#include "memory/allocation.hpp"
+
+class ShenandoahHeuristics;
+
+class ShenandoahMode : public CHeapObj<mtGC> {
+public:
+  virtual void initialize_flags() const = 0;
+  virtual ShenandoahHeuristics* initialize_heuristics() const = 0;
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHMODE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNormalMode.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shenandoah/shenandoahNormalMode.hpp"
+#include "gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp"
+#include "gc/shenandoah/heuristics/shenandoahAggressiveHeuristics.hpp"
+#include "gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp"
+#include "gc/shenandoah/heuristics/shenandoahStaticHeuristics.hpp"
+#include "logging/log.hpp"
+#include "logging/logTag.hpp"
+
+void ShenandoahNormalMode::initialize_flags() const {
+  SHENANDOAH_ERGO_ENABLE_FLAG(ExplicitGCInvokesConcurrent);
+  SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
+
+  // Final configuration checks
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahSATBBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahKeepAliveBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
+}
+
+ShenandoahHeuristics* ShenandoahNormalMode::initialize_heuristics() const {
+  if (ShenandoahGCHeuristics != NULL) {
+    if (strcmp(ShenandoahGCHeuristics, "aggressive") == 0) {
+      return new ShenandoahAggressiveHeuristics();
+    } else if (strcmp(ShenandoahGCHeuristics, "static") == 0) {
+      return new ShenandoahStaticHeuristics();
+    } else if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) {
+      return new ShenandoahAdaptiveHeuristics();
+    } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) {
+      return new ShenandoahCompactHeuristics();
+    } else {
+      vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option");
+    }
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahNormalMode.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHNORMALMODE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHNORMALMODE_HPP
+
+#include "gc/shenandoah/shenandoahMode.hpp"
+
+class ShenandoahHeuristics;
+
+class ShenandoahNormalMode : public ShenandoahMode {
+public:
+  virtual void initialize_flags() const;
+  virtual ShenandoahHeuristics* initialize_heuristics() const;
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHNORMALMODE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPassiveMode.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shenandoah/shenandoahPassiveMode.hpp"
+#include "gc/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp"
+#include "logging/log.hpp"
+#include "logging/logTag.hpp"
+
+void ShenandoahPassiveMode::initialize_flags() const {
+  // Do not allow concurrent cycles.
+  FLAG_SET_DEFAULT(ExplicitGCInvokesConcurrent, false);
+  FLAG_SET_DEFAULT(ShenandoahImplicitGCInvokesConcurrent, false);
+
+  // Passive runs with max speed, reacts on allocation failure.
+  FLAG_SET_DEFAULT(ShenandoahPacing, false);
+
+  // No need for evacuation reserve with Full GC, only for Degenerated GC.
+  if (!ShenandoahDegeneratedGC) {
+    SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahEvacReserve, 0);
+  }
+
+  // Disable known barriers by default.
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahLoadRefBarrier);
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahSATBBarrier);
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahKeepAliveBarrier);
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValEnqueueBarrier);
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCASBarrier);
+  SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCloneBarrier);
+
+  // Final configuration checks
+  // No barriers are required to run.
+}
+ShenandoahHeuristics* ShenandoahPassiveMode::initialize_heuristics() const {
+  if (ShenandoahGCHeuristics != NULL) {
+    return new ShenandoahPassiveHeuristics();
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPassiveMode.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHPASSIVEMODE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHPASSIVEMODE_HPP
+
+#include "gc/shenandoah/shenandoahNormalMode.hpp"
+
+class ShenandoahPassiveMode : public ShenandoahNormalMode {
+public:
+  virtual void initialize_flags() const;
+  virtual ShenandoahHeuristics* initialize_heuristics() const;
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHNORMALMODE_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -41,11 +41,11 @@
 #include "services/management.hpp"
 
 ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) :
-  _claimed(false), _oops_do(oops_do), _phase(phase) {
+  _oops_do(oops_do), _phase(phase) {
 }
 
 void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) {
-  if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) {
+  if (_claimed.try_set()) {
     ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
     ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id);
     _oops_do(cl);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -36,7 +36,7 @@
 public:
   typedef void (*OopsDo)(OopClosure*);
 private:
-  volatile bool                             _claimed;
+  ShenandoahSharedFlag                      _claimed;
   const OopsDo                              _oops_do;
   const ShenandoahPhaseTimings::GCParPhases _phase;
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -225,7 +225,7 @@
 void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) {
   assert(!ShenandoahSafepoint::is_at_shenandoah_safepoint() ||
          !ShenandoahHeap::heap()->unload_classes() ||
-          ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc(),
+          ShenandoahHeap::heap()->is_traversal_mode(),
           "Expect class unloading or traversal when Shenandoah cycle is running");
   ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
   ResourceMark rm;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalMode.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shenandoah/shenandoahTraversalMode.hpp"
+#include "gc/shenandoah/heuristics/shenandoahTraversalAggressiveHeuristics.hpp"
+#include "gc/shenandoah/heuristics/shenandoahTraversalHeuristics.hpp"
+#include "logging/log.hpp"
+#include "logging/logTag.hpp"
+
+void ShenandoahTraversalMode::initialize_flags() const {
+  FLAG_SET_DEFAULT(ShenandoahSATBBarrier,            false);
+  FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, true);
+  FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier,       false);
+  FLAG_SET_DEFAULT(ShenandoahAllowMixedAllocs,       false);
+
+  SHENANDOAH_ERGO_ENABLE_FLAG(ExplicitGCInvokesConcurrent);
+  SHENANDOAH_ERGO_ENABLE_FLAG(ShenandoahImplicitGCInvokesConcurrent);
+
+  // Final configuration checks
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahLoadRefBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahStoreValEnqueueBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCASBarrier);
+  SHENANDOAH_CHECK_FLAG_SET(ShenandoahCloneBarrier);
+}
+
+ShenandoahHeuristics* ShenandoahTraversalMode::initialize_heuristics() const {
+  if (ShenandoahGCHeuristics != NULL) {
+    if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) {
+      return new ShenandoahTraversalHeuristics();
+    } else if (strcmp(ShenandoahGCHeuristics, "aggressive") == 0) {
+      return new ShenandoahTraversalAggressiveHeuristics();
+    } else {
+      vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option");
+    }
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalMode.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHTRAVERSALMODE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHTRAVERSALMODE_HPP
+
+#include "gc/shenandoah/shenandoahMode.hpp"
+
+class ShenandoahHeuristics;
+
+class ShenandoahTraversalMode : public ShenandoahMode {
+public:
+  virtual void initialize_flags() const;
+  virtual ShenandoahHeuristics* initialize_heuristics() const;
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHTRAVERSALMODE_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -65,13 +65,18 @@
           " *) static  -  start concurrent GC when static free heap "       \
           "               threshold and static allocation threshold are "   \
           "               tripped;"                                         \
-          " *) passive -  do not start concurrent GC, wait for Full GC; "   \
           " *) aggressive - run concurrent GC continuously, evacuate "      \
           "               everything;"                                      \
           " *) compact - run GC with lower footprint target, may end up "   \
           "               doing continuous GC, evacuate lots of live "      \
           "               objects, uncommit heap aggressively;")            \
                                                                             \
+  experimental(ccstr, ShenandoahGCMode, "normal",                           \
+          "The GC mode to use in Shenandoah GC. Possible values"            \
+          " *) normal    - normal GC (mark-evac-update)"                    \
+          " *) traversal - traversal GC (single-pass)"                      \
+          " *) passive   - disable concurrent GC, do stop-the-world GC")    \
+                                                                            \
   experimental(ccstr, ShenandoahUpdateRefsEarly, "adaptive",                \
           "Run a separate concurrent reference updating phase after"        \
           "concurrent evacuation. Possible values: 'on', 'off', 'adaptive'")\
@@ -364,10 +369,6 @@
   diagnostic(bool, ShenandoahLoadRefBarrier, true,                          \
           "Turn on/off load-reference barriers in Shenandoah")              \
                                                                             \
-  diagnostic(bool, ShenandoahStoreCheck, false,                             \
-          "Emit additional code that checks objects are written to only"    \
-          " in to-space")                                                   \
-                                                                            \
   experimental(bool, ShenandoahConcurrentScanCodeRoots, true,               \
           "Scan code roots concurrently, instead of during a pause")        \
                                                                             \
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -128,14 +128,19 @@
   }
 }
 
-static bool load_require_barrier(LoadNode* load)      { return ((load->barrier_data() & RequireBarrier) != 0); }
-static bool load_has_weak_barrier(LoadNode* load)     { return ((load->barrier_data() & WeakBarrier) != 0); }
-static bool load_has_expanded_barrier(LoadNode* load) { return ((load->barrier_data() & ExpandedBarrier) != 0); }
+const uint NoBarrier       = 0;
+const uint RequireBarrier  = 1;
+const uint WeakBarrier     = 2;
+const uint ExpandedBarrier = 4;
+
+static bool load_require_barrier(LoadNode* load)      { return (load->barrier_data() & RequireBarrier)  == RequireBarrier; }
+static bool load_has_weak_barrier(LoadNode* load)     { return (load->barrier_data() & WeakBarrier)     == WeakBarrier; }
+static bool load_has_expanded_barrier(LoadNode* load) { return (load->barrier_data() & ExpandedBarrier) == ExpandedBarrier; }
 static void load_set_expanded_barrier(LoadNode* load) { return load->set_barrier_data(ExpandedBarrier); }
 
-static void load_set_barrier(LoadNode* load, bool weak)    {
+static void load_set_barrier(LoadNode* load, bool weak) {
   if (weak) {
-    load->set_barrier_data(WeakBarrier);
+    load->set_barrier_data(RequireBarrier | WeakBarrier);
   } else {
     load->set_barrier_data(RequireBarrier);
   }
@@ -522,7 +527,7 @@
   Node* in_val = barrier->in(LoadBarrierNode::Oop);
   Node* in_adr = barrier->in(LoadBarrierNode::Address);
 
-  Node* out_ctrl = barrier->proj_out_or_null(LoadBarrierNode::Control);
+  Node* out_ctrl = barrier->proj_out(LoadBarrierNode::Control);
   Node* out_res = barrier->proj_out(LoadBarrierNode::Oop);
 
   assert(barrier->in(LoadBarrierNode::Oop) != NULL, "oop to loadbarrier node cannot be null");
@@ -540,8 +545,8 @@
   Node* then = igvn.transform(new IfTrueNode(iff));
   Node* elsen = igvn.transform(new IfFalseNode(iff));
 
-  Node* new_loadp = igvn.transform(new LoadBarrierSlowRegNode(then, in_mem, in_adr, in_val->adr_type(),
-                                                                    (const TypePtr*) in_val->bottom_type(), MemNode::unordered, barrier->is_weak()));
+  Node* new_loadp = igvn.transform(new LoadBarrierSlowRegNode(then, in_adr, in_val,
+                                                              (const TypePtr*) in_val->bottom_type(), barrier->is_weak()));
 
   // Create the final region/phi pair to converge cntl/data paths to downstream code
   Node* result_region = igvn.transform(new RegionNode(3));
@@ -552,9 +557,8 @@
   result_phi->set_req(1, new_loadp);
   result_phi->set_req(2, barrier->in(LoadBarrierNode::Oop));
 
-  if (out_ctrl != NULL) {
-    igvn.replace_node(out_ctrl, result_region);
-  }
+
+  igvn.replace_node(out_ctrl, result_region);
   igvn.replace_node(out_res, result_phi);
 
   assert(barrier->outcnt() == 0,"LoadBarrier macro node has non-null outputs after expansion!");
@@ -640,6 +644,22 @@
   return c;
 }
 
+Node* ZBarrierSetC2::step_over_gc_barrier_ctrl(Node* c) const {
+  Node* node = c;
+
+  // 1. This step follows potential ctrl projections of a load barrier before expansion
+  if (node->is_Proj()) {
+    node = node->in(0);
+  }
+
+  // 2. This step checks for unexpanded load barriers
+  if (node->is_LoadBarrier()) {
+    return node->in(LoadBarrierNode::Control);
+  }
+
+  return c;
+}
+
 bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
   return type == T_OBJECT || type == T_ARRAY;
 }
@@ -652,7 +672,6 @@
     case Op_ZCompareAndExchangeP:
     case Op_ZCompareAndSwapP:
     case Op_ZWeakCompareAndSwapP:
-    case Op_LoadBarrierSlowReg:
 #ifdef ASSERT
       if (VerifyOptoOopOffsets) {
         MemNode *mem = n->as_Mem();
@@ -1214,7 +1233,6 @@
   Compile *C = phase->C;
   PhaseIterGVN &igvn = phase->igvn();
   LoadStoreNode* zclone = NULL;
-  bool is_weak = false;
 
   Node *in_ctrl = old_node->in(MemNode::Control);
   Node *in_mem  = old_node->in(MemNode::Memory);
@@ -1234,7 +1252,6 @@
       if (can_simplify_cas(old_node)) {
         break;
       }
-      is_weak  = true;
       zclone = new ZWeakCompareAndSwapPNode(in_ctrl, in_mem, in_adr, in_val, old_node->in(LoadStoreConditionalNode::ExpectedIn),
               ((CompareAndSwapNode*)old_node)->order());
       adr_type = TypePtr::BOTTOM;
@@ -1265,7 +1282,7 @@
     igvn.register_new_node_with_optimizer(load);
     igvn.replace_node(old_node, zclone);
 
-    Node *barrier = new LoadBarrierNode(C, NULL, in_mem, load, in_adr, is_weak);
+    Node *barrier = new LoadBarrierNode(C, NULL, in_mem, load, in_adr, false /* weak */);
     Node *barrier_val = new ProjNode(barrier, LoadBarrierNode::Oop);
     Node *barrier_ctrl = new ProjNode(barrier, LoadBarrierNode::Control);
 
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -104,22 +104,25 @@
   }
 };
 
-class LoadBarrierSlowRegNode : public LoadPNode {
+class LoadBarrierSlowRegNode : public TypeNode {
 private:
-    bool _is_weak;
+  bool _is_weak;
 public:
   LoadBarrierSlowRegNode(Node *c,
-                         Node *mem,
                          Node *adr,
-                         const TypePtr *at,
+                         Node *src,
                          const TypePtr* t,
-                         MemOrd mo,
-                         bool weak = false,
-                         ControlDependency control_dependency = DependsOnlyOnTest) :
-      LoadPNode(c, mem, adr, at, t, mo, control_dependency), _is_weak(weak) {
+                         bool weak) :
+      TypeNode(t, 3), _is_weak(weak) {
+    init_req(1, adr);
+    init_req(2, src);
     init_class_id(Class_LoadBarrierSlowReg);
   }
 
+  virtual uint size_of() const {
+    return sizeof(*this);
+  }
+
   virtual const char * name() {
     return "LoadBarrierSlowRegNode";
   }
@@ -146,13 +149,6 @@
   LoadBarrierNode* load_barrier_node(int idx) const;
 };
 
-enum BarrierInfo {
-    NoBarrier       = 0,
-    RequireBarrier  = 1,
-    WeakBarrier     = 3,  // Inclusive with RequireBarrier
-    ExpandedBarrier = 4
-};
-
 class ZBarrierSetC2 : public BarrierSetC2 {
 private:
   ZBarrierSetC2State* state() const;
@@ -182,6 +178,7 @@
   virtual bool has_load_barriers() const { return true; }
   virtual bool is_gc_barrier_node(Node* node) const;
   virtual Node* step_over_gc_barrier(Node* c) const;
+  virtual Node* step_over_gc_barrier_ctrl(Node* c) const;
 
   virtual void register_potential_barrier_node(Node* node) const;
   virtual void unregister_potential_barrier_node(Node* node) const;
--- a/src/hotspot/share/gc/z/zArguments.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zArguments.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -92,6 +92,11 @@
   // same reason we need fixup_partial_loads
   FLAG_SET_DEFAULT(VerifyBeforeIteration, false);
 
+  if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
+    FLAG_SET_DEFAULT(ZVerifyRoots, true);
+    FLAG_SET_DEFAULT(ZVerifyObjects, true);
+  }
+
   // 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/zBarrier.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -24,10 +24,12 @@
 #ifndef SHARE_GC_Z_ZBARRIER_INLINE_HPP
 #define SHARE_GC_Z_ZBARRIER_INLINE_HPP
 
+#include "classfile/javaClasses.hpp"
 #include "gc/z/zAddress.inline.hpp"
 #include "gc/z/zBarrier.hpp"
 #include "gc/z/zOop.inline.hpp"
 #include "gc/z/zResurrection.inline.hpp"
+#include "oops/oop.hpp"
 #include "runtime/atomic.hpp"
 
 template <ZBarrierFastPath fast_path, ZBarrierSlowPath slow_path>
@@ -173,7 +175,21 @@
   }
 }
 
+// ON_WEAK barriers should only ever be applied to j.l.r.Reference.referents.
+inline void verify_on_weak(volatile oop* referent_addr) {
+#ifdef ASSERT
+  if (referent_addr != NULL) {
+    uintptr_t base = (uintptr_t)referent_addr - java_lang_ref_Reference::referent_offset;
+    oop obj = cast_to_oop(base);
+    assert(oopDesc::is_oop(obj), "Verification failed for: ref " PTR_FORMAT " obj: " PTR_FORMAT, (uintptr_t)referent_addr, base);
+    assert(java_lang_ref_Reference::is_referent_field(obj, java_lang_ref_Reference::referent_offset), "Sanity");
+  }
+#endif
+}
+
 inline oop ZBarrier::load_barrier_on_weak_oop_field_preloaded(volatile oop* p, oop o) {
+  verify_on_weak(p);
+
   if (is_resurrection_blocked(p, &o)) {
     return weak_barrier<is_good_or_null_fast_path, weak_load_barrier_on_weak_oop_slow_path>(p, o);
   }
@@ -217,6 +233,8 @@
 }
 
 inline oop ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(volatile oop* p, oop o) {
+  verify_on_weak(p);
+
   if (is_resurrection_blocked(p, &o)) {
     return weak_barrier<is_good_or_null_fast_path, weak_load_barrier_on_weak_oop_slow_path>(p, o);
   }
--- a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -62,6 +62,7 @@
     } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) {
       return ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(addr, o);
     } else {
+      assert((HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value), "Must be");
       return ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(addr, o);
     }
   } else {
@@ -70,6 +71,7 @@
     } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) {
       return ZBarrier::load_barrier_on_weak_oop_field_preloaded(addr, o);
     } else {
+      assert((HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value), "Must be");
       return ZBarrier::load_barrier_on_phantom_oop_field_preloaded(addr, o);
     }
   }
@@ -89,6 +91,7 @@
     } else if (decorators_known_strength & ON_WEAK_OOP_REF) {
       return ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(addr, o);
     } else {
+      assert(decorators_known_strength & ON_PHANTOM_OOP_REF, "Must be");
       return ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(addr, o);
     }
   } else {
@@ -97,6 +100,7 @@
     } else if (decorators_known_strength & ON_WEAK_OOP_REF) {
       return ZBarrier::load_barrier_on_weak_oop_field_preloaded(addr, o);
     } else {
+      assert(decorators_known_strength & ON_PHANTOM_OOP_REF, "Must be");
       return ZBarrier::load_barrier_on_phantom_oop_field_preloaded(addr, o);
     }
   }
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -232,11 +232,11 @@
 }
 
 void ZCollectedHeap::object_iterate(ObjectClosure* cl) {
-  _heap.object_iterate(cl, true /* visit_referents */);
+  _heap.object_iterate(cl, true /* visit_weaks */);
 }
 
 void ZCollectedHeap::safe_object_iterate(ObjectClosure* cl) {
-  _heap.object_iterate(cl, true /* visit_referents */);
+  _heap.object_iterate(cl, true /* visit_weaks */);
 }
 
 HeapWord* ZCollectedHeap::block_start(const void* addr) const {
--- a/src/hotspot/share/gc/z/zDriver.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zDriver.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -31,6 +31,7 @@
 #include "gc/z/zMessagePort.inline.hpp"
 #include "gc/z/zServiceability.hpp"
 #include "gc/z/zStat.hpp"
+#include "gc/z/zVerify.hpp"
 #include "logging/log.hpp"
 #include "memory/universe.hpp"
 #include "runtime/vmOperations.hpp"
@@ -86,6 +87,9 @@
     GCIdMark gc_id_mark(_gc_id);
     IsGCActiveMark gc_active_mark;
 
+    // Verify roots
+    ZVerify::roots_strong();
+
     // Execute operation
     _success = do_operation();
 
@@ -301,8 +305,14 @@
 
 void ZDriver::pause_verify() {
   if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
+    // Full verification
     VM_Verify op;
     VMThread::execute(&op);
+
+  } else if (ZVerifyRoots || ZVerifyObjects) {
+    // Limited verification
+    VM_ZVerifyOperation op;
+    VMThread::execute(&op);
   }
 }
 
--- a/src/hotspot/share/gc/z/zHeap.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zHeap.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -41,6 +41,7 @@
 #include "gc/z/zTask.hpp"
 #include "gc/z/zThread.hpp"
 #include "gc/z/zTracer.inline.hpp"
+#include "gc/z/zVerify.hpp"
 #include "gc/z/zVirtualMemory.inline.hpp"
 #include "gc/z/zWorkers.inline.hpp"
 #include "logging/log.hpp"
@@ -340,6 +341,9 @@
   // Enter mark completed phase
   ZGlobalPhase = ZPhaseMarkCompleted;
 
+  // Verify after mark
+  ZVerify::after_mark();
+
   // Update statistics
   ZStatSample(ZSamplerHeapUsedAfterMark, used());
   ZStatHeap::set_at_mark_end(capacity(), allocated(), used());
@@ -468,11 +472,11 @@
                                  used(), used_high(), used_low());
 }
 
-void ZHeap::object_iterate(ObjectClosure* cl, bool visit_referents) {
+void ZHeap::object_iterate(ObjectClosure* cl, bool visit_weaks) {
   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
 
   ZHeapIterator iter;
-  iter.objects_do(cl, visit_referents);
+  iter.objects_do(cl, visit_weaks);
 }
 
 void ZHeap::serviceability_initialize() {
@@ -518,40 +522,11 @@
   st->cr();
 }
 
-class ZVerifyRootsTask : public ZTask {
-private:
-  ZStatTimerDisable  _disable;
-  ZRootsIterator     _strong_roots;
-  ZWeakRootsIterator _weak_roots;
-
-public:
-  ZVerifyRootsTask() :
-      ZTask("ZVerifyRootsTask"),
-      _disable(),
-      _strong_roots(),
-      _weak_roots() {}
-
-  virtual void work() {
-    ZStatTimerDisable disable;
-    ZVerifyOopClosure cl;
-    _strong_roots.oops_do(&cl);
-    _weak_roots.oops_do(&cl);
-  }
-};
-
 void ZHeap::verify() {
   // Heap verification can only be done between mark end and
   // relocate start. This is the only window where all oop are
   // good and the whole heap is in a consistent state.
   guarantee(ZGlobalPhase == ZPhaseMarkCompleted, "Invalid phase");
 
-  {
-    ZVerifyRootsTask task;
-    _workers.run_parallel(&task);
-  }
-
-  {
-    ZVerifyObjectClosure cl;
-    object_iterate(&cl, false /* visit_referents */);
-  }
+  ZVerify::after_weak_processing();
 }
--- a/src/hotspot/share/gc/z/zHeap.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zHeap.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -161,7 +161,7 @@
   void relocate();
 
   // Iteration
-  void object_iterate(ObjectClosure* cl, bool visit_referents);
+  void object_iterate(ObjectClosure* cl, bool visit_weaks);
 
   // Serviceability
   void serviceability_initialize();
--- a/src/hotspot/share/gc/z/zHeapIterator.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zHeapIterator.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -22,6 +22,8 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderDataGraph.hpp"
 #include "gc/z/zBarrier.inline.hpp"
 #include "gc/z/zGlobals.hpp"
 #include "gc/z/zGranuleMap.inline.hpp"
@@ -83,7 +85,7 @@
 };
 
 template <bool VisitReferents>
-class ZHeapIteratorOopClosure : public BasicOopIterateClosure {
+class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure {
 private:
   ZHeapIterator* const _iter;
   const oop            _base;
@@ -98,6 +100,7 @@
 
 public:
   ZHeapIteratorOopClosure(ZHeapIterator* iter, oop base) :
+      ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_other),
       _iter(iter),
       _base(base) {}
 
@@ -130,6 +133,7 @@
   for (ZHeapIteratorBitMap* map; iter.next(&map);) {
     delete map;
   }
+  ClassLoaderDataGraph::clear_claimed_marks(ClassLoaderData::_claim_other);
 }
 
 static size_t object_index_max() {
@@ -184,15 +188,23 @@
   obj->oop_iterate(&cl);
 }
 
-template <bool VisitReferents>
+class ZHeapIterateConcurrentRootsIterator : public ZConcurrentRootsIterator {
+public:
+  ZHeapIterateConcurrentRootsIterator() :
+      ZConcurrentRootsIterator(ClassLoaderData::_claim_other) {}
+};
+
+template <bool VisitWeaks>
 void ZHeapIterator::objects_do(ObjectClosure* cl) {
   ZStatTimerDisable disable;
 
   // Push roots to visit
-  push_roots<ZRootsIterator,               false /* Concurrent */, false /* Weak */>();
-  push_roots<ZConcurrentRootsIterator,     true  /* Concurrent */, false /* Weak */>();
-  push_roots<ZWeakRootsIterator,           false /* Concurrent */, true  /* Weak */>();
-  push_roots<ZConcurrentWeakRootsIterator, true  /* Concurrent */, true  /* Weak */>();
+  push_roots<ZRootsIterator,                      false /* Concurrent */, false /* Weak */>();
+  push_roots<ZHeapIterateConcurrentRootsIterator, true  /* Concurrent */, false /* Weak */>();
+  if (VisitWeaks) {
+    push_roots<ZWeakRootsIterator,           false /* Concurrent */, true  /* Weak */>();
+    push_roots<ZConcurrentWeakRootsIterator, true  /* Concurrent */, true  /* Weak */>();
+  }
 
   // Drain stack
   while (!_visit_stack.is_empty()) {
@@ -202,14 +214,14 @@
     cl->do_object(obj);
 
     // Push fields to visit
-    push_fields<VisitReferents>(obj);
+    push_fields<VisitWeaks>(obj);
   }
 }
 
-void ZHeapIterator::objects_do(ObjectClosure* cl, bool visit_referents) {
-  if (visit_referents) {
-    objects_do<true /* VisitReferents */>(cl);
+void ZHeapIterator::objects_do(ObjectClosure* cl, bool visit_weaks) {
+  if (visit_weaks) {
+    objects_do<true /* VisitWeaks */>(cl);
   } else {
-    objects_do<false /* VisitReferents */>(cl);
+    objects_do<false /* VisitWeaks */>(cl);
   }
 }
--- a/src/hotspot/share/gc/z/zHeapIterator.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zHeapIterator.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -54,7 +54,7 @@
   ZHeapIterator();
   ~ZHeapIterator();
 
-  void objects_do(ObjectClosure* cl, bool visit_referents);
+  void objects_do(ObjectClosure* cl, bool visit_weaks);
 };
 
 #endif // SHARE_GC_Z_ZHEAPITERATOR_HPP
--- a/src/hotspot/share/gc/z/zMark.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zMark.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -22,6 +22,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/classLoaderDataGraph.hpp"
 #include "gc/z/zBarrier.inline.hpp"
 #include "gc/z/zMark.inline.hpp"
 #include "gc/z/zMarkCache.inline.hpp"
@@ -632,14 +633,23 @@
 
 class ZMarkConcurrentRootsTask : public ZTask {
 private:
+  SuspendibleThreadSetJoiner          _sts_joiner;
   ZConcurrentRootsIterator            _roots;
   ZMarkConcurrentRootsIteratorClosure _cl;
 
 public:
   ZMarkConcurrentRootsTask(ZMark* mark) :
       ZTask("ZMarkConcurrentRootsTask"),
-      _roots(true /* marking */),
-      _cl() {}
+      _sts_joiner(true /* active */),
+      _roots(ClassLoaderData::_claim_strong),
+      _cl() {
+    ClassLoaderDataGraph_lock->lock();
+    ClassLoaderDataGraph::clear_claimed_marks();
+  }
+
+  ~ZMarkConcurrentRootsTask() {
+    ClassLoaderDataGraph_lock->unlock();
+  }
 
   virtual void work() {
     _roots.oops_do(&_cl);
--- a/src/hotspot/share/gc/z/zOopClosures.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zHeap.hpp"
-#include "gc/z/zOopClosures.inline.hpp"
-#include "gc/z/zOop.inline.hpp"
-#include "memory/iterator.inline.hpp"
-#include "oops/access.inline.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/safepoint.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-void ZVerifyOopClosure::do_oop(oop* p) {
-  guarantee(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
-  guarantee(ZGlobalPhase == ZPhaseMarkCompleted, "Invalid phase");
-  guarantee(!ZResurrection::is_blocked(), "Invalid phase");
-
-  const oop o = RawAccess<>::oop_load(p);
-  if (o != NULL) {
-    const uintptr_t addr = ZOop::to_address(o);
-    const uintptr_t good_addr = ZAddress::good(addr);
-    guarantee(ZAddress::is_good(addr) || ZAddress::is_finalizable_good(addr),
-              "Bad oop " PTR_FORMAT " found at " PTR_FORMAT ", expected " PTR_FORMAT,
-              addr, p2i(p), good_addr);
-    guarantee(oopDesc::is_oop(ZOop::from_address(good_addr)),
-              "Bad object " PTR_FORMAT " found at " PTR_FORMAT,
-              addr, p2i(p));
-  }
-}
-
-void ZVerifyOopClosure::do_oop(narrowOop* p) {
-  ShouldNotReachHere();
-}
-
-void ZVerifyObjectClosure::do_object(oop o) {
-  ZVerifyOopClosure cl;
-  o->oop_iterate(&cl);
-}
--- a/src/hotspot/share/gc/z/zOopClosures.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zOopClosures.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -46,16 +46,13 @@
 };
 
 template <bool finalizable>
-class ZMarkBarrierOopClosure : public MetadataVisitingOopIterateClosure {
+class ZMarkBarrierOopClosure : public ClaimMetadataVisitingOopIterateClosure {
 public:
   ZMarkBarrierOopClosure();
 
   virtual void do_oop(oop* p);
   virtual void do_oop(narrowOop* p);
 
-  virtual void do_klass(Klass* k);
-  virtual void do_cld(ClassLoaderData* cld);
-
 #ifdef ASSERT
   virtual bool should_verify_oops() {
     return false;
@@ -80,26 +77,4 @@
   virtual void do_oop(narrowOop* p);
 };
 
-class ZVerifyOopClosure : public ZRootsIteratorClosure, public BasicOopIterateClosure {
-public:
-  virtual void do_oop(oop* p);
-  virtual void do_oop(narrowOop* p);
-
-  virtual ReferenceIterationMode reference_iteration_mode() {
-    return DO_FIELDS;
-  }
-
-#ifdef ASSERT
-  // Verification handled by the closure itself
-  virtual bool should_verify_oops() {
-    return false;
-  }
-#endif
-};
-
-class ZVerifyObjectClosure : public ObjectClosure {
-public:
-  virtual void do_object(oop o);
-};
-
 #endif // SHARE_GC_Z_ZOOPCLOSURES_HPP
--- a/src/hotspot/share/gc/z/zOopClosures.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -55,7 +55,12 @@
 
 template <bool finalizable>
 inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() :
-    MetadataVisitingOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {}
+    ClaimMetadataVisitingOopIterateClosure(finalizable
+                                               ? ClassLoaderData::_claim_finalizable
+                                               : ClassLoaderData::_claim_strong,
+                                           finalizable
+                                               ? NULL
+                                               : ZHeap::heap()->reference_discoverer()) {}
 
 template <bool finalizable>
 inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) {
@@ -67,18 +72,6 @@
   ShouldNotReachHere();
 }
 
-template <bool finalizable>
-inline void ZMarkBarrierOopClosure<finalizable>::do_klass(Klass* k) {
-  ClassLoaderData* const cld = k->class_loader_data();
-  ZMarkBarrierOopClosure<finalizable>::do_cld(cld);
-}
-
-template <bool finalizable>
-inline void ZMarkBarrierOopClosure<finalizable>::do_cld(ClassLoaderData* cld) {
-  const int claim = finalizable ? ClassLoaderData::_claim_finalizable : ClassLoaderData::_claim_strong;
-  cld->oops_do(this, claim);
-}
-
 inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) {
   return ZBarrier::is_alive_barrier_on_phantom_oop(o);
 }
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -262,24 +262,16 @@
   }
 }
 
-ZConcurrentRootsIterator::ZConcurrentRootsIterator(bool marking) :
-    _marking(marking),
-    _sts_joiner(marking /* active */),
+ZConcurrentRootsIterator::ZConcurrentRootsIterator(int cld_claim) :
     _jni_handles_iter(JNIHandles::global_handles()),
+    _cld_claim(cld_claim),
     _jni_handles(this),
     _class_loader_data_graph(this) {
   ZStatTimer timer(ZSubPhaseConcurrentRootsSetup);
-  if (_marking) {
-    ClassLoaderDataGraph_lock->lock();
-    ClassLoaderDataGraph::clear_claimed_marks();
-  }
 }
 
 ZConcurrentRootsIterator::~ZConcurrentRootsIterator() {
   ZStatTimer timer(ZSubPhaseConcurrentRootsTeardown);
-  if (_marking) {
-    ClassLoaderDataGraph_lock->unlock();
-  }
 }
 
 void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
@@ -289,13 +281,8 @@
 
 void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
   ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph);
-  if (_marking) {
-    CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_strong);
-    ClassLoaderDataGraph::always_strong_cld_do(&cld_cl);
-  } else {
-    CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_none);
-    ClassLoaderDataGraph::cld_do(&cld_cl);
-  }
+  CLDToOopClosure cld_cl(cl, _cld_claim);
+  ClassLoaderDataGraph::always_strong_cld_do(&cld_cl);
 }
 
 void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
--- a/src/hotspot/share/gc/z/zRootsIterator.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/zRootsIterator.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -111,9 +111,8 @@
 
 class ZConcurrentRootsIterator {
 private:
-  const bool                 _marking;
-  SuspendibleThreadSetJoiner _sts_joiner;
   ZOopStorageIterator        _jni_handles_iter;
+  int                        _cld_claim;
 
   void do_jni_handles(ZRootsIteratorClosure* cl);
   void do_class_loader_data_graph(ZRootsIteratorClosure* cl);
@@ -122,7 +121,7 @@
   ZParallelOopsDo<ZConcurrentRootsIterator, &ZConcurrentRootsIterator::do_class_loader_data_graph> _class_loader_data_graph;
 
 public:
-  ZConcurrentRootsIterator(bool marking = false);
+  ZConcurrentRootsIterator(int cld_claim);
   ~ZConcurrentRootsIterator();
 
   void oops_do(ZRootsIteratorClosure* cl);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zVerify.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
+#include "classfile/classLoaderDataGraph.hpp"
+#include "gc/z/zAddress.hpp"
+#include "gc/z/zHeap.inline.hpp"
+#include "gc/z/zOop.hpp"
+#include "gc/z/zResurrection.hpp"
+#include "gc/z/zRootsIterator.hpp"
+#include "gc/z/zStat.hpp"
+#include "gc/z/zVerify.hpp"
+#include "memory/allocation.hpp"
+#include "memory/iterator.inline.hpp"
+#include "oops/oop.inline.hpp"
+
+#define BAD_OOP_REPORT(addr)                                                \
+    "Bad oop " PTR_FORMAT " found at " PTR_FORMAT ", expected " PTR_FORMAT, \
+    addr, p2i(p), ZAddress::good(addr)
+
+class ZVerifyRootsClosure : public ZRootsIteratorClosure {
+public:
+  virtual void do_oop(oop* p) {
+    uintptr_t value = ZOop::to_address(*p);
+
+    if (value == 0) {
+      return;
+    }
+
+    guarantee(!ZAddress::is_finalizable(value), BAD_OOP_REPORT(value));
+    guarantee(ZAddress::is_good(value), BAD_OOP_REPORT(value));
+    guarantee(oopDesc::is_oop(ZOop::from_address(value)), BAD_OOP_REPORT(value));
+  }
+  virtual void do_oop(narrowOop*) { ShouldNotReachHere(); }
+};
+
+template <bool VisitReferents>
+class ZVerifyOopClosure : public ClaimMetadataVisitingOopIterateClosure, public ZRootsIteratorClosure  {
+public:
+  ZVerifyOopClosure() :
+      ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_other) {}
+
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+
+  virtual ReferenceIterationMode reference_iteration_mode() {
+    return VisitReferents ? DO_FIELDS : DO_FIELDS_EXCEPT_REFERENT;
+  }
+
+#ifdef ASSERT
+  // Verification handled by the closure itself
+  virtual bool should_verify_oops() {
+    return false;
+  }
+#endif
+};
+
+class ZVerifyObjectClosure : public ObjectClosure {
+private:
+  bool _visit_referents;
+
+public:
+  ZVerifyObjectClosure(bool visit_referents) : _visit_referents(visit_referents) {}
+  virtual void do_object(oop o);
+};
+
+template <typename RootsIterator>
+void ZVerify::roots_impl() {
+  if (ZVerifyRoots) {
+    ZVerifyRootsClosure cl;
+    RootsIterator iter;
+    iter.oops_do(&cl);
+  }
+}
+
+void ZVerify::roots_strong() {
+  roots_impl<ZRootsIterator>();
+}
+
+class ZVerifyConcurrentRootsIterator : public ZConcurrentRootsIterator {
+public:
+  ZVerifyConcurrentRootsIterator()
+      : ZConcurrentRootsIterator(ClassLoaderData::_claim_none) {}
+};
+
+void ZVerify::roots_concurrent() {
+  roots_impl<ZVerifyConcurrentRootsIterator>();
+}
+
+void ZVerify::roots_weak() {
+  assert(!ZResurrection::is_blocked(), "Invalid phase");
+
+  roots_impl<ZWeakRootsIterator>();
+}
+
+void ZVerify::roots(bool verify_weaks) {
+  roots_strong();
+  roots_concurrent();
+  if (verify_weaks) {
+    roots_weak();
+    roots_concurrent_weak();
+  }
+}
+
+void ZVerify::objects(bool verify_weaks) {
+  if (ZVerifyObjects) {
+    ZVerifyObjectClosure cl(verify_weaks);
+    ZHeap::heap()->object_iterate(&cl, verify_weaks);
+  }
+}
+
+void ZVerify::roots_concurrent_weak() {
+  assert(!ZResurrection::is_blocked(), "Invalid phase");
+
+  roots_impl<ZConcurrentWeakRootsIterator>();
+}
+
+void ZVerify::roots_and_objects(bool verify_weaks) {
+  ZStatTimerDisable  _disable;
+
+  roots(verify_weaks);
+  objects(verify_weaks);
+}
+
+void ZVerify::after_mark() {
+  // Only verify strong roots and references.
+  roots_and_objects(false /* verify_weaks */);
+}
+
+void ZVerify::after_weak_processing() {
+  // Also verify weaks - all should have been processed at this point.
+  roots_and_objects(true /* verify_weaks */);
+}
+
+template <bool VisitReferents>
+void ZVerifyOopClosure<VisitReferents>::do_oop(oop* p) {
+  guarantee(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+  guarantee(ZGlobalPhase == ZPhaseMarkCompleted, "Invalid phase");
+  guarantee(!ZResurrection::is_blocked(), "Invalid phase");
+
+  const oop o = RawAccess<>::oop_load(p);
+  if (o == NULL) {
+    return;
+  }
+
+  const uintptr_t addr = ZOop::to_address(o);
+  if (VisitReferents) {
+    guarantee(ZAddress::is_good(addr) || ZAddress::is_finalizable_good(addr), BAD_OOP_REPORT(addr));
+  } else {
+    // Should not encounter finalizable oops through strong-only paths. Assumes only strong roots are visited.
+    guarantee(ZAddress::is_good(addr), BAD_OOP_REPORT(addr));
+  }
+
+  const uintptr_t good_addr = ZAddress::good(addr);
+  guarantee(oopDesc::is_oop(ZOop::from_address(good_addr)), BAD_OOP_REPORT(addr));
+}
+
+void ZVerifyObjectClosure::do_object(oop o) {
+  if (_visit_referents) {
+    ZVerifyOopClosure<true /* VisitReferents */> cl;
+    o->oop_iterate((OopIterateClosure*)&cl);
+  } else {
+    ZVerifyOopClosure<false /* VisitReferents */> cl;
+    o->oop_iterate(&cl);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zVerify.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef SHARE_GC_Z_ZVERIFY_HPP
+#define SHARE_GC_Z_ZVERIFY_HPP
+
+#include "memory/allocation.hpp"
+
+class ZVerify : public AllStatic {
+private:
+  template <typename RootsIterator>
+  static void roots_impl();
+  static void roots(bool verify_weaks);
+
+  static void roots_weak();
+  static void roots_concurrent();
+  static void roots_concurrent_weak();
+
+  static void objects(bool verify_weaks);
+
+  static void roots_and_objects(bool visit_weaks);
+
+public:
+  // Verify strong (non-concurrent) roots. Should always be good.
+  static void roots_strong();
+
+  // Verify all strong roots and references after marking.
+  static void after_mark();
+
+  // Verify strong and weak roots and references.
+  static void after_weak_processing();
+};
+
+class VM_ZVerifyOperation : public VM_Operation {
+public:
+  virtual bool needs_inactive_gc_locker() const {
+    // An inactive GC locker is needed in operations where we change the bad
+    // mask or move objects. Changing the bad mask will invalidate all oops,
+    // which makes it conceptually the same thing as moving all objects.
+    return false;
+  }
+
+  virtual void doit() {
+    ZVerify::after_weak_processing();
+  }
+
+  bool success() const {
+    return true;
+  }
+
+  virtual VMOp_Type type() const { return VMOp_ZVerify; }
+};
+
+#endif // SHARE_GC_Z_ZVERIFY_HPP
--- a/src/hotspot/share/gc/z/z_globals.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/gc/z/z_globals.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -76,6 +76,12 @@
   diagnostic(bool, ZVerifyViews, false,                                     \
           "Verify heap view accesses")                                      \
                                                                             \
+  diagnostic(bool, ZVerifyRoots, trueInDebug,                               \
+          "Verify roots")                                                   \
+                                                                            \
+  diagnostic(bool, ZVerifyObjects, false,                                   \
+          "Verify objects")                                                 \
+                                                                            \
   diagnostic(bool, ZVerifyMarking, false,                                   \
           "Verify marking stacks")                                          \
                                                                             \
--- a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -99,7 +99,6 @@
 }
 
 void BFSClosure::process() {
-
   process_root_set();
   process_queue();
 }
@@ -138,7 +137,6 @@
 
     // if we are processinig initial root set, don't add to queue
     if (_current_parent != NULL) {
-      assert(_current_parent->distance_to_root() == _current_frontier_level, "invariant");
       _edge_queue->add(_current_parent, reference);
     }
 
@@ -151,20 +149,8 @@
 void BFSClosure::add_chain(const oop* reference, const oop pointee) {
   assert(pointee != NULL, "invariant");
   assert(NULL == pointee->mark(), "invariant");
-
-  const size_t length = _current_parent == NULL ? 1 : _current_parent->distance_to_root() + 2;
-  ResourceMark rm;
-  Edge* const chain = NEW_RESOURCE_ARRAY(Edge, length);
-  size_t idx = 0;
-  chain[idx++] = Edge(NULL, reference);
-  // aggregate from breadth-first search
-  const Edge* current = _current_parent;
-  while (current != NULL) {
-    chain[idx++] = Edge(NULL, current->reference());
-    current = current->parent();
-  }
-  assert(length == idx, "invariant");
-  _edge_store->add_chain(chain, length);
+  Edge leak_edge(_current_parent, reference);
+  _edge_store->put_chain(&leak_edge, _current_parent == NULL ? 1 : _current_frontier_level + 2);
 }
 
 void BFSClosure::dfs_fallback() {
@@ -241,3 +227,12 @@
     closure_impl(UnifiedOop::encode(ref), pointee);
   }
 }
+
+void BFSClosure::do_root(const oop* ref) {
+  assert(ref != NULL, "invariant");
+  assert(is_aligned(ref, HeapWordSize), "invariant");
+  assert(*ref != NULL, "invariant");
+  if (!_edge_queue->is_full()) {
+    _edge_queue->add(NULL, ref);
+  }
+}
--- a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -26,7 +26,6 @@
 #define SHARE_JFR_LEAKPROFILER_CHAINS_BFSCLOSURE_HPP
 
 #include "memory/iterator.hpp"
-#include "oops/oop.hpp"
 
 class BitSet;
 class Edge;
@@ -65,6 +64,7 @@
  public:
   BFSClosure(EdgeQueue* edge_queue, EdgeStore* edge_store, BitSet* mark_bits);
   void process();
+  void do_root(const oop* ref);
 
   virtual void do_oop(oop* ref);
   virtual void do_oop(narrowOop* ref);
--- a/src/hotspot/share/jfr/leakprofiler/chains/bitset.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/bitset.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -47,7 +47,7 @@
 
   BitMap::idx_t mark_obj(const HeapWord* addr) {
     const BitMap::idx_t bit = addr_to_bit(addr);
-    _bits.par_set_bit(bit);
+    _bits.set_bit(bit);
     return bit;
   }
 
--- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,14 +23,14 @@
  */
 
 #include "precompiled.hpp"
+#include "jfr/leakprofiler/chains/bitset.hpp"
 #include "jfr/leakprofiler/chains/dfsClosure.hpp"
 #include "jfr/leakprofiler/chains/edge.hpp"
 #include "jfr/leakprofiler/chains/edgeStore.hpp"
+#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
 #include "jfr/leakprofiler/utilities/granularTimer.hpp"
-#include "jfr/leakprofiler/chains/bitset.hpp"
+#include "jfr/leakprofiler/utilities/rootType.hpp"
 #include "jfr/leakprofiler/utilities/unifiedOop.hpp"
-#include "jfr/leakprofiler/utilities/rootType.hpp"
-#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/access.inline.hpp"
@@ -88,15 +88,15 @@
   // Mark root set, to avoid going sideways
   _max_depth = 1;
   _ignore_root_set = false;
-  DFSClosure dfs1;
-  RootSetClosure::process_roots(&dfs1);
+  DFSClosure dfs;
+  RootSetClosure<DFSClosure> rs(&dfs);
+  rs.process();
 
   // Depth-first search
   _max_depth = max_dfs_depth;
   _ignore_root_set = true;
   assert(_start_edge == NULL, "invariant");
-  DFSClosure dfs2;
-  RootSetClosure::process_roots(&dfs2);
+  rs.process();
 }
 
 void DFSClosure::closure_impl(const oop* reference, const oop pointee) {
@@ -133,30 +133,29 @@
 }
 
 void DFSClosure::add_chain() {
-  const size_t length = _start_edge == NULL ? _depth + 1 :
-                        _start_edge->distance_to_root() + 1 + _depth + 1;
+  const size_t array_length = _depth + 2;
 
   ResourceMark rm;
-  Edge* const chain = NEW_RESOURCE_ARRAY(Edge, length);
+  Edge* const chain = NEW_RESOURCE_ARRAY(Edge, array_length);
   size_t idx = 0;
 
   // aggregate from depth-first search
   const DFSClosure* c = this;
   while (c != NULL) {
-    chain[idx++] = Edge(NULL, c->reference());
+    const size_t next = idx + 1;
+    chain[idx++] = Edge(&chain[next], c->reference());
     c = c->parent();
   }
-
-  assert(idx == _depth + 1, "invariant");
+  assert(_depth + 1 == idx, "invariant");
+  assert(array_length == idx + 1, "invariant");
 
   // aggregate from breadth-first search
-  const Edge* current = _start_edge;
-  while (current != NULL) {
-    chain[idx++] = Edge(NULL, current->reference());
-    current = current->parent();
+  if (_start_edge != NULL) {
+    chain[idx++] = *_start_edge;
+  } else {
+    chain[idx - 1] = Edge(NULL, chain[idx - 1].reference());
   }
-  assert(idx == length, "invariant");
-  _edge_store->add_chain(chain, length);
+  _edge_store->put_chain(chain, idx + (_start_edge != NULL ? _start_edge->distance_to_root() : 0));
 }
 
 void DFSClosure::do_oop(oop* ref) {
@@ -176,3 +175,11 @@
     closure_impl(UnifiedOop::encode(ref), pointee);
   }
 }
+
+void DFSClosure::do_root(const oop* ref) {
+  assert(ref != NULL, "invariant");
+  assert(is_aligned(ref, HeapWordSize), "invariant");
+  const oop pointee = *ref;
+  assert(pointee != NULL, "invariant");
+  closure_impl(ref, pointee);
+}
--- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -26,7 +26,6 @@
 #define SHARE_JFR_LEAKPROFILER_CHAINS_DFSCLOSURE_HPP
 
 #include "memory/iterator.hpp"
-#include "oops/oop.hpp"
 
 class BitSet;
 class Edge;
@@ -34,7 +33,7 @@
 class EdgeQueue;
 
 // Class responsible for iterating the heap depth-first
-class DFSClosure: public BasicOopIterateClosure {
+class DFSClosure : public BasicOopIterateClosure {
  private:
   static EdgeStore* _edge_store;
   static BitSet*    _mark_bits;
@@ -57,6 +56,7 @@
  public:
   static void find_leaks_from_edge(EdgeStore* edge_store, BitSet* mark_bits, const Edge* start_edge);
   static void find_leaks_from_root_set(EdgeStore* edge_store, BitSet* mark_bits);
+  void do_root(const oop* ref);
 
   virtual void do_oop(oop* ref);
   virtual void do_oop(narrowOop* ref);
--- a/src/hotspot/share/jfr/leakprofiler/chains/edge.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/edge.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -29,7 +29,7 @@
 #include "oops/oopsHierarchy.hpp"
 
 class Edge {
- private:
+ protected:
   const Edge* _parent;
   const oop* _reference;
  public:
--- a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,37 +27,17 @@
 #include "jfr/leakprofiler/chains/edgeUtils.hpp"
 #include "oops/oop.inline.hpp"
 
-RoutableEdge::RoutableEdge() : Edge() {}
-RoutableEdge::RoutableEdge(const Edge* parent, const oop* reference) : Edge(parent, reference),
-                                                                       _skip_edge(NULL),
-                                                                       _skip_length(0),
-                                                                       _processed(false) {}
+StoredEdge::StoredEdge() : Edge() {}
+StoredEdge::StoredEdge(const Edge* parent, const oop* reference) : Edge(parent, reference), _gc_root_id(0), _skip_length(0) {}
 
-RoutableEdge::RoutableEdge(const Edge& edge) : Edge(edge),
-                                               _skip_edge(NULL),
-                                               _skip_length(0),
-                                               _processed(false) {}
-
-RoutableEdge::RoutableEdge(const RoutableEdge& edge) : Edge(edge),
-                                                      _skip_edge(edge._skip_edge),
-                                                      _skip_length(edge._skip_length),
-                                                      _processed(edge._processed) {}
+StoredEdge::StoredEdge(const Edge& edge) : Edge(edge), _gc_root_id(0), _skip_length(0) {}
 
-void RoutableEdge::operator=(const RoutableEdge& edge) {
-  Edge::operator=(edge);
-  _skip_edge = edge._skip_edge;
-  _skip_length = edge._skip_length;
-  _processed = edge._processed;
-}
+StoredEdge::StoredEdge(const StoredEdge& edge) : Edge(edge), _gc_root_id(edge._gc_root_id), _skip_length(edge._skip_length) {}
 
-size_t RoutableEdge::logical_distance_to_root() const {
-  size_t depth = 0;
-  const RoutableEdge* current = logical_parent();
-  while (current != NULL) {
-    depth++;
-    current = current->logical_parent();
-  }
-  return depth;
+void StoredEdge::operator=(const StoredEdge& edge) {
+  Edge::operator=(edge);
+  _gc_root_id = edge._gc_root_id;
+  _skip_length = edge._skip_length;
 }
 
 traceid EdgeStore::_edge_id_counter = 0;
@@ -69,79 +49,12 @@
 EdgeStore::~EdgeStore() {
   assert(_edges != NULL, "invariant");
   delete _edges;
-  _edges = NULL;
-}
-
-const Edge* EdgeStore::get_edge(const Edge* edge) const {
-  assert(edge != NULL, "invariant");
-  EdgeEntry* const entry = _edges->lookup_only(*edge, (uintptr_t)edge->reference());
-  return entry != NULL ? entry->literal_addr() : NULL;
-}
-
-const Edge* EdgeStore::put(const Edge* edge) {
-  assert(edge != NULL, "invariant");
-  const RoutableEdge e = *edge;
-  assert(NULL == _edges->lookup_only(e, (uintptr_t)e.reference()), "invariant");
-  EdgeEntry& entry = _edges->put(e, (uintptr_t)e.reference());
-  return entry.literal_addr();
-}
-
-traceid EdgeStore::get_id(const Edge* edge) const {
-  assert(edge != NULL, "invariant");
-  EdgeEntry* const entry = _edges->lookup_only(*edge, (uintptr_t)edge->reference());
-  assert(entry != NULL, "invariant");
-  return entry->id();
-}
-
-traceid EdgeStore::get_root_id(const Edge* edge) const {
-  assert(edge != NULL, "invariant");
-  const Edge* root = EdgeUtils::root(*edge);
-  assert(root != NULL, "invariant");
-  return get_id(root);
-}
-
-void EdgeStore::add_chain(const Edge* chain, size_t length) {
-  assert(chain != NULL, "invariant");
-  assert(length > 0, "invariant");
-
-  size_t bottom_index = length - 1;
-  const size_t top_index = 0;
-
-  const Edge* stored_parent_edge = NULL;
-
-  // determine level of shared ancestry
-  for (; bottom_index > top_index; --bottom_index) {
-    const Edge* stored_edge = get_edge(&chain[bottom_index]);
-    if (stored_edge != NULL) {
-      stored_parent_edge = stored_edge;
-      continue;
-    }
-    break;
-  }
-
-  // insertion of new Edges
-  for (int i = (int)bottom_index; i >= (int)top_index; --i) {
-    Edge edge(stored_parent_edge, chain[i].reference());
-    stored_parent_edge = put(&edge);
-  }
-
-  const oop sample_object = stored_parent_edge->pointee();
-  assert(sample_object != NULL, "invariant");
-  assert(NULL == sample_object->mark(), "invariant");
-
-  // Install the "top" edge of the chain into the sample object mark oop.
-  // This associates the sample object with its navigable reference chain.
-  sample_object->set_mark(markOop(stored_parent_edge));
 }
 
 bool EdgeStore::is_empty() const {
   return !_edges->has_entries();
 }
 
-size_t EdgeStore::number_of_entries() const {
-  return _edges->cardinality();
-}
-
 void EdgeStore::assign_id(EdgeEntry* entry) {
   assert(entry != NULL, "invariant");
   assert(entry->id() == 0, "invariant");
@@ -153,3 +66,254 @@
   assert(entry->hash() == hash, "invariant");
   return true;
 }
+
+#ifdef ASSERT
+bool EdgeStore::contains(const oop* reference) const {
+  return get(reference) != NULL;
+}
+#endif
+
+StoredEdge* EdgeStore::get(const oop* reference) const {
+  assert(reference != NULL, "invariant");
+  const StoredEdge e(NULL, reference);
+  EdgeEntry* const entry = _edges->lookup_only(e, (uintptr_t)reference);
+  return entry != NULL ? entry->literal_addr() : NULL;
+}
+
+StoredEdge* EdgeStore::put(const oop* reference) {
+  assert(reference != NULL, "invariant");
+  const StoredEdge e(NULL, reference);
+  assert(NULL == _edges->lookup_only(e, (uintptr_t)reference), "invariant");
+  EdgeEntry& entry = _edges->put(e, (uintptr_t)reference);
+  return entry.literal_addr();
+}
+
+traceid EdgeStore::get_id(const Edge* edge) const {
+  assert(edge != NULL, "invariant");
+  EdgeEntry* const entry = _edges->lookup_only(*edge, (uintptr_t)edge->reference());
+  assert(entry != NULL, "invariant");
+  return entry->id();
+}
+
+traceid EdgeStore::gc_root_id(const Edge* edge) const {
+  assert(edge != NULL, "invariant");
+  const traceid gc_root_id = static_cast<const StoredEdge*>(edge)->gc_root_id();
+  if (gc_root_id != 0) {
+    return gc_root_id;
+  }
+  // not cached
+  assert(edge != NULL, "invariant");
+  const Edge* const root = EdgeUtils::root(*edge);
+  assert(root != NULL, "invariant");
+  assert(root->parent() == NULL, "invariant");
+  return get_id(root);
+}
+
+static const Edge* get_skip_ancestor(const Edge** current, size_t distance_to_root, size_t* skip_length) {
+  assert(distance_to_root >= EdgeUtils::root_context, "invariant");
+  assert(*skip_length == 0, "invariant");
+  *skip_length = distance_to_root - (EdgeUtils::root_context - 1);
+  const Edge* const target = EdgeUtils::ancestor(**current, *skip_length);
+  assert(target != NULL, "invariant");
+  assert(target->distance_to_root() + 1 == EdgeUtils::root_context, "invariant");
+  return target;
+}
+
+bool EdgeStore::put_skip_edge(StoredEdge** previous, const Edge** current, size_t distance_to_root) {
+  assert(*previous != NULL, "invariant");
+  assert((*previous)->parent() == NULL, "invariant");
+  assert(*current != NULL, "invariant");
+  assert((*current)->distance_to_root() == distance_to_root, "invariant");
+
+  if (distance_to_root < EdgeUtils::root_context) {
+    // nothing to skip
+    return false;
+  }
+
+  size_t skip_length = 0;
+  const Edge* const skip_ancestor = get_skip_ancestor(current, distance_to_root, &skip_length);
+  assert(skip_ancestor != NULL, "invariant");
+  (*previous)->set_skip_length(skip_length);
+
+  // lookup target
+  StoredEdge* stored_target = get(skip_ancestor->reference());
+  if (stored_target != NULL) {
+    (*previous)->set_parent(stored_target);
+    // linked to existing, complete
+    return true;
+  }
+
+  assert(stored_target == NULL, "invariant");
+  stored_target = put(skip_ancestor->reference());
+  assert(stored_target != NULL, "invariant");
+  (*previous)->set_parent(stored_target);
+  *previous = stored_target;
+  *current = skip_ancestor->parent();
+  return false;
+}
+
+static void link_edge(const StoredEdge* current_stored, StoredEdge** previous) {
+  assert(current_stored != NULL, "invariant");
+  assert(*previous != NULL, "invariant");
+  assert((*previous)->parent() == NULL, "invariant");
+  (*previous)->set_parent(current_stored);
+}
+
+static const StoredEdge* find_closest_skip_edge(const StoredEdge* edge, size_t* distance) {
+  assert(edge != NULL, "invariant");
+  assert(distance != NULL, "invariant");
+  const StoredEdge* current = edge;
+  *distance = 1;
+  while (current != NULL && !current->is_skip_edge()) {
+    ++(*distance);
+    current = current->parent();
+  }
+  return current;
+}
+
+void EdgeStore::link_with_existing_chain(const StoredEdge* current_stored, StoredEdge** previous, size_t previous_length) {
+  assert(current_stored != NULL, "invariant");
+  assert((*previous)->parent() == NULL, "invariant");
+  size_t distance_to_skip_edge; // including the skip edge itself
+  const StoredEdge* const closest_skip_edge = find_closest_skip_edge(current_stored, &distance_to_skip_edge);
+  if (closest_skip_edge == NULL) {
+    // no found skip edge implies root
+    if (distance_to_skip_edge + previous_length <= EdgeUtils::max_ref_chain_depth) {
+      link_edge(current_stored, previous);
+      return;
+    }
+    assert(current_stored->distance_to_root() == distance_to_skip_edge - 2, "invariant");
+    put_skip_edge(previous, reinterpret_cast<const Edge**>(&current_stored), distance_to_skip_edge - 2);
+    return;
+  }
+  assert(closest_skip_edge->is_skip_edge(), "invariant");
+  if (distance_to_skip_edge + previous_length <= EdgeUtils::leak_context) {
+    link_edge(current_stored, previous);
+    return;
+  }
+  // create a new skip edge with derived information from closest skip edge
+  (*previous)->set_skip_length(distance_to_skip_edge + closest_skip_edge->skip_length());
+  (*previous)->set_parent(closest_skip_edge->parent());
+}
+
+StoredEdge* EdgeStore::link_new_edge(StoredEdge** previous, const Edge** current) {
+  assert(*previous != NULL, "invariant");
+  assert((*previous)->parent() == NULL, "invariant");
+  assert(*current != NULL, "invariant");
+  assert(!contains((*current)->reference()), "invariant");
+  StoredEdge* const stored_edge = put((*current)->reference());
+  assert(stored_edge != NULL, "invariant");
+  link_edge(stored_edge, previous);
+  return stored_edge;
+}
+
+bool EdgeStore::put_edges(StoredEdge** previous, const Edge** current, size_t limit) {
+  assert(*previous != NULL, "invariant");
+  assert(*current != NULL, "invariant");
+  size_t depth = 1;
+  while (*current != NULL && depth < limit) {
+    StoredEdge* stored_edge = get((*current)->reference());
+    if (stored_edge != NULL) {
+      link_with_existing_chain(stored_edge, previous, depth);
+      return true;
+    }
+    stored_edge = link_new_edge(previous, current);
+    assert((*previous)->parent() != NULL, "invariant");
+    *previous = stored_edge;
+    *current = (*current)->parent();
+    ++depth;
+  }
+  return NULL == *current;
+}
+
+// Install the immediate edge into the mark word of the leak candidate object
+StoredEdge* EdgeStore::associate_leak_context_with_candidate(const Edge* edge) {
+  assert(edge != NULL, "invariant");
+  assert(!contains(edge->reference()), "invariant");
+  StoredEdge* const leak_context_edge = put(edge->reference());
+  oop sample_object = edge->pointee();
+  assert(sample_object != NULL, "invariant");
+  assert(NULL == sample_object->mark(), "invariant");
+  sample_object->set_mark(markOop(leak_context_edge));
+  return leak_context_edge;
+}
+
+/*
+ * The purpose of put_chain() is to reify the edge sequence
+ * discovered during heap traversal with a normalized logical copy.
+ * This copy consist of two sub-sequences and a connecting link (skip edge).
+ *
+ * "current" can be thought of as the cursor (search) edge, it is not in the edge store.
+ * "previous" is always an edge in the edge store.
+ * The leak context edge is the edge adjacent to the leak candidate object, always an edge in the edge store.
+ */
+void EdgeStore::put_chain(const Edge* chain, size_t length) {
+  assert(chain != NULL, "invariant");
+  assert(chain->distance_to_root() + 1 == length, "invariant");
+  StoredEdge* const leak_context_edge = associate_leak_context_with_candidate(chain);
+  assert(leak_context_edge != NULL, "invariant");
+  assert(leak_context_edge->parent() == NULL, "invariant");
+
+  if (1 == length) {
+    return;
+  }
+
+  const Edge* current = chain->parent();
+  assert(current != NULL, "invariant");
+  StoredEdge* previous = leak_context_edge;
+
+  // a leak context is the sequence of (limited) edges reachable from the leak candidate
+  if (put_edges(&previous, &current, EdgeUtils::leak_context)) {
+    // complete
+    assert(previous != NULL, "invariant");
+    put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous));
+    return;
+  }
+
+  const size_t distance_to_root = length > EdgeUtils::leak_context ? length - 1 - EdgeUtils::leak_context : length - 1;
+  assert(current->distance_to_root() == distance_to_root, "invariant");
+
+  // a skip edge is the logical link
+  // connecting the leak context sequence with the root context sequence
+  if (put_skip_edge(&previous, &current, distance_to_root)) {
+    // complete
+    assert(previous != NULL, "invariant");
+    assert(previous->is_skip_edge(), "invariant");
+    assert(previous->parent() != NULL, "invariant");
+    put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous->parent()));
+    return;
+  }
+
+  assert(current->distance_to_root() < EdgeUtils::root_context, "invariant");
+
+  // a root context is the sequence of (limited) edges reachable from the root
+  put_edges(&previous, &current, EdgeUtils::root_context);
+  assert(previous != NULL, "invariant");
+  put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous));
+}
+
+void EdgeStore::put_chain_epilogue(StoredEdge* leak_context_edge, const Edge* root) const {
+  assert(leak_context_edge != NULL, "invariant");
+  assert(root != NULL, "invariant");
+  store_gc_root_id_in_leak_context_edge(leak_context_edge, root);
+  assert(leak_context_edge->distance_to_root() + 1 <= EdgeUtils::max_ref_chain_depth, "invariant");
+}
+
+// To avoid another traversal to resolve the root edge id later,
+// cache it in the immediate leak context edge for fast retrieval.
+void EdgeStore::store_gc_root_id_in_leak_context_edge(StoredEdge* leak_context_edge, const Edge* root) const {
+  assert(leak_context_edge != NULL, "invariant");
+  assert(leak_context_edge->gc_root_id() == 0, "invariant");
+  assert(root != NULL, "invariant");
+  assert(root->parent() == NULL, "invariant");
+  assert(root->distance_to_root() == 0, "invariant");
+  const StoredEdge* const stored_root = static_cast<const StoredEdge*>(root);
+  traceid root_id = stored_root->gc_root_id();
+  if (root_id == 0) {
+    root_id = get_id(root);
+    stored_root->set_gc_root_id(root_id);
+  }
+  assert(root_id != 0, "invariant");
+  leak_context_edge->set_gc_root_id(root_id);
+  assert(leak_context_edge->gc_root_id() == stored_root->gc_root_id(), "invariant");
+}
--- a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -25,64 +25,40 @@
 #ifndef SHARE_JFR_LEAKPROFILER_CHAINS_EDGESTORE_HPP
 #define SHARE_JFR_LEAKPROFILER_CHAINS_EDGESTORE_HPP
 
+#include "jfr/leakprofiler/chains/edge.hpp"
 #include "jfr/utilities/jfrHashtable.hpp"
-#include "jfr/leakprofiler/chains/edge.hpp"
 #include "memory/allocation.hpp"
 
 typedef u8 traceid;
 
-class RoutableEdge : public Edge {
+class StoredEdge : public Edge {
  private:
-  mutable const RoutableEdge* _skip_edge;
-  mutable size_t _skip_length;
-  mutable bool _processed;
+  mutable traceid _gc_root_id;
+  size_t _skip_length;
 
  public:
-  RoutableEdge();
-  RoutableEdge(const Edge* parent, const oop* reference);
-  RoutableEdge(const Edge& edge);
-  RoutableEdge(const RoutableEdge& edge);
-  void operator=(const RoutableEdge& edge);
-
-  const RoutableEdge* skip_edge() const { return _skip_edge; }
-  size_t skip_length() const { return _skip_length; }
+  StoredEdge();
+  StoredEdge(const Edge* parent, const oop* reference);
+  StoredEdge(const Edge& edge);
+  StoredEdge(const StoredEdge& edge);
+  void operator=(const StoredEdge& edge);
 
-  bool is_skip_edge() const { return _skip_edge != NULL; }
-  bool processed() const { return _processed; }
-  bool is_sentinel() const {
-    return _skip_edge == NULL && _skip_length == 1;
-  }
-
-  void set_skip_edge(const RoutableEdge* edge) const {
-    assert(!is_skip_edge(), "invariant");
-    assert(edge != this, "invariant");
-    _skip_edge = edge;
-  }
+  traceid gc_root_id() const { return _gc_root_id; }
+  void set_gc_root_id(traceid root_id) const { _gc_root_id = root_id; }
 
-  void set_skip_length(size_t length) const {
-    _skip_length = length;
-  }
-
-  void set_processed() const {
-    assert(!_processed, "invariant");
-    _processed = true;
-  }
+  bool is_skip_edge() const { return _skip_length != 0; }
+  size_t skip_length() const { return _skip_length; }
+  void set_skip_length(size_t length) { _skip_length = length; }
 
-  // true navigation according to physical tree representation
-  const RoutableEdge* physical_parent() const {
-    return static_cast<const RoutableEdge*>(parent());
-  }
+  void set_parent(const Edge* edge) { this->_parent = edge; }
 
-  // logical navigation taking skip levels into account
-  const RoutableEdge* logical_parent() const {
-    return is_skip_edge() ? skip_edge() : physical_parent();
+  StoredEdge* parent() const {
+    return const_cast<StoredEdge*>(static_cast<const StoredEdge*>(Edge::parent()));
   }
-
-  size_t logical_distance_to_root() const;
 };
 
 class EdgeStore : public CHeapObj<mtTracing> {
-  typedef HashTableHost<RoutableEdge, traceid, Entry, EdgeStore> EdgeHashTable;
+  typedef HashTableHost<StoredEdge, traceid, Entry, EdgeStore> EdgeHashTable;
   typedef EdgeHashTable::HashEntry EdgeEntry;
   template <typename,
             typename,
@@ -90,6 +66,9 @@
             typename,
             size_t>
   friend class HashTableHost;
+  friend class EventEmitter;
+  friend class ObjectSampleWriter;
+  friend class ObjectSampleCheckpoint;
  private:
   static traceid _edge_id_counter;
   EdgeHashTable* _edges;
@@ -98,22 +77,31 @@
   void assign_id(EdgeEntry* entry);
   bool equals(const Edge& query, uintptr_t hash, const EdgeEntry* entry);
 
-  const Edge* get_edge(const Edge* edge) const;
-  const Edge* put(const Edge* edge);
+  StoredEdge* get(const oop* reference) const;
+  StoredEdge* put(const oop* reference);
+  traceid gc_root_id(const Edge* edge) const;
+
+  bool put_edges(StoredEdge** previous, const Edge** current, size_t length);
+  bool put_skip_edge(StoredEdge** previous, const Edge** current, size_t distance_to_root);
+  void put_chain_epilogue(StoredEdge* leak_context_edge, const Edge* root) const;
+
+  StoredEdge* associate_leak_context_with_candidate(const Edge* edge);
+  void store_gc_root_id_in_leak_context_edge(StoredEdge* leak_context_edge, const Edge* root) const;
+  StoredEdge* link_new_edge(StoredEdge** previous, const Edge** current);
+  void link_with_existing_chain(const StoredEdge* current_stored, StoredEdge** previous, size_t previous_length);
+
+  template <typename T>
+  void iterate(T& functor) const { _edges->iterate_value<T>(functor); }
+
+  DEBUG_ONLY(bool contains(const oop* reference) const;)
 
  public:
   EdgeStore();
   ~EdgeStore();
 
-  void add_chain(const Edge* chain, size_t length);
   bool is_empty() const;
-  size_t number_of_entries() const;
-
   traceid get_id(const Edge* edge) const;
-  traceid get_root_id(const Edge* edge) const;
-
-  template <typename T>
-  void iterate_edges(T& functor) const { _edges->iterate_value<T>(functor); }
+  void put_chain(const Edge* chain, size_t length);
 };
 
 #endif // SHARE_JFR_LEAKPROFILER_CHAINS_EDGESTORE_HPP
--- a/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -38,11 +38,7 @@
   return (const Edge*)edge.pointee()->mark() == &edge;
 }
 
-bool EdgeUtils::is_root(const Edge& edge) {
-  return edge.is_root();
-}
-
-static int field_offset(const Edge& edge) {
+static int field_offset(const StoredEdge& edge) {
   assert(!edge.is_root(), "invariant");
   const oop ref_owner = edge.reference_owner();
   assert(ref_owner != NULL, "invariant");
@@ -56,7 +52,7 @@
   return offset;
 }
 
-static const InstanceKlass* field_type(const Edge& edge) {
+static const InstanceKlass* field_type(const StoredEdge& edge) {
   assert(!edge.is_root() || !EdgeUtils::is_array_element(edge), "invariant");
   return (const InstanceKlass*)edge.reference_owner_klass();
 }
@@ -138,175 +134,18 @@
     current = parent;
     parent = current->parent();
   }
-  return current;
-}
-
-// The number of references associated with the leak node;
-// can be viewed as the leak node "context".
-// Used to provide leak context for a "capped/skipped" reference chain.
-static const size_t leak_context = 100;
-
-// The number of references associated with the root node;
-// can be viewed as the root node "context".
-// Used to provide root context for a "capped/skipped" reference chain.
-static const size_t root_context = 100;
-
-// A limit on the reference chain depth to be serialized,
-static const size_t max_ref_chain_depth = leak_context + root_context;
-
-const RoutableEdge* skip_to(const RoutableEdge& edge, size_t skip_length) {
-  const RoutableEdge* current = &edge;
-  const RoutableEdge* parent = current->physical_parent();
-  size_t seek = 0;
-  while (parent != NULL && seek != skip_length) {
-    seek++;
-    current = parent;
-    parent = parent->physical_parent();
-  }
-  return current;
-}
-
-#ifdef ASSERT
-static void validate_skip_target(const RoutableEdge* skip_target) {
-  assert(skip_target != NULL, "invariant");
-  assert(skip_target->distance_to_root() + 1 == root_context, "invariant");
-  assert(skip_target->is_sentinel(), "invariant");
-}
-
-static void validate_new_skip_edge(const RoutableEdge* new_skip_edge, const RoutableEdge* last_skip_edge, size_t adjustment) {
-  assert(new_skip_edge != NULL, "invariant");
-  assert(new_skip_edge->is_skip_edge(), "invariant");
-  if (last_skip_edge != NULL) {
-    const RoutableEdge* const target = skip_to(*new_skip_edge->logical_parent(), adjustment);
-    validate_skip_target(target->logical_parent());
-    return;
-  }
-  assert(last_skip_edge == NULL, "invariant");
-  // only one level of logical indirection
-  validate_skip_target(new_skip_edge->logical_parent());
-}
-#endif // ASSERT
-
-static void install_logical_route(const RoutableEdge* new_skip_edge, size_t skip_target_distance) {
-  assert(new_skip_edge != NULL, "invariant");
-  assert(!new_skip_edge->is_skip_edge(), "invariant");
-  assert(!new_skip_edge->processed(), "invariant");
-  const RoutableEdge* const skip_target = skip_to(*new_skip_edge, skip_target_distance);
-  assert(skip_target != NULL, "invariant");
-  new_skip_edge->set_skip_edge(skip_target);
-  new_skip_edge->set_skip_length(skip_target_distance);
-  assert(new_skip_edge->is_skip_edge(), "invariant");
-  assert(new_skip_edge->logical_parent() == skip_target, "invariant");
-}
-
-static const RoutableEdge* find_last_skip_edge(const RoutableEdge& edge, size_t& distance) {
-  assert(distance == 0, "invariant");
-  const RoutableEdge* current = &edge;
-  while (current != NULL) {
-    if (current->is_skip_edge() && current->skip_edge()->is_sentinel()) {
-      return current;
-    }
-    current = current->physical_parent();
-    ++distance;
-  }
+  assert(current != NULL, "invariant");
   return current;
 }
 
-static void collapse_overlapping_chain(const RoutableEdge& edge,
-                                       const RoutableEdge* first_processed_edge,
-                                       size_t first_processed_distance) {
-  assert(first_processed_edge != NULL, "invariant");
-  // first_processed_edge is already processed / written
-  assert(first_processed_edge->processed(), "invariant");
-  assert(first_processed_distance + 1 <= leak_context, "invariant");
-
-  // from this first processed edge, attempt to fetch the last skip edge
-  size_t last_skip_edge_distance = 0;
-  const RoutableEdge* const last_skip_edge = find_last_skip_edge(*first_processed_edge, last_skip_edge_distance);
-  const size_t distance_discovered = first_processed_distance + last_skip_edge_distance + 1;
-
-  if (distance_discovered <= leak_context || (last_skip_edge == NULL && distance_discovered <= max_ref_chain_depth)) {
-    // complete chain can be accommodated without modification
-    return;
-  }
-
-  // backtrack one edge from existing processed edge
-  const RoutableEdge* const new_skip_edge = skip_to(edge, first_processed_distance - 1);
-  assert(new_skip_edge != NULL, "invariant");
-  assert(!new_skip_edge->processed(), "invariant");
-  assert(new_skip_edge->parent() == first_processed_edge, "invariant");
-
-  size_t adjustment = 0;
-  if (last_skip_edge != NULL) {
-    assert(leak_context - 1 > first_processed_distance - 1, "invariant");
-    adjustment = leak_context - first_processed_distance - 1;
-    assert(last_skip_edge_distance + 1 > adjustment, "invariant");
-    install_logical_route(new_skip_edge, last_skip_edge_distance + 1 - adjustment);
-  } else {
-    install_logical_route(new_skip_edge, last_skip_edge_distance + 1 - root_context);
-    new_skip_edge->logical_parent()->set_skip_length(1); // sentinel
+const Edge* EdgeUtils::ancestor(const Edge& edge, size_t distance) {
+  const Edge* current = &edge;
+  const Edge* parent = current->parent();
+  size_t seek = 0;
+  while (parent != NULL && seek != distance) {
+    seek++;
+    current = parent;
+    parent = parent->parent();
   }
-
-  DEBUG_ONLY(validate_new_skip_edge(new_skip_edge, last_skip_edge, adjustment);)
-}
-
-static void collapse_non_overlapping_chain(const RoutableEdge& edge,
-                                           const RoutableEdge* first_processed_edge,
-                                           size_t first_processed_distance) {
-  assert(first_processed_edge != NULL, "invariant");
-  assert(!first_processed_edge->processed(), "invariant");
-  // this implies that the first "processed" edge is the leak context relative "leaf"
-  assert(first_processed_distance + 1 == leak_context, "invariant");
-
-  const size_t distance_to_root = edge.distance_to_root();
-  if (distance_to_root + 1 <= max_ref_chain_depth) {
-    // complete chain can be accommodated without constructing a skip edge
-    return;
-  }
-
-  install_logical_route(first_processed_edge, distance_to_root + 1 - first_processed_distance - root_context);
-  first_processed_edge->logical_parent()->set_skip_length(1); // sentinel
-
-  DEBUG_ONLY(validate_new_skip_edge(first_processed_edge, NULL, 0);)
-}
-
-static const RoutableEdge* processed_edge(const RoutableEdge& edge, size_t& distance) {
-  assert(distance == 0, "invariant");
-  const RoutableEdge* current = &edge;
-  while (current != NULL && distance < leak_context - 1) {
-    if (current->processed()) {
-      return current;
-    }
-    current = current->physical_parent();
-    ++distance;
-  }
-  assert(distance <= leak_context - 1, "invariant");
   return current;
 }
-
-/*
- * Some vocabulary:
- * -----------
- * "Context" is an interval in the chain, it is associcated with an edge and it signifies a number of connected edges.
- * "Processed / written" means an edge that has already been serialized.
- * "Skip edge" is an edge that contains additional information for logical routing purposes.
- * "Skip target" is an edge used as a destination for a skip edge
- */
-void EdgeUtils::collapse_chain(const RoutableEdge& edge) {
-  assert(is_leak_edge(edge), "invariant");
-
-  // attempt to locate an already processed edge inside current leak context (if any)
-  size_t first_processed_distance = 0;
-  const RoutableEdge* const first_processed_edge = processed_edge(edge, first_processed_distance);
-  if (first_processed_edge == NULL) {
-    return;
-  }
-
-  if (first_processed_edge->processed()) {
-    collapse_overlapping_chain(edge, first_processed_edge, first_processed_distance);
-  } else {
-    collapse_non_overlapping_chain(edge, first_processed_edge, first_processed_distance);
-  }
-
-  assert(edge.logical_distance_to_root() + 1 <= max_ref_chain_depth, "invariant");
-}
--- a/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeUtils.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -28,15 +28,17 @@
 #include "memory/allocation.hpp"
 
 class Edge;
-class RoutableEdge;
 class Symbol;
 
 class EdgeUtils : public AllStatic {
  public:
-  static bool is_leak_edge(const Edge& edge);
+  static const size_t leak_context = 100;
+  static const size_t root_context = 100;
+  static const size_t max_ref_chain_depth = leak_context + root_context;
 
+  static bool is_leak_edge(const Edge& edge);
   static const Edge* root(const Edge& edge);
-  static bool is_root(const Edge& edge);
+  static const Edge* ancestor(const Edge& edge, size_t distance);
 
   static bool is_array_element(const Edge& edge);
   static int array_index(const Edge& edge);
@@ -44,8 +46,6 @@
 
   static const Symbol* field_name_symbol(const Edge& edge);
   static jshort field_modifiers(const Edge& edge);
-
-  static void collapse_chain(const RoutableEdge& edge);
 };
 
 #endif // SHARE_JFR_LEAKPROFILER_CHAINS_EDGEUTILS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/leakprofiler/chains/pathToGcRootsOperation.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "jfr/leakprofiler/leakProfiler.hpp"
+#include "jfr/leakprofiler/chains/bfsClosure.hpp"
+#include "jfr/leakprofiler/chains/bitset.hpp"
+#include "jfr/leakprofiler/chains/dfsClosure.hpp"
+#include "jfr/leakprofiler/chains/edge.hpp"
+#include "jfr/leakprofiler/chains/edgeQueue.hpp"
+#include "jfr/leakprofiler/chains/edgeStore.hpp"
+#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
+#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
+#include "jfr/leakprofiler/chains/edgeStore.hpp"
+#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
+#include "jfr/leakprofiler/chains/pathToGcRootsOperation.hpp"
+#include "jfr/leakprofiler/checkpoint/eventEmitter.hpp"
+#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
+#include "jfr/leakprofiler/sampling/objectSample.hpp"
+#include "jfr/leakprofiler/sampling/objectSampler.hpp"
+#include "jfr/leakprofiler/utilities/granularTimer.hpp"
+#include "logging/log.hpp"
+#include "memory/universe.hpp"
+#include "oops/markOop.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/safepoint.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+PathToGcRootsOperation::PathToGcRootsOperation(ObjectSampler* sampler, EdgeStore* edge_store, int64_t cutoff, bool emit_all) :
+  _sampler(sampler),_edge_store(edge_store), _cutoff_ticks(cutoff), _emit_all(emit_all) {}
+
+/* The EdgeQueue is backed by directly managed virtual memory.
+ * We will attempt to dimension an initial reservation
+ * in proportion to the size of the heap (represented by heap_region).
+ * Initial memory reservation: 5% of the heap OR at least 32 Mb
+ * Commit ratio: 1 : 10 (subject to allocation granularties)
+ */
+static size_t edge_queue_memory_reservation(const MemRegion& heap_region) {
+  const size_t memory_reservation_bytes = MAX2(heap_region.byte_size() / 20, 32*M);
+  assert(memory_reservation_bytes >= (size_t)32*M, "invariant");
+  return memory_reservation_bytes;
+}
+
+static size_t edge_queue_memory_commit_size(size_t memory_reservation_bytes) {
+  const size_t memory_commit_block_size_bytes = memory_reservation_bytes / 10;
+  assert(memory_commit_block_size_bytes >= (size_t)3*M, "invariant");
+  return memory_commit_block_size_bytes;
+}
+
+static void log_edge_queue_summary(const EdgeQueue& edge_queue) {
+  log_trace(jfr, system)("EdgeQueue reserved size total: " SIZE_FORMAT " [KB]", edge_queue.reserved_size() / K);
+  log_trace(jfr, system)("EdgeQueue edges total: " SIZE_FORMAT, edge_queue.top());
+  log_trace(jfr, system)("EdgeQueue liveset total: " SIZE_FORMAT " [KB]", edge_queue.live_set() / K);
+  if (edge_queue.reserved_size() > 0) {
+    log_trace(jfr, system)("EdgeQueue commit reserve ratio: %f\n",
+      ((double)edge_queue.live_set() / (double)edge_queue.reserved_size()));
+  }
+}
+
+void PathToGcRootsOperation::doit() {
+  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
+  assert(_cutoff_ticks > 0, "invariant");
+
+  // The bitset used for marking is dimensioned as a function of the heap size
+  const MemRegion heap_region = Universe::heap()->reserved_region();
+  BitSet mark_bits(heap_region);
+
+  // The edge queue is dimensioned as a fraction of the heap size
+  const size_t edge_queue_reservation_size = edge_queue_memory_reservation(heap_region);
+  EdgeQueue edge_queue(edge_queue_reservation_size, edge_queue_memory_commit_size(edge_queue_reservation_size));
+
+  // The initialize() routines will attempt to reserve and allocate backing storage memory.
+  // Failure to accommodate will render root chain processing impossible.
+  // As a fallback on failure, just write out the existing samples, flat, without chains.
+  if (!(mark_bits.initialize() && edge_queue.initialize())) {
+    log_warning(jfr)("Unable to allocate memory for root chain processing");
+    return;
+  }
+
+  // Save the original markWord for the potential leak objects,
+  // to be restored on function exit
+  ObjectSampleMarker marker;
+  if (ObjectSampleCheckpoint::mark(_sampler, marker, _emit_all) == 0) {
+    // no valid samples to process
+    return;
+  }
+
+  // Necessary condition for attempting a root set iteration
+  Universe::heap()->ensure_parsability(false);
+
+  BFSClosure bfs(&edge_queue, _edge_store, &mark_bits);
+  RootSetClosure<BFSClosure> roots(&bfs);
+
+  GranularTimer::start(_cutoff_ticks, 1000000);
+  roots.process();
+  if (edge_queue.is_full()) {
+    // Pathological case where roots don't fit in queue
+    // Do a depth-first search, but mark roots first
+    // to avoid walking sideways over roots
+    DFSClosure::find_leaks_from_root_set(_edge_store, &mark_bits);
+  } else {
+    bfs.process();
+  }
+  GranularTimer::stop();
+  log_edge_queue_summary(edge_queue);
+
+  // Emit old objects including their reference chains as events
+  EventEmitter emitter(GranularTimer::start_time(), GranularTimer::end_time());
+  emitter.write_events(_sampler, _edge_store, _emit_all);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/leakprofiler/chains/pathToGcRootsOperation.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+#ifndef SHARE_JFR_LEAKPROFILER_CHAINS_PATHTOGCROOTSOPERATION_HPP
+#define SHARE_JFR_LEAKPROFILER_CHAINS_PATHTOGCROOTSOPERATION_HPP
+
+#include "jfr/leakprofiler/utilities/vmOperation.hpp"
+
+class EdgeStore;
+class ObjectSampler;
+
+// Safepoint operation for finding paths to gc roots
+class PathToGcRootsOperation : public OldObjectVMOperation {
+ private:
+  ObjectSampler* _sampler;
+  EdgeStore* const _edge_store;
+  const int64_t _cutoff_ticks;
+  const bool _emit_all;
+
+ public:
+  PathToGcRootsOperation(ObjectSampler* sampler, EdgeStore* edge_store, int64_t cutoff, bool emit_all);
+  virtual void doit();
+};
+
+#endif // SHARE_JFR_LEAKPROFILER_CHAINS_PATHTOGCROOTSOPERATION_HPP
--- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -28,12 +28,14 @@
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/strongRootsScope.hpp"
+#include "jfr/leakprofiler/chains/bfsClosure.hpp"
+#include "jfr/leakprofiler/chains/dfsClosure.hpp"
 #include "jfr/leakprofiler/chains/edgeQueue.hpp"
 #include "jfr/leakprofiler/chains/rootSetClosure.hpp"
-#include "jfr/leakprofiler/utilities/saveRestore.hpp"
 #include "jfr/leakprofiler/utilities/unifiedOop.hpp"
 #include "memory/universe.hpp"
 #include "oops/access.inline.hpp"
+#include "oops/oop.inline.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/synchronizer.hpp"
@@ -44,11 +46,11 @@
 #include "jvmci/jvmci.hpp"
 #endif
 
-RootSetClosure::RootSetClosure(EdgeQueue* edge_queue) :
-  _edge_queue(edge_queue) {
-}
+template <typename Delegate>
+RootSetClosure<Delegate>::RootSetClosure(Delegate* delegate) : _delegate(delegate) {}
 
-void RootSetClosure::do_oop(oop* ref) {
+template <typename Delegate>
+void RootSetClosure<Delegate>::do_oop(oop* ref) {
   assert(ref != NULL, "invariant");
   // We discard unaligned root references because
   // our reference tagging scheme will use
@@ -62,50 +64,40 @@
   }
 
   assert(is_aligned(ref, HeapWordSize), "invariant");
-  const oop pointee = *ref;
-  if (pointee != NULL) {
-    closure_impl(ref, pointee);
+  if (*ref != NULL) {
+    _delegate->do_root(ref);
   }
 }
 
-void RootSetClosure::do_oop(narrowOop* ref) {
+template <typename Delegate>
+void RootSetClosure<Delegate>::do_oop(narrowOop* ref) {
   assert(ref != NULL, "invariant");
   assert(is_aligned(ref, sizeof(narrowOop)), "invariant");
   const oop pointee = RawAccess<>::oop_load(ref);
   if (pointee != NULL) {
-    closure_impl(UnifiedOop::encode(ref), pointee);
-  }
-}
-
-void RootSetClosure::closure_impl(const oop* reference, const oop pointee) {
-  if (!_edge_queue->is_full())  {
-    _edge_queue->add(NULL, reference);
+    _delegate->do_root(UnifiedOop::encode(ref));
   }
 }
 
-void RootSetClosure::add_to_queue(EdgeQueue* edge_queue) {
-  RootSetClosure rs(edge_queue);
-  process_roots(&rs);
+class RootSetClosureMarkScope : public MarkScope {};
+
+template <typename Delegate>
+void RootSetClosure<Delegate>::process() {
+  RootSetClosureMarkScope mark_scope;
+  CLDToOopClosure cldt_closure(this, ClassLoaderData::_claim_none);
+  ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
+  CodeBlobToOopClosure blobs(this, false);
+  Threads::oops_do(this, &blobs);
+  ObjectSynchronizer::oops_do(this);
+  Universe::oops_do(this);
+  JNIHandles::oops_do(this);
+  JvmtiExport::oops_do(this);
+  SystemDictionary::oops_do(this);
+  Management::oops_do(this);
+  StringTable::oops_do(this);
+  AOTLoader::oops_do(this);
+  JVMCI_ONLY(JVMCI::oops_do(this);)
 }
 
-class RootSetClosureMarkScope : public MarkScope {
-};
-
-void RootSetClosure::process_roots(OopClosure* closure) {
-  SaveRestoreCLDClaimBits save_restore_cld_claim_bits;
-  RootSetClosureMarkScope mark_scope;
-
-  CLDToOopClosure cldt_closure(closure, ClassLoaderData::_claim_strong);
-  ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
-  CodeBlobToOopClosure blobs(closure, false);
-  Threads::oops_do(closure, &blobs);
-  ObjectSynchronizer::oops_do(closure);
-  Universe::oops_do(closure);
-  JNIHandles::oops_do(closure);
-  JvmtiExport::oops_do(closure);
-  SystemDictionary::oops_do(closure);
-  Management::oops_do(closure);
-  StringTable::oops_do(closure);
-  AOTLoader::oops_do(closure);
-  JVMCI_ONLY(JVMCI::oops_do(closure);)
-}
+template class RootSetClosure<BFSClosure>;
+template class RootSetClosure<DFSClosure>;
--- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -26,18 +26,14 @@
 #define SHARE_JFR_LEAKPROFILER_CHAINS_ROOTSETCLOSURE_HPP
 
 #include "memory/iterator.hpp"
-#include "oops/oop.hpp"
 
-class EdgeQueue;
-
+template <typename Delegate>
 class RootSetClosure: public BasicOopIterateClosure {
  private:
-  RootSetClosure(EdgeQueue* edge_queue);
-  EdgeQueue* _edge_queue;
-  void closure_impl(const oop* reference, const oop pointee);
+  Delegate* const _delegate;
  public:
-  static void add_to_queue(EdgeQueue* edge_queue);
-  static void process_roots(OopClosure* closure);
+  RootSetClosure(Delegate* delegate);
+  void process();
 
   virtual void do_oop(oop* reference);
   virtual void do_oop(narrowOop* reference);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/eventEmitter.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jfr/jfrEvents.hpp"
+#include "jfr/leakprofiler/chains/edgeStore.hpp"
+#include "jfr/leakprofiler/chains/pathToGcRootsOperation.hpp"
+#include "jfr/leakprofiler/checkpoint/eventEmitter.hpp"
+#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
+#include "jfr/leakprofiler/sampling/objectSample.hpp"
+#include "jfr/leakprofiler/sampling/objectSampler.hpp"
+#include "logging/log.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/markOop.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/vmThread.hpp"
+
+EventEmitter::EventEmitter(const JfrTicks& start_time, const JfrTicks& end_time) :
+  _start_time(start_time),
+  _end_time(end_time),
+  _thread(Thread::current()),
+  _jfr_thread_local(_thread->jfr_thread_local()),
+  _thread_id(_thread->jfr_thread_local()->thread_id()) {}
+
+EventEmitter::~EventEmitter() {
+  // restore / reset thread local stack trace and thread id
+  _jfr_thread_local->set_thread_id(_thread_id);
+  _jfr_thread_local->clear_cached_stack_trace();
+}
+
+void EventEmitter::emit(ObjectSampler* sampler, int64_t cutoff_ticks, bool emit_all) {
+  assert(sampler != NULL, "invariant");
+
+  ResourceMark rm;
+  EdgeStore edge_store;
+  if (cutoff_ticks <= 0) {
+    // no reference chains
+    JfrTicks time_stamp = JfrTicks::now();
+    EventEmitter emitter(time_stamp, time_stamp);
+    emitter.write_events(sampler, &edge_store, emit_all);
+    return;
+  }
+  // events emitted with reference chains require a safepoint operation
+  PathToGcRootsOperation op(sampler, &edge_store, cutoff_ticks, emit_all);
+  VMThread::execute(&op);
+}
+
+size_t EventEmitter::write_events(ObjectSampler* object_sampler, EdgeStore* edge_store, bool emit_all) {
+  assert(_thread == Thread::current(), "invariant");
+  assert(_thread->jfr_thread_local() == _jfr_thread_local, "invariant");
+  assert(object_sampler != NULL, "invariant");
+  assert(edge_store != NULL, "invariant");
+
+  const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
+  size_t count = 0;
+
+  const ObjectSample* current = object_sampler->first();
+  while (current != NULL) {
+    ObjectSample* prev = current->prev();
+    if (current->is_alive_and_older_than(last_sweep)) {
+      write_event(current, edge_store);
+      ++count;
+    }
+    current = prev;
+  }
+
+  if (count > 0) {
+    // serialize associated checkpoints and potential chains
+    ObjectSampleCheckpoint::write(object_sampler, edge_store, emit_all, _thread);
+  }
+  return count;
+}
+
+static int array_size(const oop object) {
+  assert(object != NULL, "invariant");
+  if (object->is_array()) {
+    return arrayOop(object)->length();
+  }
+  return min_jint;
+}
+
+void EventEmitter::write_event(const ObjectSample* sample, EdgeStore* edge_store) {
+  assert(sample != NULL, "invariant");
+  assert(!sample->is_dead(), "invariant");
+  assert(edge_store != NULL, "invariant");
+  assert(_jfr_thread_local != NULL, "invariant");
+
+  const oop* object_addr = sample->object_addr();
+  traceid gc_root_id = 0;
+  const Edge* edge = NULL;
+  if (SafepointSynchronize::is_at_safepoint()) {
+    edge = (const Edge*)(*object_addr)->mark();
+  }
+  if (edge == NULL) {
+    // In order to dump out a representation of the event
+    // even though it was not reachable / too long to reach,
+    // we need to register a top level edge for this object.
+    edge = edge_store->put(object_addr);
+  } else {
+    gc_root_id = edge_store->gc_root_id(edge);
+  }
+
+  assert(edge != NULL, "invariant");
+  const traceid object_id = edge_store->get_id(edge);
+  assert(object_id != 0, "invariant");
+
+  EventOldObjectSample e(UNTIMED);
+  e.set_starttime(_start_time);
+  e.set_endtime(_end_time);
+  e.set_allocationTime(sample->allocation_time());
+  e.set_lastKnownHeapUsage(sample->heap_used_at_last_gc());
+  e.set_object(object_id);
+  e.set_arrayElements(array_size(edge->pointee()));
+  e.set_root(gc_root_id);
+
+  // Temporarily assigning both the stack trace id and thread id
+  // onto the thread local data structure of the emitter thread (for the duration
+  // of the commit() call). This trick provides a means to override
+  // the event generation mechanism by injecting externally provided id's.
+  // At this particular location, it allows us to emit an old object event
+  // supplying information from where the actual sampling occurred.
+  _jfr_thread_local->set_cached_stack_trace_id(sample->stack_trace_id());
+  assert(sample->has_thread(), "invariant");
+  _jfr_thread_local->set_thread_id(sample->thread_id());
+  e.commit();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/eventEmitter.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+#ifndef SHARE_JFR_LEAKPROFILER_CHECKPOINT_EVENTEMITTER_HPP
+#define SHARE_JFR_LEAKPROFILER_CHECKPOINT_EVENTEMITTER_HPP
+
+#include "memory/allocation.hpp"
+#include "jfr/utilities/jfrTime.hpp"
+
+typedef u8 traceid;
+
+class EdgeStore;
+class JfrThreadLocal;
+class ObjectSample;
+class ObjectSampler;
+class Thread;
+
+class EventEmitter : public CHeapObj<mtTracing> {
+  friend class LeakProfiler;
+  friend class PathToGcRootsOperation;
+ private:
+  const JfrTicks& _start_time;
+  const JfrTicks& _end_time;
+  Thread* _thread;
+  JfrThreadLocal* _jfr_thread_local;
+  traceid _thread_id;
+
+  EventEmitter(const JfrTicks& start_time, const JfrTicks& end_time);
+  ~EventEmitter();
+
+  void write_event(const ObjectSample* sample, EdgeStore* edge_store);
+  size_t write_events(ObjectSampler* sampler, EdgeStore* store, bool emit_all);
+
+  static void emit(ObjectSampler* sampler, int64_t cutoff_ticks, bool emit_all);
+};
+
+#endif // SHARE_JFR_LEAKPROFILER_CHECKPOINT_EVENTEMITTER_HPP
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -181,21 +181,18 @@
   }
 };
 
-void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload, bool resume) {
-  assert(class_unload ? SafepointSynchronize::is_at_safepoint() : LeakProfiler::is_suspended(), "invariant");
-
+void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload) {
   if (!writer.has_data()) {
-    if (!class_unload) {
-      LeakProfiler::resume();
-    }
-    assert(LeakProfiler::is_running(), "invariant");
     return;
   }
 
   assert(writer.has_data(), "invariant");
   const JfrCheckpointBlobHandle h_cp = writer.checkpoint_blob();
 
-  const ObjectSampler* const object_sampler = LeakProfiler::object_sampler();
+  // Class unload implies a safepoint.
+  // Not class unload implies the object sampler is locked, because it was claimed exclusively earlier.
+  // Therefore: direct access the object sampler instance is safe.
+  const ObjectSampler* const object_sampler = ObjectSampler::sampler();
   assert(object_sampler != NULL, "invariant");
 
   ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
@@ -203,80 +200,71 @@
   CheckpointInstall install(h_cp);
 
   if (class_unload) {
-    if (last != NULL) {
-      // all samples need the class unload information
-      do_samples(last, NULL, install);
-    }
-    assert(LeakProfiler::is_running(), "invariant");
+    // all samples need class unload information
+    do_samples(last, NULL, install);
     return;
   }
 
   // only new samples since last resolved checkpoint
   if (last != last_resolved) {
     do_samples(last, last_resolved, install);
-    if (resume) {
-      const_cast<ObjectSampler*>(object_sampler)->set_last_resolved(last);
-    }
-  }
-  assert(LeakProfiler::is_suspended(), "invariant");
-  if (resume) {
-    LeakProfiler::resume();
-    assert(LeakProfiler::is_running(), "invariant");
+    const_cast<ObjectSampler*>(object_sampler)->set_last_resolved(last);
   }
 }
 
-void ObjectSampleCheckpoint::write(const EdgeStore* edge_store, bool emit_all, Thread* thread) {
+void ObjectSampleCheckpoint::write(ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread) {
+  assert(sampler != NULL, "invariant");
   assert(edge_store != NULL, "invariant");
   assert(thread != NULL, "invariant");
+
   static bool types_registered = false;
   if (!types_registered) {
     JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType());
     JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType());
     types_registered = true;
   }
-  const ObjectSampler* const object_sampler = LeakProfiler::object_sampler();
-  assert(object_sampler != NULL, "invariant");
-  const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
-  ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
+
+  const jlong last_sweep = emit_all ? max_jlong : sampler->last_sweep().value();
+  ObjectSample* const last = const_cast<ObjectSample*>(sampler->last());
   {
     JfrCheckpointWriter writer(false, false, thread);
     CheckpointWrite checkpoint_write(writer, last_sweep);
     do_samples(last, NULL, checkpoint_write);
   }
+
   CheckpointStateReset state_reset(last_sweep);
   do_samples(last, NULL, state_reset);
+
   if (!edge_store->is_empty()) {
     // java object and chain representations
     JfrCheckpointWriter writer(false, true, thread);
     ObjectSampleWriter osw(writer, edge_store);
-    edge_store->iterate_edges(osw);
+    edge_store->iterate(osw);
   }
 }
 
-WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(JfrStackTraceRepository& repo) :
-  _stack_trace_repo(repo) {
+int ObjectSampleCheckpoint::mark(ObjectSampler* object_sampler, ObjectSampleMarker& marker, bool emit_all) {
+  assert(object_sampler != NULL, "invariant");
+  ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
+  if (last == NULL) {
+    return 0;
+  }
+  const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
+  SampleMark mark(marker, last_sweep);
+  do_samples(last, NULL, mark);
+  return mark.count();
 }
 
+WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(ObjectSampler* sampler, JfrStackTraceRepository& repo) :
+  _sampler(sampler), _stack_trace_repo(repo) {}
+
 bool WriteObjectSampleStacktrace::process() {
-  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
-  if (!LeakProfiler::is_running()) {
-    return true;
-  }
-  // Suspend the LeakProfiler subsystem
-  // to ensure stable samples even
-  // after we return from the safepoint.
-  LeakProfiler::suspend();
-  assert(!LeakProfiler::is_running(), "invariant");
-  assert(LeakProfiler::is_suspended(), "invariant");
+  assert(LeakProfiler::is_running(), "invariant");
+  assert(_sampler != NULL, "invariant");
 
-  const ObjectSampler* object_sampler = LeakProfiler::object_sampler();
-  assert(object_sampler != NULL, "invariant");
-  assert(LeakProfiler::is_suspended(), "invariant");
-
-  ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
-  const ObjectSample* const last_resolved = object_sampler->last_resolved();
+  ObjectSample* const last = const_cast<ObjectSample*>(_sampler->last());
+  const ObjectSample* const last_resolved = _sampler->last_resolved();
   if (last == last_resolved) {
-    assert(LeakProfiler::is_suspended(), "invariant");
     return true;
   }
 
@@ -294,27 +282,13 @@
   }
   if (count == 0) {
     writer.set_context(ctx);
-    assert(LeakProfiler::is_suspended(), "invariant");
     return true;
   }
   assert(count > 0, "invariant");
   writer.write_count((u4)count, count_offset);
   JfrStackTraceRepository::write_metadata(writer);
 
-  ObjectSampleCheckpoint::install(writer, false, false);
-  assert(LeakProfiler::is_suspended(), "invariant");
+  // install the stacktrace checkpoint information to the candidates
+  ObjectSampleCheckpoint::install(writer, false);
   return true;
 }
-
-int ObjectSampleCheckpoint::mark(ObjectSampleMarker& marker, bool emit_all) {
-  const ObjectSampler* object_sampler = LeakProfiler::object_sampler();
-  assert(object_sampler != NULL, "invariant");
-  ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
-  if (last == NULL) {
-    return 0;
-  }
-  const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
-  SampleMark mark(marker, last_sweep);
-  do_samples(last, NULL, mark);
-  return mark.count();
-}
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -26,25 +26,26 @@
 #define SHARE_JFR_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLECHECKPOINT_HPP
 
 #include "memory/allocation.hpp"
-#include "utilities/exceptions.hpp"
 
 class EdgeStore;
+class JfrCheckpointWriter;
 class JfrStackTraceRepository;
-class JfrCheckpointWriter;
 class ObjectSampleMarker;
+class ObjectSampler;
 
 class ObjectSampleCheckpoint : AllStatic {
  public:
-  static void install(JfrCheckpointWriter& writer, bool class_unload, bool resume);
-  static void write(const EdgeStore* edge_store, bool emit_all, Thread* thread);
-  static int mark(ObjectSampleMarker& marker, bool emit_all);
+  static void install(JfrCheckpointWriter& writer, bool class_unload);
+  static void write(ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread);
+  static int mark(ObjectSampler* sampler, ObjectSampleMarker& marker, bool emit_all);
 };
 
 class WriteObjectSampleStacktrace : public StackObj {
  private:
+  ObjectSampler* const _sampler;
   JfrStackTraceRepository& _stack_trace_repo;
  public:
-  WriteObjectSampleStacktrace(JfrStackTraceRepository& repo);
+  WriteObjectSampleStacktrace(ObjectSampler* sampler, JfrStackTraceRepository& repo);
   bool process();
 };
 
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -350,7 +350,7 @@
   return 1;
 }
 
-static traceid get_root_description_info_id(const Edge& edge, traceid id) {
+static traceid get_gc_root_description_info_id(const Edge& edge, traceid id) {
   assert(edge.is_root(), "invariant");
   if (EdgeUtils::is_leak_edge(edge)) {
     return 0;
@@ -518,7 +518,7 @@
   }
 }
 
-static void add_old_object_sample_info(const Edge* current, traceid id) {
+static void add_old_object_sample_info(const StoredEdge* current, traceid id) {
   assert(current != NULL, "invariant");
   if (sample_infos == NULL) {
     sample_infos = new SampleInfo();
@@ -528,11 +528,11 @@
   assert(oosi != NULL, "invariant");
   oosi->_id = id;
   oosi->_data._object = current->pointee();
-  oosi->_data._reference_id = current->is_root() ? (traceid)0 : id;
+  oosi->_data._reference_id = current->parent() == NULL ? (traceid)0 : id;
   sample_infos->store(oosi);
 }
 
-static void add_reference_info(const RoutableEdge* current, traceid id, traceid parent_id) {
+static void add_reference_info(const StoredEdge* current, traceid id, traceid parent_id) {
   assert(current != NULL, "invariant");
   if (ref_infos == NULL) {
     ref_infos = new RefInfo();
@@ -544,37 +544,43 @@
 
   ri->_id = id;
   ri->_data._array_info_id =  !current->is_skip_edge() ? get_array_info_id(*current, id) : 0;
-  ri->_data._field_info_id = ri->_data._array_info_id == 0 && !current->is_skip_edge() ?
-                               get_field_info_id(*current) : (traceid)0;
+  ri->_data._field_info_id = ri->_data._array_info_id == 0 && !current->is_skip_edge() ? get_field_info_id(*current) : (traceid)0;
   ri->_data._old_object_sample_id = parent_id;
   ri->_data._skip = current->skip_length();
   ref_infos->store(ri);
 }
 
-static traceid add_root_info(const Edge* root, traceid id) {
-  assert(root != NULL, "invariant");
-  assert(root->is_root(), "invariant");
-  return get_root_description_info_id(*root, id);
+static bool is_gc_root(const StoredEdge* current) {
+  assert(current != NULL, "invariant");
+  return current->parent() == NULL && current->gc_root_id() != 0;
 }
 
-void ObjectSampleWriter::write(const RoutableEdge* edge) {
+static traceid add_gc_root_info(const StoredEdge* root, traceid id) {
+  assert(root != NULL, "invariant");
+  assert(is_gc_root(root), "invariant");
+  return get_gc_root_description_info_id(*root, id);
+}
+
+void ObjectSampleWriter::write(const StoredEdge* edge) {
   assert(edge != NULL, "invariant");
   const traceid id = _store->get_id(edge);
   add_old_object_sample_info(edge, id);
-  const RoutableEdge* parent = edge->logical_parent();
+  const StoredEdge* const parent = edge->parent();
   if (parent != NULL) {
     add_reference_info(edge, id, _store->get_id(parent));
   } else {
-    assert(edge->is_root(), "invariant");
-    add_root_info(edge, id);
+    if (is_gc_root(edge)) {
+      assert(edge->gc_root_id() == id, "invariant");
+      add_gc_root_info(edge, id);
+    }
   }
 }
 
-ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, const EdgeStore* store) :
+ObjectSampleWriter::ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store) :
   _writer(writer),
   _store(store) {
   assert(store != NULL, "invariant");
-  assert(store->number_of_entries() > 0, "invariant");
+  assert(!store->is_empty(), "invariant");
   sample_infos = NULL;
   ref_infos = NULL;
   array_infos = NULL;
@@ -590,26 +596,7 @@
   write_root_descriptors(_writer);
 }
 
-void ObjectSampleWriter::write_chain(const RoutableEdge& edge) {
-  assert(EdgeUtils::is_leak_edge(edge), "invariant");
-  if (edge.processed()) {
-    return;
-  }
-  EdgeUtils::collapse_chain(edge);
-  const RoutableEdge* current = &edge;
-  while (current != NULL) {
-    if (current->processed()) {
-      return;
-    }
-    write(current);
-    current->set_processed();
-    current = current->logical_parent();
-  }
-}
-
-bool ObjectSampleWriter::operator()(const RoutableEdge& edge) {
-  if (EdgeUtils::is_leak_edge(edge)) {
-    write_chain(edge);
-  }
+bool ObjectSampleWriter::operator()(StoredEdge& e) {
+  write(&e);
   return true;
 }
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -30,21 +30,17 @@
 class Edge;
 class EdgeStore;
 class JfrCheckpointWriter;
-class RoutableEdge;
+class StoredEdge;
 
 class ObjectSampleWriter : public StackObj {
  private:
   JfrCheckpointWriter& _writer;
-  const EdgeStore* const _store;
-
-  void write(const RoutableEdge* edge);
-  void write_chain(const RoutableEdge& edge);
-
+  EdgeStore* const _store;
+  void write(const StoredEdge* edge);
  public:
-  ObjectSampleWriter(JfrCheckpointWriter& writer, const EdgeStore* store);
+  ObjectSampleWriter(JfrCheckpointWriter& writer, EdgeStore* store);
   ~ObjectSampleWriter();
-
-  bool operator()(const RoutableEdge& edge);
+  bool operator()(StoredEdge& edge);
 };
 
 #endif // SHARE_JFR_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLEWRITER_HPP
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -132,7 +132,7 @@
 bool ReferenceToRootClosure::do_cldg_roots() {
   assert(!complete(), "invariant");
   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
-  CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_strong);
+  CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_none);
   ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
   return rlc.complete();
 }
@@ -435,9 +435,6 @@
 };
 
 void RootResolver::resolve(RootCallback& callback) {
-
-  // Need to clear cld claim bit before starting
-  ClassLoaderDataGraph::clear_claimed_marks();
   RootResolverMarkScope mark_scope;
 
   // thread local roots
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -25,8 +25,8 @@
 #ifndef SHARE_JFR_LEAKPROFILER_CHECKPOINT_ROOTRESOLVER_HPP
 #define SHARE_JFR_LEAKPROFILER_CHECKPOINT_ROOTRESOLVER_HPP
 
+#include "jfr/leakprofiler/utilities/rootType.hpp"
 #include "memory/allocation.hpp"
-#include "jfr/leakprofiler/utilities/rootType.hpp"
 #include "oops/oopsHierarchy.hpp"
 
 struct RootCallbackInfo {
--- a/src/hotspot/share/jfr/leakprofiler/emitEventOperation.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- *
- */
-#include "precompiled.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "jfr/jfrEvents.hpp"
-#include "jfr/leakprofiler/utilities/granularTimer.hpp"
-#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
-#include "jfr/leakprofiler/chains/edge.hpp"
-#include "jfr/leakprofiler/chains/edgeQueue.hpp"
-#include "jfr/leakprofiler/chains/edgeStore.hpp"
-#include "jfr/leakprofiler/chains/bitset.hpp"
-#include "jfr/leakprofiler/sampling/objectSample.hpp"
-#include "jfr/leakprofiler/leakProfiler.hpp"
-#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
-#include "jfr/leakprofiler/sampling/objectSampler.hpp"
-#include "jfr/leakprofiler/emitEventOperation.hpp"
-#include "jfr/leakprofiler/chains/bfsClosure.hpp"
-#include "jfr/leakprofiler/chains/dfsClosure.hpp"
-#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
-#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
-#include "jfr/support/jfrThreadId.hpp"
-#include "logging/log.hpp"
-#include "memory/resourceArea.hpp"
-#include "memory/universe.hpp"
-#include "oops/markOop.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/safepoint.hpp"
-#include "runtime/vmThread.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-/* The EdgeQueue is backed by directly managed virtual memory.
- * We will attempt to dimension an initial reservation
- * in proportion to the size of the heap (represented by heap_region).
- * Initial memory reservation: 5% of the heap OR at least 32 Mb
- * Commit ratio: 1 : 10 (subject to allocation granularties)
- */
-static size_t edge_queue_memory_reservation(const MemRegion& heap_region) {
-  const size_t memory_reservation_bytes = MAX2(heap_region.byte_size() / 20, 32*M);
-  assert(memory_reservation_bytes >= (size_t)32*M, "invariant");
-  return memory_reservation_bytes;
-}
-
-static size_t edge_queue_memory_commit_size(size_t memory_reservation_bytes) {
-  const size_t memory_commit_block_size_bytes = memory_reservation_bytes / 10;
-  assert(memory_commit_block_size_bytes >= (size_t)3*M, "invariant");
-  return memory_commit_block_size_bytes;
-}
-
-static void log_edge_queue_summary(const EdgeQueue& edge_queue) {
-  log_trace(jfr, system)("EdgeQueue reserved size total: " SIZE_FORMAT " [KB]", edge_queue.reserved_size() / K);
-  log_trace(jfr, system)("EdgeQueue edges total: " SIZE_FORMAT, edge_queue.top());
-  log_trace(jfr, system)("EdgeQueue liveset total: " SIZE_FORMAT " [KB]", edge_queue.live_set() / K);
-  if (edge_queue.reserved_size() > 0) {
-    log_trace(jfr, system)("EdgeQueue commit reserve ratio: %f\n",
-      ((double)edge_queue.live_set() / (double)edge_queue.reserved_size()));
-  }
-}
-
-void EmitEventOperation::doit() {
-  assert(LeakProfiler::is_running(), "invariant");
-  _object_sampler = LeakProfiler::object_sampler();
-  assert(_object_sampler != NULL, "invariant");
-
-  _vm_thread = VMThread::vm_thread();
-  assert(_vm_thread == Thread::current(), "invariant");
-  _vm_thread_local = _vm_thread->jfr_thread_local();
-  assert(_vm_thread_local != NULL, "invariant");
-  assert(_vm_thread->jfr_thread_local()->thread_id() == JFR_THREAD_ID(_vm_thread), "invariant");
-
-  // The VM_Operation::evaluate() which invoked doit()
-  // contains a top level ResourceMark
-
-  // save the original markWord for the potential leak objects
-  // to be restored on function exit
-  ObjectSampleMarker marker;
-  if (ObjectSampleCheckpoint::mark(marker, _emit_all) == 0) {
-    return;
-  }
-
-  EdgeStore edge_store;
-
-  GranularTimer::start(_cutoff_ticks, 1000000);
-  if (_cutoff_ticks <= 0) {
-    // no chains
-    write_events(&edge_store);
-    return;
-  }
-
-  assert(_cutoff_ticks > 0, "invariant");
-
-  // The bitset used for marking is dimensioned as a function of the heap size
-  const MemRegion heap_region = Universe::heap()->reserved_region();
-  BitSet mark_bits(heap_region);
-
-  // The edge queue is dimensioned as a fraction of the heap size
-  const size_t edge_queue_reservation_size = edge_queue_memory_reservation(heap_region);
-  EdgeQueue edge_queue(edge_queue_reservation_size, edge_queue_memory_commit_size(edge_queue_reservation_size));
-
-  // The initialize() routines will attempt to reserve and allocate backing storage memory.
-  // Failure to accommodate will render root chain processing impossible.
-  // As a fallback on failure, just write out the existing samples, flat, without chains.
-  if (!(mark_bits.initialize() && edge_queue.initialize())) {
-    log_warning(jfr)("Unable to allocate memory for root chain processing");
-    write_events(&edge_store);
-    return;
-  }
-
-  // necessary condition for attempting a root set iteration
-  Universe::heap()->ensure_parsability(false);
-
-  RootSetClosure::add_to_queue(&edge_queue);
-  if (edge_queue.is_full()) {
-    // Pathological case where roots don't fit in queue
-    // Do a depth-first search, but mark roots first
-    // to avoid walking sideways over roots
-    DFSClosure::find_leaks_from_root_set(&edge_store, &mark_bits);
-  } else {
-    BFSClosure bfs(&edge_queue, &edge_store, &mark_bits);
-    bfs.process();
-  }
-  GranularTimer::stop();
-  write_events(&edge_store);
-  log_edge_queue_summary(edge_queue);
-}
-
-int EmitEventOperation::write_events(EdgeStore* edge_store) {
-  assert(_object_sampler != NULL, "invariant");
-  assert(edge_store != NULL, "invariant");
-  assert(_vm_thread != NULL, "invariant");
-  assert(_vm_thread_local != NULL, "invariant");
-  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
-
-  // save thread id in preparation for thread local trace data manipulations
-  const traceid vmthread_id = _vm_thread_local->thread_id();
-  assert(_vm_thread_local->thread_id() == JFR_THREAD_ID(_vm_thread), "invariant");
-
-  const jlong last_sweep = _emit_all ? max_jlong : _object_sampler->last_sweep().value();
-  int count = 0;
-
-  const ObjectSample* current = _object_sampler->first();
-  while (current != NULL) {
-    ObjectSample* prev = current->prev();
-    if (current->is_alive_and_older_than(last_sweep)) {
-      write_event(current, edge_store);
-      ++count;
-    }
-    current = prev;
-  }
-
-  // restore thread local stack trace and thread id
-  _vm_thread_local->set_thread_id(vmthread_id);
-  _vm_thread_local->clear_cached_stack_trace();
-  assert(_vm_thread_local->thread_id() == JFR_THREAD_ID(_vm_thread), "invariant");
-
-  if (count > 0) {
-    // serialize assoicated checkpoints
-    ObjectSampleCheckpoint::write(edge_store, _emit_all, _vm_thread);
-  }
-  return count;
-}
-
-static int array_size(const oop object) {
-  assert(object != NULL, "invariant");
-  if (object->is_array()) {
-    return arrayOop(object)->length();
-  }
-  return min_jint;
-}
-
-void EmitEventOperation::write_event(const ObjectSample* sample, EdgeStore* edge_store) {
-  assert(sample != NULL, "invariant");
-  assert(!sample->is_dead(), "invariant");
-  assert(edge_store != NULL, "invariant");
-  assert(_vm_thread_local != NULL, "invariant");
-  const oop* object_addr = sample->object_addr();
-  assert(*object_addr != NULL, "invariant");
-
-  const Edge* edge = (const Edge*)(*object_addr)->mark();
-  traceid gc_root_id = 0;
-  if (edge == NULL) {
-    // In order to dump out a representation of the event
-    // even though it was not reachable / too long to reach,
-    // we need to register a top level edge for this object
-    Edge e(NULL, object_addr);
-    edge_store->add_chain(&e, 1);
-    edge = (const Edge*)(*object_addr)->mark();
-  } else {
-    gc_root_id = edge_store->get_root_id(edge);
-  }
-
-  assert(edge != NULL, "invariant");
-  assert(edge->pointee() == *object_addr, "invariant");
-  const traceid object_id = edge_store->get_id(edge);
-  assert(object_id != 0, "invariant");
-
-  EventOldObjectSample e(UNTIMED);
-  e.set_starttime(GranularTimer::start_time());
-  e.set_endtime(GranularTimer::end_time());
-  e.set_allocationTime(sample->allocation_time());
-  e.set_lastKnownHeapUsage(sample->heap_used_at_last_gc());
-  e.set_object(object_id);
-  e.set_arrayElements(array_size(*object_addr));
-  e.set_root(gc_root_id);
-
-  // Temporarily assigning both the stack trace id and thread id
-  // onto the thread local data structure of the VMThread (for the duration
-  // of the commit() call). This trick provides a means to override
-  // the event generation mechanism by injecting externally provided id's.
-  // Here, in particular, this allows us to emit an old object event
-  // supplying information from where the actual sampling occurred.
-  _vm_thread_local->set_cached_stack_trace_id(sample->stack_trace_id());
-  assert(sample->has_thread(), "invariant");
-  _vm_thread_local->set_thread_id(sample->thread_id());
-  e.commit();
-}
--- a/src/hotspot/share/jfr/leakprofiler/emitEventOperation.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- *
- */
-
-#ifndef SHARE_JFR_LEAKPROFILER_EMITEVENTOPERATION_HPP
-#define SHARE_JFR_LEAKPROFILER_EMITEVENTOPERATION_HPP
-
-#include "runtime/vmOperations.hpp"
-
-class BFSClosure;
-class EdgeStore;
-class EdgeQueue;
-class JfrThreadData;
-class ObjectSample;
-class ObjectSampler;
-
-class VMThread;
-
-// Safepoint operation for emitting object sample events
-class EmitEventOperation : public VM_Operation {
- private:
-  jlong _cutoff_ticks;
-  bool _emit_all;
-  VMThread* _vm_thread;
-  JfrThreadLocal* _vm_thread_local;
-  ObjectSampler* _object_sampler;
-
-  void write_event(const ObjectSample* sample, EdgeStore* edge_store);
-  int write_events(EdgeStore* edge_store);
-
- public:
-  EmitEventOperation(jlong cutoff_ticks, bool emit_all) :
-    _cutoff_ticks(cutoff_ticks),
-    _emit_all(emit_all),
-    _vm_thread(NULL),
-    _vm_thread_local(NULL),
-    _object_sampler(NULL) {
-  }
-
-  VMOp_Type type() const {
-    return VMOp_GC_HeapInspection;
-  }
-
-  Mode evaluation_mode() const {
-    return _safepoint;
-  }
-
-  virtual void doit();
-};
-
-#endif // SHARE_JFR_LEAKPROFILER_EMITEVENTOPERATION_HPP
--- a/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/leakProfiler.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,25 +23,31 @@
  */
 
 #include "precompiled.hpp"
-#include "jfr/leakprofiler/emitEventOperation.hpp"
 #include "jfr/leakprofiler/leakProfiler.hpp"
 #include "jfr/leakprofiler/startOperation.hpp"
 #include "jfr/leakprofiler/stopOperation.hpp"
+#include "jfr/leakprofiler/checkpoint/eventEmitter.hpp"
 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
 #include "jfr/recorder/service/jfrOptionSet.hpp"
+#include "logging/log.hpp"
 #include "memory/iterator.hpp"
-#include "oops/oop.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/orderAccess.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
-#include "utilities/ostream.hpp"
+
+bool LeakProfiler::is_running() {
+  return ObjectSampler::is_created();
+}
 
-// Only to be updated during safepoint
-ObjectSampler* LeakProfiler::_object_sampler = NULL;
+bool LeakProfiler::start(int sample_count) {
+  if (is_running()) {
+    return true;
+  }
 
-static volatile jbyte suspended = 0;
-bool LeakProfiler::start(jint sample_count) {
+  // Allows user to disable leak profiler on command line by setting queue size to zero.
+  if (sample_count == 0) {
+    return false;
+  }
+
   if (UseZGC) {
     log_warning(jfr)("LeakProfiler is currently not supported in combination with ZGC");
     return false;
@@ -52,49 +58,56 @@
     return false;
   }
 
-  if (_object_sampler != NULL) {
-    // already started
-    return true;
+  assert(!is_running(), "invariant");
+  assert(sample_count > 0, "invariant");
+
+  // schedule the safepoint operation for installing the object sampler
+  StartOperation op(sample_count);
+  VMThread::execute(&op);
+
+  if (!is_running()) {
+    log_trace(jfr, system)("Object sampling could not be started because the sampler could not be allocated");
+    return false;
   }
-  // Allows user to disable leak profiler on command line by setting queue size to zero.
-  if (sample_count > 0) {
-    StartOperation op(sample_count);
-    VMThread::execute(&op);
-    return _object_sampler != NULL;
-  }
-  return false;
+  assert(is_running(), "invariant");
+  log_trace(jfr, system)("Object sampling started");
+  return true;
 }
 
 bool LeakProfiler::stop() {
-  if (_object_sampler == NULL) {
-    // already stopped/not started
-    return true;
+  if (!is_running()) {
+    return false;
   }
+
+  // schedule the safepoint operation for uninstalling and destroying the object sampler
   StopOperation op;
   VMThread::execute(&op);
-  return _object_sampler == NULL;
+
+  assert(!is_running(), "invariant");
+  log_trace(jfr, system)("Object sampling stopped");
+  return true;
 }
 
-void LeakProfiler::emit_events(jlong cutoff_ticks, bool emit_all) {
+void LeakProfiler::emit_events(int64_t cutoff_ticks, bool emit_all) {
   if (!is_running()) {
     return;
   }
-  EmitEventOperation op(cutoff_ticks, emit_all);
-  VMThread::execute(&op);
+  // exclusive access to object sampler instance
+  ObjectSampler* const sampler = ObjectSampler::acquire();
+  assert(sampler != NULL, "invariant");
+  EventEmitter::emit(sampler, cutoff_ticks, emit_all);
+  ObjectSampler::release();
 }
 
 void LeakProfiler::oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
   assert(SafepointSynchronize::is_at_safepoint(),
     "Leak Profiler::oops_do(...) may only be called during safepoint");
-
-  if (_object_sampler != NULL) {
-    _object_sampler->oops_do(is_alive, f);
+  if (is_running()) {
+    ObjectSampler::oops_do(is_alive, f);
   }
 }
 
-void LeakProfiler::sample(HeapWord* object,
-                          size_t size,
-                          JavaThread* thread) {
+void LeakProfiler::sample(HeapWord* object, size_t size, JavaThread* thread) {
   assert(is_running(), "invariant");
   assert(thread != NULL, "invariant");
   assert(thread->thread_state() == _thread_in_vm, "invariant");
@@ -104,39 +117,5 @@
     return;
   }
 
-  _object_sampler->add(object, size, thread);
-}
-
-ObjectSampler* LeakProfiler::object_sampler() {
-  assert(is_suspended() || SafepointSynchronize::is_at_safepoint(),
-    "Leak Profiler::object_sampler() may only be called during safepoint");
-  return _object_sampler;
-}
-
-void LeakProfiler::set_object_sampler(ObjectSampler* object_sampler) {
-  assert(SafepointSynchronize::is_at_safepoint(),
-    "Leak Profiler::set_object_sampler() may only be called during safepoint");
-  _object_sampler = object_sampler;
-}
-
-bool LeakProfiler::is_running() {
-  return _object_sampler != NULL && !suspended;
+  ObjectSampler::sample(object, size, thread);
 }
-
-bool LeakProfiler::is_suspended() {
-  return _object_sampler != NULL && suspended;
-}
-
-void LeakProfiler::resume() {
-  assert(is_suspended(), "invariant");
-  OrderAccess::storestore();
-  Atomic::store((jbyte)0, &suspended);
-  assert(is_running(), "invariant");
-}
-
-void LeakProfiler::suspend() {
-  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
-  assert(_object_sampler != NULL, "invariant");
-  assert(!is_suspended(), "invariant");
-  suspended = (jbyte)1; // safepoint visible
-}
--- a/src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/leakProfiler.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -28,36 +28,16 @@
 #include "memory/allocation.hpp"
 
 class BoolObjectClosure;
-class ObjectSampler;
 class OopClosure;
 class JavaThread;
-class Thread;
 
 class LeakProfiler : public AllStatic {
-  friend class ClassUnloadTypeSet;
-  friend class EmitEventOperation;
-  friend class ObjectSampleCheckpoint;
-  friend class StartOperation;
-  friend class StopOperation;
-  friend class TypeSet;
-  friend class WriteObjectSampleStacktrace;
-
- private:
-  static ObjectSampler* _object_sampler;
-
-  static void set_object_sampler(ObjectSampler* object_sampler);
-  static ObjectSampler* object_sampler();
-
-  static void suspend();
-  static void resume();
-  static bool is_suspended();
-
  public:
-  static bool start(jint sample_count);
+  static bool start(int sample_count);
   static bool stop();
-  static void emit_events(jlong cutoff_ticks, bool emit_all);
   static bool is_running();
 
+  static void emit_events(int64_t cutoff_ticks, bool emit_all);
   static void sample(HeapWord* object, size_t size, JavaThread* thread);
 
   // Called by GC
--- a/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, 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
@@ -21,6 +21,7 @@
  * questions.
  *
  */
+
 #include "precompiled.hpp"
 #include "jfr/jfrEvents.hpp"
 #include "jfr/leakprofiler/sampling/objectSample.hpp"
@@ -35,8 +36,18 @@
 #include "logging/log.hpp"
 #include "memory/universe.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
+#include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
 
+static ObjectSampler* _instance = NULL;
+
+static ObjectSampler& instance() {
+  assert(_instance != NULL, "invariant");
+  return *_instance;
+}
+
 ObjectSampler::ObjectSampler(size_t size) :
   _priority_queue(new SamplePriorityQueue(size)),
   _list(new SampleList(size)),
@@ -44,7 +55,6 @@
   _total_allocated(0),
   _threshold(0),
   _size(size),
-  _tryLock(0),
   _dead_samples(false) {}
 
 ObjectSampler::~ObjectSampler() {
@@ -54,32 +64,110 @@
   _list = NULL;
 }
 
-void ObjectSampler::add(HeapWord* obj, size_t allocated, JavaThread* thread) {
+bool ObjectSampler::create(size_t size) {
+  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
+  assert(_instance == NULL, "invariant");
+  _instance = new ObjectSampler(size);
+  return _instance != NULL;
+}
+
+bool ObjectSampler::is_created() {
+  return _instance != NULL;
+}
+
+ObjectSampler* ObjectSampler::sampler() {
+  assert(is_created(), "invariant");
+  return _instance;
+}
+
+void ObjectSampler::destroy() {
+  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
+  if (_instance != NULL) {
+    ObjectSampler* const sampler = _instance;
+    _instance = NULL;
+    delete sampler;
+  }
+}
+
+static volatile int _lock = 0;
+
+ObjectSampler* ObjectSampler::acquire() {
+  assert(is_created(), "invariant");
+  while (Atomic::cmpxchg(1, &_lock, 0) == 1) {}
+  return _instance;
+}
+
+void ObjectSampler::release() {
+  assert(is_created(), "invariant");
+  OrderAccess::fence();
+  _lock = 0;
+}
+
+static traceid get_thread_id(JavaThread* thread) {
   assert(thread != NULL, "invariant");
-  const traceid thread_id = thread->threadObj() != NULL ? thread->jfr_thread_local()->thread_id() : 0;
+  if (thread->threadObj() == NULL) {
+    return 0;
+  }
+  const JfrThreadLocal* const tl = thread->jfr_thread_local();
+  assert(tl != NULL, "invariant");
+  if (!tl->has_thread_checkpoint()) {
+    JfrCheckpointManager::create_thread_checkpoint(thread);
+  }
+  assert(tl->has_thread_checkpoint(), "invariant");
+  return tl->thread_id();
+}
+
+// Populates the thread local stack frames, but does not add them
+// to the stacktrace repository (...yet, see stacktrace_id() below)
+//
+void ObjectSampler::fill_stacktrace(JfrStackTrace* stacktrace, JavaThread* thread) {
+  assert(stacktrace != NULL, "invariant");
+  assert(thread != NULL, "invariant");
+  if (JfrEventSetting::has_stacktrace(EventOldObjectSample::eventId)) {
+    JfrStackTraceRepository::fill_stacktrace_for(thread, stacktrace, 0);
+  }
+}
+
+// We were successful in acquiring the try lock and have been selected for adding a sample.
+// Go ahead with installing our previously taken stacktrace into the stacktrace repository.
+//
+traceid ObjectSampler::stacktrace_id(const JfrStackTrace* stacktrace, JavaThread* thread) {
+  assert(stacktrace != NULL, "invariant");
+  assert(stacktrace->hash() != 0, "invariant");
+  const traceid stacktrace_id = JfrStackTraceRepository::add(stacktrace, thread);
+  thread->jfr_thread_local()->set_cached_stack_trace_id(stacktrace_id, stacktrace->hash());
+  return stacktrace_id;
+}
+
+void ObjectSampler::sample(HeapWord* obj, size_t allocated, JavaThread* thread) {
+  assert(thread != NULL, "invariant");
+  assert(is_created(), "invariant");
+
+  const traceid thread_id = get_thread_id(thread);
   if (thread_id == 0) {
     return;
   }
-  assert(thread_id != 0, "invariant");
-
-  if (!thread->jfr_thread_local()->has_thread_checkpoint()) {
-    JfrCheckpointManager::create_thread_checkpoint(thread);
-    assert(thread->jfr_thread_local()->has_thread_checkpoint(), "invariant");
-  }
 
-  traceid stack_trace_id = 0;
-  unsigned int stack_trace_hash = 0;
-  if (JfrEventSetting::has_stacktrace(EventOldObjectSample::eventId)) {
-    stack_trace_id = JfrStackTraceRepository::record(thread, 0, &stack_trace_hash);
-    thread->jfr_thread_local()->set_cached_stack_trace_id(stack_trace_id, stack_trace_hash);
-  }
+  const JfrThreadLocal* const tl = thread->jfr_thread_local();
+  JfrStackTrace stacktrace(tl->stackframes(), tl->stackdepth());
+  fill_stacktrace(&stacktrace, thread);
 
-  JfrTryLock tryLock(&_tryLock);
+  // try enter critical section
+  JfrTryLock tryLock(&_lock);
   if (!tryLock.has_lock()) {
     log_trace(jfr, oldobject, sampling)("Skipping old object sample due to lock contention");
     return;
   }
 
+  instance().add(obj, allocated, thread_id, &stacktrace, thread);
+}
+
+void ObjectSampler::add(HeapWord* obj, size_t allocated, traceid thread_id, JfrStackTrace* stacktrace, JavaThread* thread) {
+  assert(stacktrace != NULL, "invariant");
+  assert(thread_id != 0, "invariant");
+  assert(thread != NULL, "invariant");
+  assert(thread->jfr_thread_local()->has_thread_checkpoint(), "invariant");
+
   if (_dead_samples) {
     scavenge();
     assert(!_dead_samples, "invariant");
@@ -101,13 +189,13 @@
   }
 
   assert(sample != NULL, "invariant");
-  assert(thread_id != 0, "invariant");
   sample->set_thread_id(thread_id);
   sample->set_thread_checkpoint(thread->jfr_thread_local()->thread_checkpoint());
 
-  if (stack_trace_id != 0) {
-    sample->set_stack_trace_id(stack_trace_id);
-    sample->set_stack_trace_hash(stack_trace_hash);
+  const unsigned int stacktrace_hash = stacktrace->hash();
+  if (stacktrace_hash != 0) {
+    sample->set_stack_trace_id(stacktrace_id(stacktrace, thread));
+    sample->set_stack_trace_hash(stacktrace_hash);
   }
 
   sample->set_span(allocated);
@@ -118,6 +206,53 @@
   _priority_queue->push(sample);
 }
 
+void ObjectSampler::scavenge() {
+  ObjectSample* current = _list->last();
+  while (current != NULL) {
+    ObjectSample* next = current->next();
+    if (current->is_dead()) {
+      remove_dead(current);
+    }
+    current = next;
+  }
+  _dead_samples = false;
+}
+
+void ObjectSampler::remove_dead(ObjectSample* sample) {
+  assert(sample != NULL, "invariant");
+  assert(sample->is_dead(), "invariant");
+  ObjectSample* const previous = sample->prev();
+  // push span on to previous
+  if (previous != NULL) {
+    _priority_queue->remove(previous);
+    previous->add_span(sample->span());
+    _priority_queue->push(previous);
+  }
+  _priority_queue->remove(sample);
+  _list->release(sample);
+}
+
+void ObjectSampler::oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+  assert(is_created(), "invariant");
+  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
+  ObjectSampler& sampler = instance();
+  ObjectSample* current = sampler._list->last();
+  while (current != NULL) {
+    ObjectSample* next = current->next();
+    if (!current->is_dead()) {
+      if (is_alive->do_object_b(current->object())) {
+        // The weakly referenced object is alive, update pointer
+        f->do_oop(const_cast<oop*>(current->object_addr()));
+      } else {
+        current->set_dead();
+        sampler._dead_samples = true;
+      }
+    }
+    current = next;
+  }
+  sampler._last_sweep = JfrTicks::now();
+}
+
 const ObjectSample* ObjectSampler::last() const {
   return _list->last();
 }
@@ -134,50 +269,6 @@
   _list->set_last_resolved(sample);
 }
 
-void ObjectSampler::oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
-  ObjectSample* current = _list->last();
-  while (current != NULL) {
-    ObjectSample* next = current->next();
-    if (!current->is_dead()) {
-      if (is_alive->do_object_b(current->object())) {
-        // The weakly referenced object is alive, update pointer
-        f->do_oop(const_cast<oop*>(current->object_addr()));
-      } else {
-        current->set_dead();
-        _dead_samples = true;
-      }
-    }
-    current = next;
-  }
-  _last_sweep = JfrTicks::now();
-}
-
-void ObjectSampler::remove_dead(ObjectSample* sample) {
-  assert(sample != NULL, "invariant");
-  assert(sample->is_dead(), "invariant");
-  ObjectSample* const previous = sample->prev();
-  // push span on to previous
-  if (previous != NULL) {
-    _priority_queue->remove(previous);
-    previous->add_span(sample->span());
-    _priority_queue->push(previous);
-  }
-  _priority_queue->remove(sample);
-  _list->release(sample);
-}
-
-void ObjectSampler::scavenge() {
-  ObjectSample* current = _list->last();
-  while (current != NULL) {
-    ObjectSample* next = current->next();
-    if (current->is_dead()) {
-      remove_dead(current);
-    }
-    current = next;
-  }
-  _dead_samples = false;
-}
-
 int ObjectSampler::item_count() const {
   return _priority_queue->count();
 }
@@ -189,7 +280,7 @@
 ObjectSample* ObjectSampler::item_at(int index) {
   return const_cast<ObjectSample*>(
     const_cast<const ObjectSampler*>(this)->item_at(index)
-                                   );
+                                  );
 }
 
 const JfrTicks& ObjectSampler::last_sweep() const {
--- a/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -28,7 +28,10 @@
 #include "memory/allocation.hpp"
 #include "jfr/utilities/jfrTime.hpp"
 
+typedef u8 traceid;
+
 class BoolObjectClosure;
+class JfrStackTrace;
 class OopClosure;
 class ObjectSample;
 class ObjectSampler;
@@ -40,11 +43,13 @@
 // making sure the samples are evenly distributed as
 // new entries are added and removed.
 class ObjectSampler : public CHeapObj<mtTracing> {
+  friend class EventEmitter;
+  friend class JfrRecorderService;
   friend class LeakProfiler;
-  friend class ObjectSampleCheckpoint;
   friend class StartOperation;
   friend class StopOperation;
-  friend class EmitEventOperation;
+  friend class ObjectSampleCheckpoint;
+  friend class WriteObjectSampleStacktrace;
  private:
   SamplePriorityQueue* _priority_queue;
   SampleList* _list;
@@ -52,20 +57,33 @@
   size_t _total_allocated;
   size_t _threshold;
   size_t _size;
-  volatile int _tryLock;
   bool _dead_samples;
 
+  // Lifecycle
   explicit ObjectSampler(size_t size);
   ~ObjectSampler();
+  static bool create(size_t size);
+  static bool is_created();
+  static ObjectSampler* sampler();
+  static void destroy();
 
-  void add(HeapWord* object, size_t size, JavaThread* thread);
+  // For operations that require exclusive access (non-safepoint)
+  static ObjectSampler* acquire();
+  static void release();
+
+  // Stacktrace
+  static void fill_stacktrace(JfrStackTrace* stacktrace, JavaThread* thread);
+  traceid stacktrace_id(const JfrStackTrace* stacktrace, JavaThread* thread);
+
+  // Sampling
+  static void sample(HeapWord* object, size_t size, JavaThread* thread);
+  void add(HeapWord* object, size_t size, traceid thread_id, JfrStackTrace* stacktrace, JavaThread* thread);
+  void scavenge();
   void remove_dead(ObjectSample* sample);
-  void scavenge();
 
   // Called by GC
-  void oops_do(BoolObjectClosure* is_alive, OopClosure* f);
+  static void oops_do(BoolObjectClosure* is_alive, OopClosure* f);
 
- public:
   const ObjectSample* item_at(int index) const;
   ObjectSample* item_at(int index);
   int item_count() const;
--- a/src/hotspot/share/jfr/leakprofiler/startOperation.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/startOperation.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -25,35 +25,18 @@
 #ifndef SHARE_JFR_LEAKPROFILER_STARTOPERATION_HPP
 #define SHARE_JFR_LEAKPROFILER_STARTOPERATION_HPP
 
-#include "jfr/recorder/jfrRecorder.hpp"
-#include "jfr/leakprofiler/leakProfiler.hpp"
 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
-#include "jfr/recorder/service/jfrOptionSet.hpp"
-#include "logging/log.hpp"
-#include "runtime/vmOperations.hpp"
+#include "jfr/leakprofiler/utilities/vmOperation.hpp"
 
-// Safepoint operation for starting leak profiler object sampler
-class StartOperation : public VM_Operation {
+// Safepoint operation for creating and starting the leak profiler object sampler
+class StartOperation : public OldObjectVMOperation {
  private:
-  jlong _sample_count;
+  int _sample_count;
  public:
-  StartOperation(jlong sample_count) :
-    _sample_count(sample_count) {
-  }
-
-  Mode evaluation_mode() const {
-    return _safepoint;
-  }
-
-  VMOp_Type type() const {
-    return VMOp_GC_HeapInspection;
-  }
+  StartOperation(int sample_count) : _sample_count(sample_count) {}
 
   virtual void doit() {
-    assert(!LeakProfiler::is_running(), "invariant");
-    jint queue_size = JfrOptionSet::old_object_queue_size();
-    LeakProfiler::set_object_sampler(new ObjectSampler(queue_size));
-    log_trace(jfr, system)( "Object sampling started");
+    ObjectSampler::create(_sample_count);
   }
 };
 
--- a/src/hotspot/share/jfr/leakprofiler/stopOperation.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/leakprofiler/stopOperation.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -25,31 +25,14 @@
 #ifndef SHARE_JFR_LEAKPROFILER_STOPOPERATION_HPP
 #define SHARE_JFR_LEAKPROFILER_STOPOPERATION_HPP
 
-#include "jfr/leakprofiler/leakProfiler.hpp"
 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
-#include "jfr/recorder/service/jfrOptionSet.hpp"
-#include "logging/log.hpp"
-#include "runtime/vmOperations.hpp"
-
-// Safepoint operation for stopping leak profiler object sampler
-class StopOperation : public VM_Operation {
- public:
-  StopOperation() {}
+#include "jfr/leakprofiler/utilities/vmOperation.hpp"
 
-  Mode evaluation_mode() const {
-    return _safepoint;
-  }
-
-  VMOp_Type type() const {
-    return VMOp_GC_HeapInspection;
-  }
-
+// Safepoint operation for stopping and destroying the leak profiler object sampler
+class StopOperation : public OldObjectVMOperation {
+ public:
   virtual void doit() {
-    assert(LeakProfiler::is_running(), "invariant");
-    ObjectSampler* object_sampler = LeakProfiler::object_sampler();
-    delete object_sampler;
-    LeakProfiler::set_object_sampler(NULL);
-    log_trace(jfr, system)( "Object sampling stopped");
+    ObjectSampler::destroy();
   }
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/leakprofiler/utilities/vmOperation.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+#ifndef SHARE_JFR_LEAKPROFILER_UTILITIES_VMOPERATION_HPP
+#define SHARE_JFR_LEAKPROFILER_UTILITIES_VMOPERATION_HPP
+
+#include "runtime/vmOperations.hpp"
+
+class OldObjectVMOperation : public VM_Operation {
+ public:
+  Mode evaluation_mode() const {
+    return _safepoint;
+  }
+
+  VMOp_Type type() const {
+    return VMOp_JFROldObject;
+  }
+};
+
+#endif // SHARE_JFR_LEAKPROFILER_UTILITIES_VMOPERATION_HPP
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -311,7 +311,7 @@
   if (LeakProfiler::is_running()) {
     JfrCheckpointWriter leakp_writer(false, true, Thread::current());
     type_set.write(writer, &leakp_writer);
-    ObjectSampleCheckpoint::install(leakp_writer, true, true);
+    ObjectSampleCheckpoint::install(leakp_writer, true);
     return;
   }
   type_set.write(writer, NULL);
@@ -319,10 +319,10 @@
 
 void TypeSet::serialize(JfrCheckpointWriter& writer) {
   TypeSetSerialization type_set(false);
-  if (LeakProfiler::is_suspended()) {
+  if (LeakProfiler::is_running()) {
     JfrCheckpointWriter leakp_writer(false, true, Thread::current());
     type_set.write(writer, &leakp_writer);
-    ObjectSampleCheckpoint::install(leakp_writer, false, true);
+    ObjectSampleCheckpoint::install(leakp_writer, false);
     return;
   }
   type_set.write(writer, NULL);
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -194,9 +194,6 @@
     if (!validate_recording_options(thread)) {
       return false;
     }
-    if (!JfrJavaEventWriter::initialize()) {
-      return false;
-    }
     if (!JfrOptionSet::configure(thread)) {
       return false;
     }
@@ -246,6 +243,9 @@
   ResourceMark rm;
   HandleMark hm;
 
+  if (!create_java_event_writer()) {
+    return false;
+  }
   if (!create_jvmti_agent()) {
     return false;
   }
@@ -287,6 +287,10 @@
 static JfrOSInterface* _os_interface = NULL;
 static JfrThreadSampling* _thread_sampling = NULL;
 
+bool JfrRecorder::create_java_event_writer() {
+  return JfrJavaEventWriter::initialize();
+}
+
 bool JfrRecorder::create_jvmti_agent() {
   return JfrOptionSet::allow_retransforms() ? JfrJvmtiAgent::create() : true;
 }
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -40,6 +40,7 @@
  private:
   static bool create_checkpoint_manager();
   static bool create_chunk_repository();
+  static bool create_java_event_writer();
   static bool create_jvmti_agent();
   static bool create_os_interface();
   static bool create_post_box();
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -24,7 +24,9 @@
 
 #include "precompiled.hpp"
 #include "jfr/jni/jfrJavaSupport.hpp"
+#include "jfr/leakprofiler/leakProfiler.hpp"
 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
+#include "jfr/leakprofiler/sampling/objectSampler.hpp"
 #include "jfr/recorder/jfrRecorder.hpp"
 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
@@ -335,6 +337,7 @@
     open_new_chunk(true);
   }
   _checkpoint_manager.register_service_thread(Thread::current());
+  JfrMetadataEvent::lock();
 }
 
 void JfrRecorderService::open_new_chunk(bool vm_error) {
@@ -398,6 +401,11 @@
   write_stack_trace_checkpoint.process();
 }
 
+static void write_object_sample_stacktrace(ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repository) {
+  WriteObjectSampleStacktrace object_sample_stacktrace(sampler, stack_trace_repository);
+  object_sample_stacktrace.process();
+}
+
 static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
   WriteStringPool write_string_pool(string_pool);
   WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool);
@@ -418,8 +426,9 @@
 //      write checkpoint epoch transition list->
 //        write stack trace checkpoint ->
 //          write string pool checkpoint ->
-//            write storage ->
-//              release stream lock
+//            write object sample stacktraces ->
+//              write storage ->
+//                release stream lock
 //
 void JfrRecorderService::pre_safepoint_write() {
   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
@@ -428,6 +437,13 @@
   _checkpoint_manager.write_epoch_transition_mspace();
   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false);
   write_stringpool_checkpoint(_string_pool, _chunkwriter);
+  if (LeakProfiler::is_running()) {
+    // Exclusive access to the object sampler instance.
+    // The sampler is released (unlocked) later in post_safepoint_write.
+    ObjectSampler* const sampler = ObjectSampler::acquire();
+    assert(sampler != NULL, "invariant");
+    write_object_sample_stacktrace(sampler, _stack_trace_repository);
+  }
   _storage.write();
 }
 
@@ -436,16 +452,10 @@
   VMThread::execute(&safepoint_task);
 }
 
-static void write_object_sample_stacktrace(JfrStackTraceRepository& stack_trace_repository) {
-  WriteObjectSampleStacktrace object_sample_stacktrace(stack_trace_repository);
-  object_sample_stacktrace.process();
-}
-
 //
 // safepoint write sequence
 //
 //   lock stream lock ->
-//     write object sample stacktraces ->
 //       write stacktrace repository ->
 //         write string pool ->
 //           write safepoint dependent types ->
@@ -458,7 +468,6 @@
 void JfrRecorderService::safepoint_write() {
   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
-  write_object_sample_stacktrace(_stack_trace_repository);
   write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
   write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
   _checkpoint_manager.write_safepoint_types();
@@ -478,13 +487,14 @@
 //
 // post-safepoint write sequence
 //
-//  lock stream lock ->
-//    write type set ->
-//      write checkpoints ->
-//        write metadata event ->
-//          write chunk header ->
-//            close chunk fd ->
-//              release stream lock
+//   write type set ->
+//     release object sampler ->
+//       lock stream lock ->
+//         write checkpoints ->
+//           write metadata event ->
+//             write chunk header ->
+//               close chunk fd ->
+//                 release stream lock
 //
 void JfrRecorderService::post_safepoint_write() {
   assert(_chunkwriter.is_valid(), "invariant");
@@ -493,6 +503,11 @@
   // already tagged artifacts for the previous epoch. We can accomplish this concurrently
   // with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
   _checkpoint_manager.write_type_set();
+  if (LeakProfiler::is_running()) {
+    // The object sampler instance was exclusively acquired and locked in pre_safepoint_write.
+    // Note: There is a dependency on write_type_set() above, ensure the release is subsequent.
+    ObjectSampler::release();
+  }
   MutexLocker stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   // serialize any outstanding checkpoint memory
   _checkpoint_manager.write();
@@ -512,11 +527,9 @@
 void JfrRecorderService::finalize_current_chunk_on_vm_error() {
   assert(_chunkwriter.is_valid(), "invariant");
   pre_safepoint_write();
-  JfrMetadataEvent::lock();
   // Do not attempt safepoint dependent operations during emergency dump.
   // Optimistically write tagged artifacts.
   _checkpoint_manager.shift_epoch();
-  _checkpoint_manager.write_type_set();
   // update time
   _chunkwriter.time_stamp_chunk_now();
   post_safepoint_write();
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -164,7 +164,13 @@
 }
 
 traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) {
-  return instance().add_trace(stacktrace);
+  traceid tid = instance().add_trace(stacktrace);
+  if (tid == 0) {
+    stacktrace.resolve_linenos();
+    tid = instance().add_trace(stacktrace);
+  }
+  assert(tid != 0, "invariant");
+  return tid;
 }
 
 traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) {
@@ -187,54 +193,29 @@
   return instance().record_for((JavaThread*)thread, skip,frames, tl->stackdepth());
 }
 
-traceid JfrStackTraceRepository::record(Thread* thread, int skip, unsigned int* hash) {
-  assert(thread == Thread::current(), "invariant");
-  JfrThreadLocal* const tl = thread->jfr_thread_local();
-  assert(tl != NULL, "invariant");
-
-  if (tl->has_cached_stack_trace()) {
-    *hash = tl->cached_stack_trace_hash();
-    return tl->cached_stack_trace_id();
-  }
-  if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
-    return 0;
-  }
-  JfrStackFrame* frames = tl->stackframes();
-  if (frames == NULL) {
-    // pending oom
-    return 0;
-  }
-  assert(frames != NULL, "invariant");
-  assert(tl->stackframes() == frames, "invariant");
-  return instance().record_for((JavaThread*)thread, skip, frames, tl->stackdepth(), hash);
-}
-
 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) {
   JfrStackTrace stacktrace(frames, max_frames);
-  if (!stacktrace.record_safe(thread, skip)) {
-    return 0;
-  }
-  traceid tid = add(stacktrace);
-  if (tid == 0) {
-    stacktrace.resolve_linenos();
-    tid = add(stacktrace);
-  }
-  return tid;
+  return stacktrace.record_safe(thread, skip) ? add(stacktrace) : 0;
+}
+
+traceid JfrStackTraceRepository::add(const JfrStackTrace* stacktrace, JavaThread* thread) {
+  assert(stacktrace != NULL, "invariant");
+  assert(thread != NULL, "invariant");
+  assert(stacktrace->hash() != 0, "invariant");
+  return add(*stacktrace);
 }
 
-traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames, unsigned int* hash) {
-  assert(hash != NULL && *hash == 0, "invariant");
-  JfrStackTrace stacktrace(frames, max_frames);
-  if (!stacktrace.record_safe(thread, skip, true)) {
-    return 0;
+bool JfrStackTraceRepository::fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip) {
+  assert(thread == Thread::current(), "invariant");
+  assert(stacktrace != NULL, "invariant");
+  JfrThreadLocal* const tl = thread->jfr_thread_local();
+  assert(tl != NULL, "invariant");
+  const unsigned int cached_stacktrace_hash = tl->cached_stack_trace_hash();
+  if (cached_stacktrace_hash != 0) {
+    stacktrace->set_hash(cached_stacktrace_hash);
+    return true;
   }
-  traceid tid = add(stacktrace);
-  if (tid == 0) {
-    stacktrace.resolve_linenos();
-    tid = add(stacktrace);
-  }
-  *hash = stacktrace._hash;
-  return tid;
+  return stacktrace->record_safe(thread, skip, true);
 }
 
 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
@@ -363,7 +344,7 @@
   return trace;
 }
 
-void JfrStackFrame::resolve_lineno() {
+void JfrStackFrame::resolve_lineno() const {
   assert(_method, "no method pointer");
   assert(_line == 0, "already have linenumber");
   _line = _method->line_number_from_bci(_bci);
@@ -375,7 +356,7 @@
   _frames[frame_pos] = frame;
 }
 
-void JfrStackTrace::resolve_linenos() {
+void JfrStackTrace::resolve_linenos() const {
   for(unsigned int i = 0; i < _nr_of_frames; i++) {
     _frames[i].resolve_lineno();
   }
--- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -36,9 +36,9 @@
 
 class JfrStackFrame {
  private:
-  const Method* _method;
+  mutable const Method* _method;
   traceid _methodid;
-  int _line;
+  mutable int _line;
   int _bci;
   u1 _type;
 
@@ -58,7 +58,7 @@
   bool equals(const JfrStackFrame& rhs) const;
   void write(JfrChunkWriter& cw) const;
   void write(JfrCheckpointWriter& cpw) const;
-  void resolve_lineno();
+  void resolve_lineno() const;
 };
 
 class JfrStackTrace : public StackObj {
@@ -70,7 +70,7 @@
   unsigned int _hash;
   const u4 _max_frames;
   bool _reached_root;
-  bool _lineno;
+  mutable bool _lineno;
 
  public:
   JfrStackTrace(JfrStackFrame* frames, u4 max_frames) : _frames(frames),
@@ -82,9 +82,10 @@
                                                         _lineno(false) {}
   bool record_thread(JavaThread& thread, frame& frame);
   bool record_safe(JavaThread* thread, int skip, bool leakp = false);
-  void resolve_linenos();
+  void resolve_linenos() const;
   void set_nr_of_frames(u4 nr_of_frames) { _nr_of_frames = nr_of_frames; }
   void set_hash(unsigned int hash) { _hash = hash; }
+  unsigned int hash() const { return _hash; }
   void set_frame(u4 frame_pos, JfrStackFrame& frame);
   void set_reached_root(bool reached_root) { _reached_root = reached_root; }
   bool full_stacktrace() const { return _reached_root; }
@@ -128,23 +129,26 @@
   traceid _next_id;
   u4 _entries;
 
-  size_t write_impl(JfrChunkWriter& cw, bool clear);
+  traceid add_trace(const JfrStackTrace& stacktrace);
+  static traceid add(const JfrStackTrace* stacktrace, JavaThread* thread);
   traceid record_for(JavaThread* thread, int skip, JfrStackFrame* frames, u4 max_frames);
-  traceid record_for(JavaThread* thread, int skip, JfrStackFrame* frames, u4 max_frames, unsigned int* hash);
-  traceid add_trace(const JfrStackTrace& stacktrace);
+
+  size_t write_impl(JfrChunkWriter& cw, bool clear);
   const StackTrace* resolve_entry(unsigned int hash, traceid id) const;
-
   static void write_metadata(JfrCheckpointWriter& cpw);
 
+  static bool fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip);
+
   JfrStackTraceRepository();
-  static JfrStackTraceRepository& instance();
- public:
   static JfrStackTraceRepository* create();
   bool initialize();
   static void destroy();
+
+  static JfrStackTraceRepository& instance();
+
+ public:
   static traceid add(const JfrStackTrace& stacktrace);
   static traceid record(Thread* thread, int skip = 0);
-  static traceid record(Thread* thread, int skip, unsigned int* hash);
   traceid write(JfrCheckpointWriter& cpw, traceid id, unsigned int hash);
   size_t write(JfrChunkWriter& cw, bool clear);
   size_t clear();
--- a/src/hotspot/share/jfr/support/jfrFlush.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/support/jfrFlush.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -48,10 +48,12 @@
 
 template <typename Event>
 class JfrConditionalFlush {
+ protected:
+  bool _enabled;
  public:
   typedef JfrBuffer Type;
-  JfrConditionalFlush(Thread* t) {
-    if (jfr_is_event_enabled(Event::eventId)) {
+  JfrConditionalFlush(Thread* t) : _enabled(jfr_is_event_enabled(Event::eventId)) {
+    if (_enabled) {
       jfr_conditional_flush(Event::eventId, sizeof(Event), t);
     }
   }
@@ -63,7 +65,7 @@
   bool _owner;
  public:
   JfrConditionalFlushWithStacktrace(Thread* t) : JfrConditionalFlush<Event>(t), _t(t), _owner(false) {
-    if (Event::has_stacktrace() && jfr_has_stacktrace_enabled(Event::eventId)) {
+    if (this->_enabled && Event::has_stacktrace() && jfr_has_stacktrace_enabled(Event::eventId)) {
       _owner = jfr_save_stacktrace(t);
     }
   }
--- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -150,9 +150,7 @@
 
 JfrStackFrame* JfrThreadLocal::install_stackframes() const {
   assert(_stackframes == NULL, "invariant");
-  _stackdepth = (u4)JfrOptionSet::stackdepth();
-  guarantee(_stackdepth > 0, "Stackdepth must be > 0");
-  _stackframes = NEW_C_HEAP_ARRAY(JfrStackFrame, _stackdepth, mtTracing);
+  _stackframes = NEW_C_HEAP_ARRAY(JfrStackFrame, stackdepth(), mtTracing);
   return _stackframes;
 }
 
@@ -163,3 +161,7 @@
 ByteSize JfrThreadLocal::java_event_writer_offset() {
   return in_ByteSize(offset_of(JfrThreadLocal, _java_event_writer));
 }
+
+u4 JfrThreadLocal::stackdepth() const {
+  return _stackdepth != 0 ? _stackdepth : (u4)JfrOptionSet::stackdepth();
+}
--- a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -113,9 +113,7 @@
     _stackframes = frames;
   }
 
-  u4 stackdepth() const {
-    return _stackdepth;
-  }
+  u4 stackdepth() const;
 
   void set_stackdepth(u4 depth) {
     _stackdepth = depth;
--- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -135,8 +135,7 @@
 bool JfrJavaEventWriter::initialize() {
   static bool initialized = false;
   if (!initialized) {
-    Thread* thread = Thread::current();
-    initialized = setup_event_writer_offsets(thread);
+    initialized = setup_event_writer_offsets(Thread::current());
   }
   return initialized;
 }
@@ -155,6 +154,7 @@
   // large enough to accommodate the "requested size".
   const bool is_valid = buffer->free_size() >= (size_t)(used + requested);
   u1* const new_current_position = is_valid ? buffer->pos() + used : buffer->pos();
+  assert(start_pos_offset != invalid_offset, "invariant");
   w->long_field_put(start_pos_offset, (jlong)buffer->pos());
   w->long_field_put(current_pos_offset, (jlong)new_current_position);
   // only update java writer if underlying memory changed
--- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -33,13 +33,14 @@
 
 class JfrJavaEventWriter : AllStatic {
   friend class JfrCheckpointThreadClosure;
+  friend class JfrJavaEventWriterNotificationClosure;
   friend class JfrJavaEventWriterNotifyOperation;
-  friend class JfrJavaEventWriterNotificationClosure;
+  friend class JfrRecorder;
  private:
+  static bool initialize();
   static void notify(JavaThread* jt);
 
  public:
-  static bool initialize();
   static void notify();
   static jobject event_writer(Thread* t);
   static jobject new_event_writer(TRAPS);
--- a/src/hotspot/share/memory/filemap.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/memory/filemap.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -75,7 +75,7 @@
 // an archive file should stop the process.  Unrecoverable errors during
 // the reading of the archive file should stop the process.
 
-static void fail(const char *msg, va_list ap) {
+static void fail_exit(const char *msg, va_list ap) {
   // This occurs very early during initialization: tty is not initialized.
   jio_fprintf(defaultStream::error_stream(),
               "An error has occurred while processing the"
@@ -90,7 +90,7 @@
 void FileMapInfo::fail_stop(const char *msg, ...) {
         va_list ap;
   va_start(ap, msg);
-  fail(msg, ap);        // Never returns.
+  fail_exit(msg, ap);   // Never returns.
   va_end(ap);           // for completeness.
 }
 
@@ -118,7 +118,7 @@
     tty->print_cr("]");
   } else {
     if (RequireSharedSpaces) {
-      fail(msg, ap);
+      fail_exit(msg, ap);
     } else {
       if (log_is_enabled(Info, cds)) {
         ResourceMark rm;
@@ -252,13 +252,15 @@
   _base_archive_is_default = false;
 }
 
-void SharedClassPathEntry::init(const char* name, bool is_modules_image, TRAPS) {
+void SharedClassPathEntry::init(bool is_modules_image,
+                                ClassPathEntry* cpe, TRAPS) {
   assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
   _timestamp = 0;
   _filesize  = 0;
+  _from_class_path_attr = false;
 
   struct stat st;
-  if (os::stat(name, &st) == 0) {
+  if (os::stat(cpe->name(), &st) == 0) {
     if ((st.st_mode & S_IFMT) == S_IFDIR) {
       _type = dir_entry;
     } else {
@@ -268,6 +270,7 @@
       } else {
         _type = jar_entry;
         _timestamp = st.st_mtime;
+        _from_class_path_attr = cpe->from_class_path_attr();
       }
       _filesize = st.st_size;
     }
@@ -277,12 +280,12 @@
     //
     // If we can't access a jar file in the boot path, then we can't
     // make assumptions about where classes get loaded from.
-    FileMapInfo::fail_stop("Unable to open file %s.", name);
+    FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
   }
 
-  size_t len = strlen(name) + 1;
+  size_t len = strlen(cpe->name()) + 1;
   _name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD);
-  strcpy(_name->data(), name);
+  strcpy(_name->data(), cpe->name());
 }
 
 bool SharedClassPathEntry::validate(bool is_class_path) {
@@ -381,7 +384,7 @@
     const char* type = (is_jrt ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
     log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(cpe->name(), is_jrt, THREAD);
+    ent->init(is_jrt, cpe, THREAD);
     if (!is_jrt) {    // No need to do the modules image.
       EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
       update_shared_classpath(cpe, ent, THREAD);
@@ -397,7 +400,7 @@
   while (acpe != NULL) {
     log_info(class, path)("add app shared path %s", acpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(acpe->name(), false, THREAD);
+    ent->init(false, acpe, THREAD);
     EXCEPTION_MARK;
     update_shared_classpath(acpe, ent, THREAD);
     acpe = acpe->next();
@@ -409,7 +412,7 @@
   while (mpe != NULL) {
     log_info(class, path)("add module path %s",mpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(mpe->name(), false, THREAD);
+    ent->init(false, mpe, THREAD);
     EXCEPTION_MARK;
     update_shared_classpath(mpe, ent, THREAD);
     mpe = mpe->next();
@@ -520,6 +523,182 @@
   }
 }
 
+char* FileMapInfo::skip_first_path_entry(const char* path) {
+  size_t path_sep_len = strlen(os::path_separator());
+  char* p = strstr((char*)path, os::path_separator());
+  if (p != NULL) {
+    debug_only( {
+      size_t image_name_len = strlen(MODULES_IMAGE_NAME);
+      assert(strncmp(p - image_name_len, MODULES_IMAGE_NAME, image_name_len) == 0,
+             "first entry must be the modules image");
+    } );
+    p += path_sep_len;
+  } else {
+    debug_only( {
+      assert(ClassLoader::string_ends_with(path, MODULES_IMAGE_NAME),
+             "first entry must be the modules image");
+    } );
+  }
+  return p;
+}
+
+int FileMapInfo::num_paths(const char* path) {
+  if (path == NULL) {
+    return 0;
+  }
+  int npaths = 1;
+  char* p = (char*)path;
+  while (p != NULL) {
+    char* prev = p;
+    p = strstr((char*)p, os::path_separator());
+    if (p != NULL) {
+      p++;
+      // don't count empty path
+      if ((p - prev) > 1) {
+       npaths++;
+      }
+    }
+  }
+  return npaths;
+}
+
+GrowableArray<char*>* FileMapInfo::create_path_array(const char* path) {
+  GrowableArray<char*>* path_array =  new(ResourceObj::RESOURCE_AREA, mtInternal)
+      GrowableArray<char*>(10);
+  char* begin_ptr = (char*)path;
+  char* end_ptr = strchr((char*)path, os::path_separator()[0]);
+  if (end_ptr == NULL) {
+    end_ptr = strchr((char*)path, '\0');
+  }
+  while (end_ptr != NULL) {
+    if ((end_ptr - begin_ptr) > 1) {
+      struct stat st;
+      char* temp_name = NEW_RESOURCE_ARRAY(char, (size_t)(end_ptr - begin_ptr + 1));
+      strncpy(temp_name, begin_ptr, end_ptr - begin_ptr);
+      temp_name[end_ptr - begin_ptr] = '\0';
+      if (os::stat(temp_name, &st) == 0) {
+        path_array->append(temp_name);
+      }
+    }
+    if (end_ptr < (path + strlen(path))) {
+      begin_ptr = ++end_ptr;
+      end_ptr = strchr(begin_ptr, os::path_separator()[0]);
+      if (end_ptr == NULL) {
+        end_ptr = strchr(begin_ptr, '\0');
+      }
+    } else {
+      break;
+    }
+  }
+  return path_array;
+}
+
+bool FileMapInfo::fail(const char* msg, const char* name) {
+  ClassLoader::trace_class_path(msg, name);
+  MetaspaceShared::set_archive_loading_failed();
+  return false;
+}
+
+bool FileMapInfo::check_paths(int shared_path_start_idx, int num_paths, GrowableArray<char*>* rp_array) {
+  int i = 0;
+  int j = shared_path_start_idx;
+  bool mismatch = false;
+  while (i < num_paths && !mismatch) {
+    while (shared_path(j)->from_class_path_attr()) {
+      // shared_path(j) was expanded from the JAR file attribute "Class-Path:"
+      // during dump time. It's not included in the -classpath VM argument.
+      j++;
+    }
+    if (!os::same_files(shared_path(j)->name(), rp_array->at(i))) {
+      mismatch = true;
+    }
+    i++;
+    j++;
+  }
+  return mismatch;
+}
+
+bool FileMapInfo::validate_boot_class_paths() {
+  //
+  // - Archive contains boot classes only - relaxed boot path check:
+  //   Extra path elements appended to the boot path at runtime are allowed.
+  //
+  // - Archive contains application or platform classes - strict boot path check:
+  //   Validate the entire runtime boot path, which must be compatible
+  //   with the dump time boot path. Appending boot path at runtime is not
+  //   allowed.
+  //
+
+  // The first entry in boot path is the modules_image (guaranteed by
+  // ClassLoader::setup_boot_search_path()). Skip the first entry. The
+  // path of the runtime modules_image may be different from the dump
+  // time path (e.g. the JDK image is copied to a different location
+  // after generating the shared archive), which is acceptable. For most
+  // common cases, the dump time boot path might contain modules_image only.
+  char* runtime_boot_path = Arguments::get_sysclasspath();
+  char* rp = skip_first_path_entry(runtime_boot_path);
+  assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
+  int dp_len = _header->_app_class_paths_start_index - 1; // ignore the first path to the module image
+  bool mismatch = false;
+
+  bool relaxed_check = !header()->has_platform_or_app_classes();
+  if (dp_len == 0 && rp == NULL) {
+    return true;   // ok, both runtime and dump time boot paths have modules_images only
+  } else if (dp_len == 0 && rp != NULL) {
+    if (relaxed_check) {
+      return true;   // ok, relaxed check, runtime has extra boot append path entries
+    } else {
+      mismatch = true;
+    }
+  } else if (dp_len > 0 && rp != NULL) {
+    int num;
+    ResourceMark rm;
+    GrowableArray<char*>* rp_array = create_path_array(rp);
+    int rp_len = rp_array->length();
+    if (rp_len >= dp_len) {
+      if (relaxed_check) {
+        // only check the leading entries in the runtime boot path, up to
+        // the length of the dump time boot path
+        num = dp_len;
+      } else {
+        // check the full runtime boot path, must match with dump time
+        num = rp_len;
+      }
+      mismatch = check_paths(1, num, rp_array);
+    }
+  }
+
+  if (mismatch) {
+    // The paths are different
+    return fail("[BOOT classpath mismatch, actual =", runtime_boot_path);
+  }
+  return true;
+}
+
+bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
+  const char *appcp = Arguments::get_appclasspath();
+  assert(appcp != NULL, "NULL app classpath");
+  int rp_len = num_paths(appcp);
+  bool mismatch = false;
+  if (rp_len < shared_app_paths_len) {
+    return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
+  }
+  if (shared_app_paths_len != 0 && rp_len != 0) {
+    // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
+    ResourceMark rm;
+    GrowableArray<char*>* rp_array = create_path_array(appcp);
+    if (rp_array->length() == 0) {
+      // None of the jar file specified in the runtime -cp exists.
+      return fail("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
+    }
+    int j = _header->_app_class_paths_start_index;
+    mismatch = check_paths(j, shared_app_paths_len, rp_array);
+    if (mismatch) {
+      return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
+    }
+  }
+  return true;
+}
 
 bool FileMapInfo::validate_shared_path_table() {
   assert(UseSharedSpaces, "runtime only");
@@ -550,11 +729,16 @@
   }
 
   int module_paths_start_index = _header->_app_module_paths_start_index;
+  int shared_app_paths_len = 0;
 
   // validate the path entries up to the _max_used_path_index
   for (int i=0; i < _header->_max_used_path_index + 1; i++) {
     if (i < module_paths_start_index) {
       if (shared_path(i)->validate()) {
+        // Only count the app class paths not from the "Class-path" attribute of a jar manifest.
+        if (!shared_path(i)->from_class_path_attr() && i >= _header->_app_class_paths_start_index) {
+          shared_app_paths_len++;
+        }
         log_info(class, path)("ok");
       } else {
         if (_dynamic_archive_info != NULL && _dynamic_archive_info->_is_static) {
@@ -574,6 +758,16 @@
     }
   }
 
+  if (_header->_max_used_path_index == 0) {
+    // default archive only contains the module image in the bootclasspath
+    assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
+  } else {
+    if (!validate_boot_class_paths() || !validate_app_class_paths(shared_app_paths_len)) {
+      fail_continue("shared class paths mismatch (hint: enable -Xlog:class+path=info to diagnose the failure)");
+      return false;
+    }
+  }
+
   _validating_shared_path_table = false;
 
 #if INCLUDE_JVMTI
@@ -588,39 +782,6 @@
   return true;
 }
 
-bool FileMapInfo::same_files(const char* file1, const char* file2) {
-  if (strcmp(file1, file2) == 0) {
-    return true;
-  }
-
-  bool is_same = false;
-  // if the two paths diff only in case
-  struct stat st1;
-  struct stat st2;
-  int ret1;
-  int ret2;
-  ret1 = os::stat(file1, &st1);
-  ret2 = os::stat(file2, &st2);
-  if (ret1 < 0 || ret2 < 0) {
-    // one of the files is invalid. So they are not the same.
-    is_same = false;
-  } else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
-    // different files
-    is_same = false;
-#ifndef _WINDOWS
-  } else if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
-    // same files
-    is_same = true;
-#else
-  } else if ((st1.st_size == st2.st_size) && (st1.st_ctime == st2.st_ctime) &&
-             (st1.st_mtime == st2.st_mtime)) {
-    // same files
-    is_same = true;
-#endif
-  }
-  return is_same;
-}
-
 bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
   int fd = os::open(archive_name, O_RDONLY | O_BINARY, 0);
   if (fd < 0) {
@@ -1749,7 +1910,7 @@
         jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
         THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL);
       } else {
-        ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, CHECK_NULL);
+        ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, false, CHECK_NULL);
       }
     }
 
--- a/src/hotspot/share/memory/filemap.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/memory/filemap.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -53,13 +53,14 @@
   };
 protected:
   u1     _type;
+  bool   _from_class_path_attr;
   time_t _timestamp;          // jar timestamp,  0 if is directory, modules image or other
   long   _filesize;           // jar/jimage file size, -1 if is directory, -2 if other
   Array<char>* _name;
   Array<u1>*   _manifest;
 
 public:
-  void init(const char* name, bool is_modules_image, TRAPS);
+  void init(bool is_modules_image, ClassPathEntry* cpe, TRAPS);
   void metaspace_pointers_do(MetaspaceClosure* it);
   bool validate(bool is_class_path = true);
 
@@ -74,6 +75,7 @@
   void set_is_signed()     {
     _type = signed_jar_entry;
   }
+  bool from_class_path_attr() { return _from_class_path_attr; }
   time_t timestamp() const { return _timestamp; }
   long   filesize()  const { return _filesize; }
   const char* name() const { return _name->data(); }
@@ -240,7 +242,6 @@
   static bool get_base_archive_name_from_header(const char* archive_name,
                                                 int* size, char** base_archive_name);
   static bool check_archive(const char* archive_name, bool is_static);
-  static bool  same_files(const char* file1, const char* file2);
   void restore_shared_path_table();
   bool  init_from_file(int fd, bool is_static);
   static void metaspace_pointers_do(MetaspaceClosure* it);
@@ -376,6 +377,15 @@
   char* region_addr(int idx);
 
  private:
+  char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL);
+  int   num_paths(const char* path) NOT_CDS_RETURN_(0);
+  GrowableArray<char*>* create_path_array(const char* path) NOT_CDS_RETURN_(NULL);
+  bool  fail(const char* msg, const char* name) NOT_CDS_RETURN_(false);
+  bool  check_paths(int shared_path_start_idx,
+                    int num_paths,
+                    GrowableArray<char*>* rp_array) NOT_CDS_RETURN_(false);
+  bool  validate_boot_class_paths() NOT_CDS_RETURN_(false);
+  bool  validate_app_class_paths(int shared_app_paths_len) NOT_CDS_RETURN_(false);
   bool  map_heap_data(MemRegion **heap_mem, int first, int max, int* num,
                       bool is_open = false) NOT_CDS_JAVA_HEAP_RETURN_(false);
   bool  region_crc_check(char* buf, size_t size, int expected_crc) NOT_CDS_RETURN_(false);
--- a/src/hotspot/share/memory/iterator.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/memory/iterator.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -144,18 +144,28 @@
   void do_cld(ClassLoaderData* cld);
 };
 
-// The base class for all concurrent marking closures,
-// that participates in class unloading.
-// It's used to proxy through the metadata to the oops defined in them.
-class MetadataVisitingOopIterateClosure: public OopIterateClosure {
+class ClaimMetadataVisitingOopIterateClosure : public OopIterateClosure {
+ protected:
+  const int _claim;
+
  public:
-  MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd = NULL) : OopIterateClosure(rd) { }
+  ClaimMetadataVisitingOopIterateClosure(int claim, ReferenceDiscoverer* rd = NULL) :
+      OopIterateClosure(rd),
+      _claim(claim) { }
 
   virtual bool do_metadata() { return true; }
   virtual void do_klass(Klass* k);
   virtual void do_cld(ClassLoaderData* cld);
 };
 
+// The base class for all concurrent marking closures,
+// that participates in class unloading.
+// It's used to proxy through the metadata to the oops defined in them.
+class MetadataVisitingOopIterateClosure: public ClaimMetadataVisitingOopIterateClosure {
+ public:
+  MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd = NULL);
+};
+
 // ObjectClosure is used for iterating through an object space
 
 class ObjectClosure : public Closure {
--- a/src/hotspot/share/memory/iterator.inline.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/memory/iterator.inline.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -39,13 +39,17 @@
 #include "oops/typeArrayKlass.inline.hpp"
 #include "utilities/debug.hpp"
 
-inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
-  cld->oops_do(this, ClassLoaderData::_claim_strong);
+// Defaults to strong claiming.
+inline MetadataVisitingOopIterateClosure::MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd) :
+    ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_strong, rd) {}
+
+inline void ClaimMetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
+  cld->oops_do(this, _claim);
 }
 
-inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) {
+inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) {
   ClassLoaderData* cld = k->class_loader_data();
-  MetadataVisitingOopIterateClosure::do_cld(cld);
+  ClaimMetadataVisitingOopIterateClosure::do_cld(cld);
 }
 
 #ifdef ASSERT
--- a/src/hotspot/share/memory/metaspace.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/memory/metaspace.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -471,9 +471,36 @@
   return cm->chunk_free_list_summary();
 }
 
-void MetaspaceUtils::print_metaspace_change(size_t prev_metadata_used) {
-  log_info(gc, metaspace)("Metaspace: "  SIZE_FORMAT "K->" SIZE_FORMAT "K("  SIZE_FORMAT "K)",
-                          prev_metadata_used/K, used_bytes()/K, reserved_bytes()/K);
+void MetaspaceUtils::print_metaspace_change(const metaspace::MetaspaceSizesSnapshot& pre_meta_values) {
+  const metaspace::MetaspaceSizesSnapshot meta_values;
+
+  if (Metaspace::using_class_space()) {
+    log_info(gc, metaspace)(HEAP_CHANGE_FORMAT" "
+                            HEAP_CHANGE_FORMAT" "
+                            HEAP_CHANGE_FORMAT,
+                            HEAP_CHANGE_FORMAT_ARGS("Metaspace",
+                                                    pre_meta_values.used(),
+                                                    pre_meta_values.committed(),
+                                                    meta_values.used(),
+                                                    meta_values.committed()),
+                            HEAP_CHANGE_FORMAT_ARGS("NonClass",
+                                                    pre_meta_values.non_class_used(),
+                                                    pre_meta_values.non_class_committed(),
+                                                    meta_values.non_class_used(),
+                                                    meta_values.non_class_committed()),
+                            HEAP_CHANGE_FORMAT_ARGS("Class",
+                                                    pre_meta_values.class_used(),
+                                                    pre_meta_values.class_committed(),
+                                                    meta_values.class_used(),
+                                                    meta_values.class_committed()));
+  } else {
+    log_info(gc, metaspace)(HEAP_CHANGE_FORMAT,
+                            HEAP_CHANGE_FORMAT_ARGS("Metaspace",
+                                                    pre_meta_values.used(),
+                                                    pre_meta_values.committed(),
+                                                    meta_values.used(),
+                                                    meta_values.committed()));
+  }
 }
 
 void MetaspaceUtils::print_on(outputStream* out) {
@@ -557,6 +584,11 @@
 // unlike print_report() is guaranteed not to lock or to walk the CLDG.
 void MetaspaceUtils::print_basic_report(outputStream* out, size_t scale) {
 
+  if (!Metaspace::initialized()) {
+    out->print_cr("Metaspace not yet initialized.");
+    return;
+  }
+
   out->cr();
   out->print_cr("Usage:");
 
@@ -645,6 +677,11 @@
 
 void MetaspaceUtils::print_report(outputStream* out, size_t scale, int flags) {
 
+  if (!Metaspace::initialized()) {
+    out->print_cr("Metaspace not yet initialized.");
+    return;
+  }
+
   const bool print_loaders = (flags & rf_show_loaders) > 0;
   const bool print_classes = (flags & rf_show_classes) > 0;
   const bool print_by_chunktype = (flags & rf_break_down_by_chunktype) > 0;
@@ -932,6 +969,8 @@
 ChunkManager* Metaspace::_chunk_manager_metadata = NULL;
 ChunkManager* Metaspace::_chunk_manager_class = NULL;
 
+bool Metaspace::_initialized = false;
+
 #define VIRTUALSPACEMULTIPLIER 2
 
 #ifdef _LP64
@@ -1258,6 +1297,9 @@
   }
 
   _tracer = new MetaspaceTracer();
+
+  _initialized = true;
+
 }
 
 void Metaspace::post_initialize() {
@@ -1588,71 +1630,6 @@
 
 /////////////// Unit tests ///////////////
 
-#ifndef PRODUCT
-
-class TestMetaspaceUtilsTest : AllStatic {
- public:
-  static void test_reserved() {
-    size_t reserved = MetaspaceUtils::reserved_bytes();
-
-    assert(reserved > 0, "assert");
-
-    size_t committed  = MetaspaceUtils::committed_bytes();
-    assert(committed <= reserved, "assert");
-
-    size_t reserved_metadata = MetaspaceUtils::reserved_bytes(Metaspace::NonClassType);
-    assert(reserved_metadata > 0, "assert");
-    assert(reserved_metadata <= reserved, "assert");
-
-    if (UseCompressedClassPointers) {
-      size_t reserved_class    = MetaspaceUtils::reserved_bytes(Metaspace::ClassType);
-      assert(reserved_class > 0, "assert");
-      assert(reserved_class < reserved, "assert");
-    }
-  }
-
-  static void test_committed() {
-    size_t committed = MetaspaceUtils::committed_bytes();
-
-    assert(committed > 0, "assert");
-
-    size_t reserved  = MetaspaceUtils::reserved_bytes();
-    assert(committed <= reserved, "assert");
-
-    size_t committed_metadata = MetaspaceUtils::committed_bytes(Metaspace::NonClassType);
-    assert(committed_metadata > 0, "assert");
-    assert(committed_metadata <= committed, "assert");
-
-    if (UseCompressedClassPointers) {
-      size_t committed_class    = MetaspaceUtils::committed_bytes(Metaspace::ClassType);
-      assert(committed_class > 0, "assert");
-      assert(committed_class < committed, "assert");
-    }
-  }
-
-  static void test_virtual_space_list_large_chunk() {
-    VirtualSpaceList* vs_list = new VirtualSpaceList(os::vm_allocation_granularity());
-    MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
-    // A size larger than VirtualSpaceSize (256k) and add one page to make it _not_ be
-    // vm_allocation_granularity aligned on Windows.
-    size_t large_size = (size_t)(2*256*K + (os::vm_page_size()/BytesPerWord));
-    large_size += (os::vm_page_size()/BytesPerWord);
-    vs_list->get_new_chunk(large_size, 0);
-  }
-
-  static void test() {
-    test_reserved();
-    test_committed();
-    test_virtual_space_list_large_chunk();
-  }
-};
-
-void TestMetaspaceUtils_test() {
-  TestMetaspaceUtilsTest::test();
-}
-
-#endif // !PRODUCT
-
 struct chunkmanager_statistics_t {
   int num_specialized_chunks;
   int num_small_chunks;
--- a/src/hotspot/share/memory/metaspace.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/memory/metaspace.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -28,6 +28,7 @@
 #include "memory/memRegion.hpp"
 #include "memory/metaspaceChunkFreeListSummary.hpp"
 #include "memory/virtualspace.hpp"
+#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
 #include "utilities/exceptions.hpp"
 
 // Metaspace
@@ -139,6 +140,8 @@
 
   static const MetaspaceTracer* _tracer;
 
+  static bool _initialized;
+
  public:
   static metaspace::VirtualSpaceList* space_list()       { return _space_list; }
   static metaspace::VirtualSpaceList* class_space_list() { return _class_space_list; }
@@ -224,6 +227,8 @@
     return mdType == ClassType && using_class_space();
   }
 
+  static bool initialized() { return _initialized; }
+
 };
 
 // Manages the metaspace portion belonging to a class loader
@@ -410,8 +415,8 @@
   static bool has_chunk_free_list(Metaspace::MetadataType mdtype);
   static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype);
 
-  // Print change in used metadata.
-  static void print_metaspace_change(size_t prev_metadata_used);
+  // Log change in used metadata.
+  static void print_metaspace_change(const metaspace::MetaspaceSizesSnapshot& pre_meta_values);
   static void print_on(outputStream * out);
 
   // Prints an ASCII representation of the given space.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/metaspace/metaspaceSizesSnapshot.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Twitter, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "memory/metaspace.hpp"
+#include "memory/metaspace/metaspaceSizesSnapshot.hpp"
+
+namespace metaspace {
+
+MetaspaceSizesSnapshot::MetaspaceSizesSnapshot()
+    : _used(MetaspaceUtils::used_bytes()),
+      _committed(MetaspaceUtils::committed_bytes()),
+      _non_class_used(MetaspaceUtils::used_bytes(Metaspace::NonClassType)),
+      _non_class_committed(MetaspaceUtils::committed_bytes(Metaspace::NonClassType)),
+      _class_used(MetaspaceUtils::used_bytes(Metaspace::ClassType)),
+      _class_committed(MetaspaceUtils::committed_bytes(Metaspace::ClassType)) { }
+
+} // namespace metaspace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/metaspace/metaspaceSizesSnapshot.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Twitter, Inc.
+ * 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.
+ *
+ */
+
+#ifndef SHARE_MEMORY_METASPACE_METASPACESIZESSNAPSHOT_HPP
+#define SHARE_MEMORY_METASPACE_METASPACESIZESSNAPSHOT_HPP
+
+namespace metaspace {
+
+class MetaspaceSizesSnapshot {
+public:
+  MetaspaceSizesSnapshot();
+
+  size_t used() const { return _used; }
+  size_t committed() const { return _committed; }
+  size_t non_class_used() const { return _non_class_used; }
+  size_t non_class_committed() const { return _non_class_committed; }
+  size_t class_used() const { return _class_used; }
+  size_t class_committed() const { return _class_committed; }
+
+private:
+  const size_t _used;
+  const size_t _committed;
+  const size_t _non_class_used;
+  const size_t _non_class_committed;
+  const size_t _class_used;
+  const size_t _class_committed;
+};
+
+} // namespace metaspace
+
+#endif // SHARE_MEMORY_METASPACE_METASPACESIZESSNAPSHOT_HPP
--- a/src/hotspot/share/oops/methodData.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/oops/methodData.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1607,11 +1607,14 @@
 
 bool MethodData::profile_unsafe(const methodHandle& m, int bci) {
   Bytecode_invoke inv(m , bci);
-  if (inv.is_invokevirtual() && inv.klass() == vmSymbols::jdk_internal_misc_Unsafe()) {
-    ResourceMark rm;
-    char* name = inv.name()->as_C_string();
-    if (!strncmp(name, "get", 3) || !strncmp(name, "put", 3)) {
-      return true;
+  if (inv.is_invokevirtual()) {
+    if (inv.klass() == vmSymbols::jdk_internal_misc_Unsafe() ||
+        inv.klass() == vmSymbols::sun_misc_Unsafe()) {
+      ResourceMark rm;
+      char* name = inv.name()->as_C_string();
+      if (!strncmp(name, "get", 3) || !strncmp(name, "put", 3)) {
+        return true;
+      }
     }
   }
   return false;
--- a/src/hotspot/share/opto/addnode.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/addnode.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -929,3 +929,91 @@
   // Otherwise just MIN them bits.
   return TypeInt::make( MIN2(r0->_lo,r1->_lo), MIN2(r0->_hi,r1->_hi), MAX2(r0->_widen,r1->_widen) );
 }
+
+//------------------------------add_ring---------------------------------------
+const Type *MinFNode::add_ring( const Type *t0, const Type *t1 ) const {
+  const TypeF *r0 = t0->is_float_constant();
+  const TypeF *r1 = t1->is_float_constant();
+
+  if (r0->is_nan()) {
+    return r0;
+  }
+  if (r1->is_nan()) {
+    return r1;
+  }
+
+  float f0 = r0->getf();
+  float f1 = r1->getf();
+  if (f0 != 0.0f || f1 != 0.0f) {
+    return f0 < f1 ? r0 : r1;
+  }
+
+  // handle min of 0.0, -0.0 case.
+  return (jint_cast(f0) < jint_cast(f1)) ? r0 : r1;
+}
+
+//------------------------------add_ring---------------------------------------
+const Type *MinDNode::add_ring( const Type *t0, const Type *t1 ) const {
+  const TypeD *r0 = t0->is_double_constant();
+  const TypeD *r1 = t1->is_double_constant();
+
+  if (r0->is_nan()) {
+    return r0;
+  }
+  if (r1->is_nan()) {
+    return r1;
+  }
+
+  double d0 = r0->getd();
+  double d1 = r1->getd();
+  if (d0 != 0.0 || d1 != 0.0) {
+    return d0 < d1 ? r0 : r1;
+  }
+
+  // handle min of 0.0, -0.0 case.
+  return (jlong_cast(d0) < jlong_cast(d1)) ? r0 : r1;
+}
+
+//------------------------------add_ring---------------------------------------
+const Type *MaxFNode::add_ring( const Type *t0, const Type *t1 ) const {
+  const TypeF *r0 = t0->is_float_constant();
+  const TypeF *r1 = t1->is_float_constant();
+
+  if (r0->is_nan()) {
+    return r0;
+  }
+  if (r1->is_nan()) {
+    return r1;
+  }
+
+  float f0 = r0->getf();
+  float f1 = r1->getf();
+  if (f0 != 0.0f || f1 != 0.0f) {
+    return f0 > f1 ? r0 : r1;
+  }
+
+  // handle max of 0.0,-0.0 case.
+  return (jint_cast(f0) > jint_cast(f1)) ? r0 : r1;
+}
+
+//------------------------------add_ring---------------------------------------
+const Type *MaxDNode::add_ring( const Type *t0, const Type *t1 ) const {
+  const TypeD *r0 = t0->is_double_constant();
+  const TypeD *r1 = t1->is_double_constant();
+
+  if (r0->is_nan()) {
+    return r0;
+  }
+  if (r1->is_nan()) {
+    return r1;
+  }
+
+  double d0 = r0->getd();
+  double d1 = r1->getd();
+  if (d0 != 0.0 || d1 != 0.0) {
+    return d0 > d1 ? r0 : r1;
+  }
+
+  // handle max of 0.0, -0.0 case.
+  return (jlong_cast(d0) > jlong_cast(d1)) ? r0 : r1;
+}
--- a/src/hotspot/share/opto/addnode.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/addnode.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -255,7 +255,7 @@
 public:
   MaxFNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
   virtual int Opcode() const;
-  virtual const Type *add_ring(const Type*, const Type*) const { return Type::FLOAT; }
+  virtual const Type *add_ring(const Type*, const Type*) const;
   virtual const Type *add_id() const { return TypeF::NEG_INF; }
   virtual const Type *bottom_type() const { return Type::FLOAT; }
   virtual uint ideal_reg() const { return Op_RegF; }
@@ -267,7 +267,7 @@
 public:
   MinFNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
   virtual int Opcode() const;
-  virtual const Type *add_ring(const Type*, const Type*) const { return Type::FLOAT; }
+  virtual const Type *add_ring(const Type*, const Type*) const;
   virtual const Type *add_id() const { return TypeF::POS_INF; }
   virtual const Type *bottom_type() const { return Type::FLOAT; }
   virtual uint ideal_reg() const { return Op_RegF; }
@@ -279,7 +279,7 @@
 public:
   MaxDNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
   virtual int Opcode() const;
-  virtual const Type *add_ring(const Type*, const Type*) const { return Type::DOUBLE; }
+  virtual const Type *add_ring(const Type*, const Type*) const;
   virtual const Type *add_id() const { return TypeD::NEG_INF; }
   virtual const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
@@ -291,7 +291,7 @@
 public:
   MinDNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
   virtual int Opcode() const;
-  virtual const Type *add_ring(const Type*, const Type*) const { return Type::DOUBLE; }
+  virtual const Type *add_ring(const Type*, const Type*) const;
   virtual const Type *add_id() const { return TypeD::POS_INF; }
   virtual const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint ideal_reg() const { return Op_RegD; }
--- a/src/hotspot/share/opto/compile.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/compile.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -465,7 +465,6 @@
   compile->set_type_dict(NULL);
   compile->set_clone_map(new Dict(cmpkey, hashkey, _compile->comp_arena()));
   compile->clone_map().set_clone_idx(0);
-  compile->set_type_hwm(NULL);
   compile->set_type_last_size(0);
   compile->set_last_tf(NULL, NULL);
   compile->set_indexSet_arena(NULL);
--- a/src/hotspot/share/opto/compile.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/compile.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -478,7 +478,6 @@
   Arena*                _type_arena;            // Alias for _Compile_types except in Initialize_shared()
   Dict*                 _type_dict;             // Intern table
   CloneMap              _clone_map;             // used for recording history of cloned nodes
-  void*                 _type_hwm;              // Last allocation (see Type::operator new/delete)
   size_t                _type_last_size;        // Last allocation size (see Type::operator new/delete)
   ciMethod*             _last_tf_m;             // Cache for
   const TypeFunc*       _last_tf;               //  TypeFunc::make
@@ -977,14 +976,12 @@
   // Type management
   Arena*            type_arena()                { return _type_arena; }
   Dict*             type_dict()                 { return _type_dict; }
-  void*             type_hwm()                  { return _type_hwm; }
   size_t            type_last_size()            { return _type_last_size; }
   int               num_alias_types()           { return _num_alias_types; }
 
   void          init_type_arena()                       { _type_arena = &_Compile_types; }
   void          set_type_arena(Arena* a)                { _type_arena = a; }
   void          set_type_dict(Dict* d)                  { _type_dict = d; }
-  void          set_type_hwm(void* p)                   { _type_hwm = p; }
   void          set_type_last_size(size_t sz)           { _type_last_size = sz; }
 
   const TypeFunc* last_tf(ciMethod* m) {
--- a/src/hotspot/share/opto/escape.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/escape.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -350,6 +350,12 @@
   if (n_ptn != NULL)
     return; // No need to redefine PointsTo node during first iteration.
 
+  int opcode = n->Opcode();
+  bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_to_con_graph(this, igvn, delayed_worklist, n, opcode);
+  if (gc_handled) {
+    return; // Ignore node if already handled by GC.
+  }
+
   if (n->is_Call()) {
     // Arguments to allocation and locking don't escape.
     if (n->is_AbstractLock()) {
@@ -382,11 +388,6 @@
   if (n_ptn == phantom_obj || n_ptn == null_obj)
     return; // Skip predefined nodes.
 
-  int opcode = n->Opcode();
-  bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_to_con_graph(this, igvn, delayed_worklist, n, opcode);
-  if (gc_handled) {
-    return; // Ignore node if already handled by GC.
-  }
   switch (opcode) {
     case Op_AddP: {
       Node* base = get_addp_base(n);
--- a/src/hotspot/share/opto/escape.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/escape.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -333,7 +333,6 @@
 
   bool               _verify;  // verify graph
 
-  JavaObjectNode* phantom_obj; // Unknown object
   JavaObjectNode*    null_obj;
   Node*             _pcmp_neq; // ConI(#CC_GT)
   Node*              _pcmp_eq; // ConI(#CC_EQ)
@@ -343,6 +342,10 @@
 
   Unique_Node_List ideal_nodes; // Used by CG construction and types splitting.
 
+public:
+  JavaObjectNode* phantom_obj; // Unknown object
+
+private:
   // Address of an element in _nodes.  Used when the element is to be modified
   PointsToNode* ptnode_adr(int idx) const {
     // There should be no new ideal nodes during ConnectionGraph build,
@@ -365,12 +368,6 @@
   // Add PointsToNode node corresponding to a call
   void add_call_node(CallNode* call);
 
-  // Map ideal node to existing PointsTo node (usually phantom_object).
-  void map_ideal_node(Node *n, PointsToNode* ptn) {
-    assert(ptn != NULL, "only existing PointsTo node");
-    _nodes.at_put(n->_idx, ptn);
-  }
-
   // Create PointsToNode node and add it to Connection Graph.
   void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist);
 
@@ -594,6 +591,12 @@
     add_edge(ptnode_adr(n->_idx), ptn);
   }
 
+  // Map ideal node to existing PointsTo node (usually phantom_object).
+  void map_ideal_node(Node *n, PointsToNode* ptn) {
+    assert(ptn != NULL, "only existing PointsTo node");
+    _nodes.at_put(n->_idx, ptn);
+  }
+
   void add_to_congraph_unsafe_access(Node* n, uint opcode, Unique_Node_List* delayed_worklist);
   bool add_final_edges_unsafe_access(Node* n, uint opcode);
 
--- a/src/hotspot/share/opto/lcm.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/lcm.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -170,7 +170,6 @@
     case Op_LoadI:
     case Op_LoadL:
     case Op_LoadP:
-    case Op_LoadBarrierSlowReg:
     case Op_LoadN:
     case Op_LoadS:
     case Op_LoadKlass:
--- a/src/hotspot/share/opto/library_call.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/library_call.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -6706,9 +6706,6 @@
     fatal_unexpected_iid(id);
     break;
   }
-  if (a->is_Con() || b->is_Con()) {
-    return false;
-  }
   switch (id) {
   case vmIntrinsics::_maxF:  n = new MaxFNode(a, b);  break;
   case vmIntrinsics::_minF:  n = new MinFNode(a, b);  break;
--- a/src/hotspot/share/opto/loopnode.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/loopnode.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -2494,9 +2494,11 @@
       }
     }
   }
-  // Add data (x1.5) and control (x1.0) count to estimate iff both are > 0.
+  // Add data and control count (x2.0) to estimate iff both are > 0. This is
+  // a rather pessimistic estimate for the most part, in particular for some
+  // complex loops, but still not enough to capture all loops.
   if (ctrl_edge_out_cnt > 0 && data_edge_out_cnt > 0) {
-    estimate += ctrl_edge_out_cnt + data_edge_out_cnt + data_edge_out_cnt / 2;
+    estimate += 2 * (ctrl_edge_out_cnt + data_edge_out_cnt);
   }
 
   return estimate;
@@ -4292,7 +4294,6 @@
     case Op_LoadL:
     case Op_LoadS:
     case Op_LoadP:
-    case Op_LoadBarrierSlowReg:
     case Op_LoadN:
     case Op_LoadRange:
     case Op_LoadD_unaligned:
--- a/src/hotspot/share/opto/macro.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/macro.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1008,8 +1008,17 @@
         assert(init->outcnt() <= 2, "only a control and memory projection expected");
         Node *ctrl_proj = init->proj_out_or_null(TypeFunc::Control);
         if (ctrl_proj != NULL) {
-           assert(init->in(TypeFunc::Control) == _fallthroughcatchproj, "allocation control projection");
-          _igvn.replace_node(ctrl_proj, _fallthroughcatchproj);
+          _igvn.replace_node(ctrl_proj, init->in(TypeFunc::Control));
+#ifdef ASSERT
+          BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
+          Node* tmp = init->in(TypeFunc::Control);
+          while (bs->is_gc_barrier_node(tmp)) {
+            Node* tmp2 = bs->step_over_gc_barrier_ctrl(tmp);
+            assert(tmp != tmp2, "Must make progress");
+            tmp = tmp2;
+          }
+          assert(tmp == _fallthroughcatchproj, "allocation control projection");
+#endif
         }
         Node *mem_proj = init->proj_out_or_null(TypeFunc::Memory);
         if (mem_proj != NULL) {
--- a/src/hotspot/share/opto/node.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/node.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -675,6 +675,7 @@
       DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6)
         DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0)
         DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1)
+      DEFINE_CLASS_ID(LoadBarrierSlowReg, Type, 7)
 
     DEFINE_CLASS_ID(Proj,  Node, 3)
       DEFINE_CLASS_ID(CatchProj, Proj, 0)
@@ -688,7 +689,6 @@
     DEFINE_CLASS_ID(Mem,   Node, 4)
       DEFINE_CLASS_ID(Load,  Mem, 0)
         DEFINE_CLASS_ID(LoadVector,  Load, 0)
-        DEFINE_CLASS_ID(LoadBarrierSlowReg, Load, 1)
       DEFINE_CLASS_ID(Store, Mem, 1)
         DEFINE_CLASS_ID(StoreVector, Store, 0)
       DEFINE_CLASS_ID(LoadStore, Mem, 2)
--- a/src/hotspot/share/opto/type.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/type.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -411,18 +411,8 @@
 }
 
 #define SMALLINT ((juint)3)  // a value too insignificant to consider widening
-
-static double pos_dinf() {
-  union { int64_t i; double d; } v;
-  v.i = CONST64(0x7ff0000000000000);
-  return v.d;
-}
-
-static float pos_finf() {
-  union { int32_t i; float f; } v;
-  v.i = 0x7f800000;
-  return v.f;
-}
+#define POSITIVE_INFINITE_F 0x7f800000 // hex representation for IEEE 754 single precision positive infinite
+#define POSITIVE_INFINITE_D 0x7ff0000000000000 // hex representation for IEEE 754 double precision positive infinite
 
 //--------------------------Initialize_shared----------------------------------
 void Type::Initialize_shared(Compile* current) {
@@ -453,13 +443,13 @@
 
   TypeF::ZERO = TypeF::make(0.0); // Float 0 (positive zero)
   TypeF::ONE  = TypeF::make(1.0); // Float 1
-  TypeF::POS_INF = TypeF::make(pos_finf());
-  TypeF::NEG_INF = TypeF::make(-pos_finf());
+  TypeF::POS_INF = TypeF::make(jfloat_cast(POSITIVE_INFINITE_F));
+  TypeF::NEG_INF = TypeF::make(-jfloat_cast(POSITIVE_INFINITE_F));
 
   TypeD::ZERO = TypeD::make(0.0); // Double 0 (positive zero)
   TypeD::ONE  = TypeD::make(1.0); // Double 1
-  TypeD::POS_INF = TypeD::make(pos_dinf());
-  TypeD::NEG_INF = TypeD::make(-pos_dinf());
+  TypeD::POS_INF = TypeD::make(jdouble_cast(POSITIVE_INFINITE_D));
+  TypeD::NEG_INF = TypeD::make(-jdouble_cast(POSITIVE_INFINITE_D));
 
   TypeInt::MINUS_1 = TypeInt::make(-1);  // -1
   TypeInt::ZERO    = TypeInt::make( 0);  //  0
--- a/src/hotspot/share/opto/type.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/type.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -184,9 +184,7 @@
   inline void* operator new( size_t x ) throw() {
     Compile* compile = Compile::current();
     compile->set_type_last_size(x);
-    void *temp = compile->type_arena()->Amalloc_D(x);
-    compile->set_type_hwm(temp);
-    return temp;
+    return compile->type_arena()->Amalloc_D(x);
   }
   inline void operator delete( void* ptr ) {
     Compile* compile = Compile::current();
--- a/src/hotspot/share/opto/vectornode.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/opto/vectornode.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -297,7 +297,6 @@
   case Op_LoadI:   case Op_LoadL:
   case Op_LoadF:   case Op_LoadD:
   case Op_LoadP:   case Op_LoadN:
-  case Op_LoadBarrierSlowReg:
     *start = 0;
     *end   = 0; // no vector operands
     break;
--- a/src/hotspot/share/prims/jvmti.xsl	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/prims/jvmti.xsl	Mon Jul 08 16:04:25 2019 +0530
@@ -62,37 +62,96 @@
     <div class="centered" role="banner">
       <xsl:apply-templates select="title"/>
     </div>
-    <ul role="navigation">
-      <li>
-        <a href="#SpecificationIntro"><b>Introduction</b></a>
-        <ul>
-          <xsl:for-each select="intro">
+    <nav>
+      <ul>
+        <li>
+          <a href="#SpecificationIntro"><b>Introduction</b></a>
+          <ul>
+            <xsl:for-each select="intro">
+              <li>
+                <a>
+                  <xsl:attribute name="href">#<xsl:value-of select="@id"/>
+                  </xsl:attribute>
+                  <b><xsl:value-of select="@label"/></b>
+                </a>
+              </li>
+            </xsl:for-each>
+          </ul>
+        </li>
+        <li>
+          <a href="#FunctionSection"><b>Functions</b></a>
+          <ul>
+            <xsl:for-each select="functionsection/intro">
+              <li>
+                <a>
+                  <xsl:attribute name="href">#<xsl:value-of select="@id"/>
+                  </xsl:attribute>
+                  <b><xsl:value-of select="@label"/></b>
+                </a>
+              </li>
+            </xsl:for-each>
+            <li>
+              <a href="#FunctionIndex"><b>Function Index</b></a>
+              <ul>
+                <xsl:for-each select="functionsection/category">
+                  <li>
+                    <a>
+                      <xsl:attribute name="href">#<xsl:value-of select="@id"/>
+                      </xsl:attribute>
+                      <b><xsl:value-of select="@label"/></b>
+                    </a>
+                  </li>
+                </xsl:for-each>
+              </ul>
+            </li>
+            <li>
+              <a href="#ErrorSection"><b>Error Codes</b></a>
+            </li>
+          </ul>
+        </li>
+        <li>
+          <a href="#EventSection"><b>Events</b></a>
+          <ul>
+            <li>
+              <a href="#EventIndex"><b>Event Index</b></a>
+            </li>
+          </ul>
+        </li>
+        <li>
+          <a href="#DataSection"><b>Data Types</b></a>
+          <ul>
+            <xsl:for-each select="//basetypes">
             <li>
               <a>
-                <xsl:attribute name="href">#<xsl:value-of select="@id"/>
-                </xsl:attribute>
-                <b><xsl:value-of select="@label"/></b>
+                <xsl:attribute name="href">#<xsl:value-of select="@id"/></xsl:attribute>
+                <b>
+                  <xsl:value-of select="@label"/>
+                </b>
               </a>
             </li>
-          </xsl:for-each>
-        </ul>
-      </li>
-      <li>
-        <a href="#FunctionSection"><b>Functions</b></a>
-        <ul>
-          <xsl:for-each select="functionsection/intro">
+            </xsl:for-each>
+            <li>
+              <a href="#StructureTypeDefinitions"><b>Structure Type Definitions</b></a>
+            </li>
+            <li>
+              <a href="#FunctionTypeDefinitions"><b>Function Type Definitions</b></a>
+            </li>
+            <li>
+              <a href="#EnumerationDefinitions"><b>Enumeration Definitions</b></a>
+            </li>
             <li>
-              <a>
-                <xsl:attribute name="href">#<xsl:value-of select="@id"/>
-                </xsl:attribute>
-                <b><xsl:value-of select="@label"/></b>
-              </a>
+              <a href="#FunctionTable"><b>Function Table</b></a>
             </li>
-          </xsl:for-each>
+          </ul>
+        </li>
+        <li>
+          <a href="#ConstantIndex"><b>Constant Index</b></a>
+        </li>
+        <xsl:if test="$development = 'Show'">
           <li>
-            <a href="#FunctionIndex"><b>Function Index</b></a>
+            <a href="#SpecificationIssues"><b>Issues</b></a>
             <ul>
-              <xsl:for-each select="functionsection/category">
+              <xsl:for-each select="issuessection/intro">
                 <li>
                   <a>
                     <xsl:attribute name="href">#<xsl:value-of select="@id"/>
@@ -103,69 +162,12 @@
               </xsl:for-each>
             </ul>
           </li>
-          <li>
-            <a href="#ErrorSection"><b>Error Codes</b></a>
-          </li>
-        </ul>
-      </li>
-      <li>
-        <a href="#EventSection"><b>Events</b></a>
-        <ul>
-          <li>
-            <a href="#EventIndex"><b>Event Index</b></a>
-          </li>
-        </ul>
-      </li>
-      <li>
-        <a href="#DataSection"><b>Data Types</b></a>
-        <ul>
-          <xsl:for-each select="//basetypes">
-          <li>
-            <a>
-              <xsl:attribute name="href">#<xsl:value-of select="@id"/></xsl:attribute>
-              <b>
-                <xsl:value-of select="@label"/>
-              </b>
-            </a>
-          </li>
-          </xsl:for-each>
-          <li>
-            <a href="#StructureTypeDefinitions"><b>Structure Type Definitions</b></a>
-          </li>
-          <li>
-            <a href="#FunctionTypeDefinitions"><b>Function Type Definitions</b></a>
-          </li>
-          <li>
-            <a href="#EnumerationDefinitions"><b>Enumeration Definitions</b></a>
-          </li>
-          <li>
-            <a href="#FunctionTable"><b>Function Table</b></a>
-          </li>
-        </ul>
-      </li>
-      <li>
-        <a href="#ConstantIndex"><b>Constant Index</b></a>
-      </li>
-      <xsl:if test="$development = 'Show'">
+        </xsl:if>
         <li>
-          <a href="#SpecificationIssues"><b>Issues</b></a>
-          <ul>
-            <xsl:for-each select="issuessection/intro">
-              <li>
-                <a>
-                  <xsl:attribute name="href">#<xsl:value-of select="@id"/>
-                  </xsl:attribute>
-                  <b><xsl:value-of select="@label"/></b>
-                </a>
-              </li>
-            </xsl:for-each>
-          </ul>
+          <a href="#ChangeHistory"><b>Change History</b></a>
         </li>
-      </xsl:if>
-      <li>
-        <a href="#ChangeHistory"><b>Change History</b></a>
-      </li>
-    </ul>
+      </ul>
+    </nav>
     <!-- end table of contents, begin body -->
     <div role="main">
     <div class="sep"/>
@@ -212,11 +214,11 @@
     <h1>
       <xsl:apply-templates/>
     </h1>
-    <h3>
+    <h2>
       <xsl:value-of select="@subtitle"/>
       <xsl:text> </xsl:text>
       <xsl:call-template name="showbasicversion"/>
-    </h3>
+    </h2>
 </xsl:template>
 
 <xsl:template match="functionsection">
@@ -363,7 +365,7 @@
       </td>
     </tr>
     <tr>
-      <td >
+      <td>
         <xsl:apply-templates select="." mode="phaseinfo"/>
       </td>
       <td>
@@ -642,12 +644,12 @@
 </xsl:template>
 
 <xsl:template match="capabilitiestypedef|typedef|uniontypedef">
-  <h4>
+  <h3>
     <xsl:attribute name="id">
       <xsl:value-of select="@id"/>
     </xsl:attribute>
     <xsl:value-of select="@label"/>
-  </h4>
+  </h3>
   <xsl:apply-templates select="." mode="description"/>
   <blockquote>
     <xsl:apply-templates select="." mode="code"/>
@@ -1951,12 +1953,12 @@
   <xsl:if test="@id!=''">
     <xsl:choose>
       <xsl:when test="@label!=''">
-        <h4>
+        <h3>
           <xsl:attribute name="id">
             <xsl:value-of select="@id"/>
           </xsl:attribute>
           <xsl:value-of select="@label"/>
-        </h4>
+        </h3>
       </xsl:when>
       <xsl:otherwise>
         <a>
--- a/src/hotspot/share/prims/whitebox.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/prims/whitebox.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -242,7 +242,6 @@
 void TestReservedSpace_test();
 void TestReserveMemorySpecial_test();
 void TestVirtualSpace_test();
-void TestMetaspaceUtils_test();
 #endif
 
 WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
@@ -250,7 +249,6 @@
   TestReservedSpace_test();
   TestReserveMemorySpecial_test();
   TestVirtualSpace_test();
-  TestMetaspaceUtils_test();
 #endif
 WB_END
 
--- a/src/hotspot/share/runtime/arguments.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/arguments.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -3571,7 +3571,7 @@
           "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping");
       }
       if (DynamicDumpSharedSpaces) {
-        if (FileMapInfo::same_files(SharedArchiveFile, ArchiveClassesAtExit)) {
+        if (os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) {
           vm_exit_during_initialization(
             "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit",
             SharedArchiveFile);
--- a/src/hotspot/share/runtime/biasedLocking.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/biasedLocking.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -52,23 +52,24 @@
   k->set_prototype_header(markOopDesc::biased_locking_prototype());
 }
 
+static void enable_biased_locking() {
+  _biased_locking_enabled = true;
+  log_info(biasedlocking)("Biased locking enabled");
+}
+
 class VM_EnableBiasedLocking: public VM_Operation {
- private:
-  bool _is_cheap_allocated;
  public:
-  VM_EnableBiasedLocking(bool is_cheap_allocated) { _is_cheap_allocated = is_cheap_allocated; }
+  VM_EnableBiasedLocking() {}
   VMOp_Type type() const          { return VMOp_EnableBiasedLocking; }
-  Mode evaluation_mode() const    { return _is_cheap_allocated ? _async_safepoint : _safepoint; }
-  bool is_cheap_allocated() const { return _is_cheap_allocated; }
+  Mode evaluation_mode() const    { return _async_safepoint; }
+  bool is_cheap_allocated() const { return true; }
 
   void doit() {
     // Iterate the class loader data dictionaries enabling biased locking for all
     // currently loaded classes.
     ClassLoaderDataGraph::dictionary_classes_do(enable_biased_locking);
     // Indicate that future instances should enable it as well
-    _biased_locking_enabled = true;
-
-    log_info(biasedlocking)("Biased locking enabled");
+    enable_biased_locking();
   }
 
   bool allow_nested_vm_operations() const        { return false; }
@@ -83,7 +84,7 @@
   virtual void task() {
     // Use async VM operation to avoid blocking the Watcher thread.
     // VM Thread will free C heap storage.
-    VM_EnableBiasedLocking *op = new VM_EnableBiasedLocking(true);
+    VM_EnableBiasedLocking *op = new VM_EnableBiasedLocking();
     VMThread::execute(op);
 
     // Reclaim our storage and disenroll ourself
@@ -93,27 +94,29 @@
 
 
 void BiasedLocking::init() {
-  // If biased locking is enabled, schedule a task to fire a few
-  // seconds into the run which turns on biased locking for all
-  // currently loaded classes as well as future ones. This is a
-  // workaround for startup time regressions due to a large number of
-  // safepoints being taken during VM startup for bias revocation.
-  // Ideally we would have a lower cost for individual bias revocation
-  // and not need a mechanism like this.
+  // If biased locking is enabled and BiasedLockingStartupDelay is set,
+  // schedule a task to fire after the specified delay which turns on
+  // biased locking for all currently loaded classes as well as future
+  // ones. This could be a workaround for startup time regressions
+  // due to large number of safepoints being taken during VM startup for
+  // bias revocation.
   if (UseBiasedLocking) {
     if (BiasedLockingStartupDelay > 0) {
       EnableBiasedLockingTask* task = new EnableBiasedLockingTask(BiasedLockingStartupDelay);
       task->enroll();
     } else {
-      VM_EnableBiasedLocking op(false);
-      VMThread::execute(&op);
+      enable_biased_locking();
     }
   }
 }
 
 
 bool BiasedLocking::enabled() {
-  return _biased_locking_enabled;
+  assert(UseBiasedLocking, "precondition");
+  // We check "BiasedLockingStartupDelay == 0" here to cover the
+  // possibility of calls to BiasedLocking::enabled() before
+  // BiasedLocking::init().
+  return _biased_locking_enabled || BiasedLockingStartupDelay == 0;
 }
 
 // Returns MonitorInfos for all objects locked on this thread in youngest to oldest order
--- a/src/hotspot/share/runtime/deoptimization.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -840,6 +840,15 @@
     }
     return NULL;
   }
+  oop lookup_raw(intptr_t raw_value) {
+    // Have to cast to avoid little/big-endian problems.
+    if (sizeof(PrimitiveType) > sizeof(jint)) {
+      jlong value = (jlong)raw_value;
+      return lookup(value);
+    }
+    PrimitiveType value = (PrimitiveType)*((jint*)&raw_value);
+    return lookup(value);
+  }
 };
 
 typedef BoxCache<jint, java_lang_Integer_IntegerCache, java_lang_Integer> IntegerBoxCache;
@@ -878,6 +887,11 @@
     }
     return _singleton;
   }
+  oop lookup_raw(intptr_t raw_value) {
+    // Have to cast to avoid little/big-endian problems.
+    jboolean value = (jboolean)*((jint*)&raw_value);
+    return lookup(value);
+  }
   oop lookup(jboolean value) {
     if (value != 0) {
       return JNIHandles::resolve_non_null(_true_cache);
@@ -892,18 +906,14 @@
    Klass* k = java_lang_Class::as_Klass(bv->klass()->as_ConstantOopReadValue()->value()());
    BasicType box_type = SystemDictionary::box_klass_type(k);
    if (box_type != T_OBJECT) {
-     StackValue* value = StackValue::create_stack_value(fr, reg_map, bv->field_at(0));
+     StackValue* value = StackValue::create_stack_value(fr, reg_map, bv->field_at(box_type == T_LONG ? 1 : 0));
      switch(box_type) {
-       case T_INT:     return IntegerBoxCache::singleton(THREAD)->lookup(value->get_int());
-       case T_LONG: {
-                       StackValue* low = StackValue::create_stack_value(fr, reg_map, bv->field_at(1));
-                       jlong res = (jlong)low->get_int();
-                       return LongBoxCache::singleton(THREAD)->lookup(res);
-                     }
-       case T_CHAR:    return CharacterBoxCache::singleton(THREAD)->lookup(value->get_int());
-       case T_SHORT:   return ShortBoxCache::singleton(THREAD)->lookup(value->get_int());
-       case T_BYTE:    return ByteBoxCache::singleton(THREAD)->lookup(value->get_int());
-       case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup(value->get_int());
+       case T_INT:     return IntegerBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
+       case T_CHAR:    return CharacterBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
+       case T_SHORT:   return ShortBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
+       case T_BYTE:    return ByteBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
+       case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
+       case T_LONG:    return LongBoxCache::singleton(THREAD)->lookup_raw(value->get_int());
        default:;
      }
    }
--- a/src/hotspot/share/runtime/flags/jvmFlag.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/flags/jvmFlag.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -1475,19 +1475,13 @@
 
 void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges, bool skipDefaults) {
   // Print the flags sorted by name
-  // note: this method is called before the thread structure is in place
-  //       which means resource allocation cannot be used.
+  // Note: This method may be called before the thread structure is in place
+  //       which means resource allocation cannot be used. Also, it may be
+  //       called as part of error reporting, so handle native OOMs gracefully.
 
   // The last entry is the null entry.
   const size_t length = JVMFlag::numFlags - 1;
 
-  // Sort
-  JVMFlag** array = NEW_C_HEAP_ARRAY(JVMFlag*, length, mtArguments);
-  for (size_t i = 0; i < length; i++) {
-    array[i] = &flagTable[i];
-  }
-  qsort(array, length, sizeof(JVMFlag*), compare_flags);
-
   // Print
   if (!printRanges) {
     out->print_cr("[Global flags]");
@@ -1495,12 +1489,28 @@
     out->print_cr("[Global flags ranges]");
   }
 
-  for (size_t i = 0; i < length; i++) {
-    if (array[i]->is_unlocked() && !(skipDefaults && array[i]->is_default())) {
-      array[i]->print_on(out, withComments, printRanges);
+  // Sort
+  JVMFlag** array = NEW_C_HEAP_ARRAY_RETURN_NULL(JVMFlag*, length, mtArguments);
+  if (array != NULL) {
+    for (size_t i = 0; i < length; i++) {
+      array[i] = &flagTable[i];
+    }
+    qsort(array, length, sizeof(JVMFlag*), compare_flags);
+
+    for (size_t i = 0; i < length; i++) {
+      if (array[i]->is_unlocked() && !(skipDefaults && array[i]->is_default())) {
+        array[i]->print_on(out, withComments, printRanges);
+      }
+    }
+    FREE_C_HEAP_ARRAY(JVMFlag*, array);
+  } else {
+    // OOM? Print unsorted.
+    for (size_t i = 0; i < length; i++) {
+      if (flagTable[i].is_unlocked() && !(skipDefaults && flagTable[i].is_default())) {
+        flagTable[i].print_on(out, withComments, printRanges);
+      }
     }
   }
-  FREE_C_HEAP_ARRAY(JVMFlag*, array);
 }
 
 void JVMFlag::printError(bool verbose, const char* msg, ...) {
--- a/src/hotspot/share/runtime/os.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/os.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -171,10 +171,6 @@
     init_globals_ext();
   }
 
-  // File names are case-insensitive on windows only
-  // Override me as needed
-  static int    file_name_strncmp(const char* s1, const char* s2, size_t num);
-
   // unset environment variable
   static bool unsetenv(const char* name);
 
@@ -544,6 +540,8 @@
 
   static int compare_file_modified_times(const char* file1, const char* file2);
 
+  static bool same_files(const char* file1, const char* file2);
+
   //File i/o operations
 
   static ssize_t read(int fd, void *buf, unsigned int nBytes);
--- a/src/hotspot/share/runtime/safepoint.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/safepoint.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -35,6 +35,7 @@
 #include "code/scopeDesc.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/gcLocker.hpp"
+#include "gc/shared/oopStorage.hpp"
 #include "gc/shared/strongRootsScope.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "interpreter/interpreter.hpp"
@@ -643,6 +644,12 @@
       }
     }
 
+    if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP)) {
+      // Don't bother reporting event or time for this very short operation.
+      // To have any utility we'd also want to report whether needed.
+      OopStorage::trigger_cleanup_if_needed();
+    }
+
     _subtasks.all_tasks_completed(_num_workers);
   }
 };
--- a/src/hotspot/share/runtime/safepoint.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/safepoint.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -77,6 +77,7 @@
     SAFEPOINT_CLEANUP_STRING_TABLE_REHASH,
     SAFEPOINT_CLEANUP_CLD_PURGE,
     SAFEPOINT_CLEANUP_SYSTEM_DICTIONARY_RESIZE,
+    SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP,
     // Leave this one last.
     SAFEPOINT_CLEANUP_NUM_TASKS
   };
--- a/src/hotspot/share/runtime/serviceThread.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/serviceThread.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -83,27 +83,9 @@
   }
 }
 
-static bool needs_oopstorage_cleanup(OopStorage* const* storages,
-                                     bool* needs_cleanup,
-                                     size_t size) {
-  bool any_needs_cleanup = false;
+static void cleanup_oopstorages(OopStorage* const* storages, size_t size) {
   for (size_t i = 0; i < size; ++i) {
-    assert(!needs_cleanup[i], "precondition");
-    if (storages[i]->needs_delete_empty_blocks()) {
-      needs_cleanup[i] = true;
-      any_needs_cleanup = true;
-    }
-  }
-  return any_needs_cleanup;
-}
-
-static void cleanup_oopstorages(OopStorage* const* storages,
-                                const bool* needs_cleanup,
-                                size_t size) {
-  for (size_t i = 0; i < size; ++i) {
-    if (needs_cleanup[i]) {
-      storages[i]->delete_empty_blocks();
-    }
+    storages[i]->delete_empty_blocks();
   }
 }
 
@@ -126,7 +108,6 @@
     bool resolved_method_table_work = false;
     bool protection_domain_table_work = false;
     bool oopstorage_work = false;
-    bool oopstorages_cleanup[oopstorage_count] = {}; // Zero (false) initialize.
     JvmtiDeferredEvent jvmti_event;
     {
       // Need state transition ThreadBlockInVM so that this thread
@@ -152,10 +133,7 @@
               (symboltable_work = SymbolTable::has_work()) |
               (resolved_method_table_work = ResolvedMethodTable::has_work()) |
               (protection_domain_table_work = SystemDictionary::pd_cache_table()->has_work()) |
-              (oopstorage_work = needs_oopstorage_cleanup(oopstorages,
-                                                          oopstorages_cleanup,
-                                                          oopstorage_count)))
-
+              (oopstorage_work = OopStorage::has_cleanup_work_and_reset()))
              == 0) {
         // Wait until notified that there is some work to do.
         ml.wait();
@@ -199,7 +177,7 @@
     }
 
     if (oopstorage_work) {
-      cleanup_oopstorages(oopstorages, oopstorages_cleanup, oopstorage_count);
+      cleanup_oopstorages(oopstorages, oopstorage_count);
     }
   }
 }
--- a/src/hotspot/share/runtime/vmOperations.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/runtime/vmOperations.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -72,6 +72,7 @@
   template(ZMarkStart)                            \
   template(ZMarkEnd)                              \
   template(ZRelocateStart)                        \
+  template(ZVerify)                               \
   template(HandshakeOneThread)                    \
   template(HandshakeAllThreads)                   \
   template(HandshakeFallback)                     \
@@ -128,6 +129,7 @@
   template(ScavengeMonitors)                      \
   template(PrintMetadata)                         \
   template(GTestExecuteAtSafepoint)               \
+  template(JFROldObject)                          \
 
 class VM_Operation: public CHeapObj<mtInternal> {
  public:
--- a/src/hotspot/share/services/diagnosticCommand.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/services/diagnosticCommand.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -880,7 +880,7 @@
     return "High: Switches the VM into Java debug mode.";
   }
   static const JavaPermission permission() {
-    JavaPermission p = { "java.lang.management.ManagementPermission", "monitor", NULL };
+    JavaPermission p = { "java.lang.management.ManagementPermission", "control", NULL };
     return p;
   }
   static int num_arguments() { return 0; }
--- a/src/hotspot/share/utilities/globalDefinitions.hpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp	Mon Jul 08 16:04:25 2019 +0530
@@ -308,6 +308,13 @@
   return s;
 }
 
+// Memory size transition formatting.
+
+#define HEAP_CHANGE_FORMAT "%s: " SIZE_FORMAT "K(" SIZE_FORMAT "K)->" SIZE_FORMAT "K(" SIZE_FORMAT "K)"
+
+#define HEAP_CHANGE_FORMAT_ARGS(_name_, _prev_used_, _prev_capacity_, _used_, _capacity_) \
+  (_name_), (_prev_used_) / K, (_prev_capacity_) / K, (_used_) / K, (_capacity_) / K
+
 //----------------------------------------------------------------------------------------------------
 // VM type definitions
 
--- a/src/java.base/share/classes/java/lang/Class.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/java/lang/Class.java	Mon Jul 08 16:04:25 2019 +0530
@@ -3491,9 +3491,17 @@
      * Returns true if and only if this class was declared as an enum in the
      * source code.
      *
+     * Note that if an enum constant is declared with a class body,
+     * the class of that enum constant object is an anonymous class
+     * and <em>not</em> the class of the declaring enum type. The
+     * {@link Enum#getDeclaringClass} method of an enum constant can
+     * be used to get the class of the enum type declaring the
+     * constant.
+     *
      * @return true if and only if this class was declared as an enum in the
      *     source code
      * @since 1.5
+     * @jls 8.9.1 Enum Constants
      */
     public boolean isEnum() {
         // An enum must both directly extend java.lang.Enum and have
--- a/src/java.base/share/classes/java/lang/Throwable.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/java/lang/Throwable.java	Mon Jul 08 16:04:25 2019 +0530
@@ -693,7 +693,7 @@
                                          Set<Throwable> dejaVu) {
         assert Thread.holdsLock(s.lock());
         if (dejaVu.contains(this)) {
-            s.println("\t[CIRCULAR REFERENCE:" + this + "]");
+            s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]");
         } else {
             dejaVu.add(this);
             // Compute number of frames in common between this and enclosing trace
--- a/src/java.base/share/classes/java/net/Inet6AddressImpl.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/java/net/Inet6AddressImpl.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -25,6 +25,8 @@
 package java.net;
 
 import java.io.IOException;
+
+import static java.net.InetAddress.IPv6;
 import static java.net.InetAddress.PREFER_IPV6_VALUE;
 import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
 
@@ -70,7 +72,7 @@
              * stack system).
              */
             java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
-            InetAddress inetaddr = null;
+            InetAddress inetaddr;
             while (it.hasMoreElements()) {
                 inetaddr = it.nextElement();
                 if (inetaddr.getClass().isInstance(addr)) {
@@ -110,20 +112,23 @@
             boolean preferIPv6Address =
                 InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
                 InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE;
-            InetAddress loopback4 = (new Inet4AddressImpl()).loopbackAddress();
-            InetAddress loopback6 = new Inet6Address("localhost",
-                new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
-            // Order the candidate addresses by preference.
-            InetAddress[] addresses = preferIPv6Address
-                ? new InetAddress[] {loopback6, loopback4}
-                : new InetAddress[] {loopback4, loopback6};
-            // In case of failure, default to the preferred address.
-            loopbackAddress = addresses[0];
-            // Pick the first candidate address that actually exists.
-            for (InetAddress address : addresses) {
+
+            for (int i = 0; i < 2; i++) {
+                InetAddress address;
+                // Order the candidate addresses by preference.
+                if (i == (preferIPv6Address ? 0 : 1)) {
+                    address = new Inet6Address("localhost",
+                            new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
+                } else {
+                    address = new Inet4Address("localhost", new byte[]{ 0x7f,0x00,0x00,0x01 });
+                }
+                if (i == 0) {
+                    // In case of failure, default to the preferred address.
+                    loopbackAddress = address;
+                }
                 try {
-                    if (NetworkInterface.getByInetAddress(address) == null) {
+                    if (!NetworkInterface.isBoundInetAddress(address)) {
                         continue;
                     }
                 } catch (SocketException e) {
--- a/src/java.base/share/classes/java/net/InetAddress.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/java/net/InetAddress.java	Mon Jul 08 16:04:25 2019 +0530
@@ -290,7 +290,7 @@
     }
 
     /* Used to store the name service provider */
-    private static transient NameService nameService = null;
+    private static transient NameService nameService;
 
     /**
      * Used to store the best available hostname.
@@ -305,8 +305,7 @@
      * Load net library into runtime, and perform initializations.
      */
     static {
-        String str = java.security.AccessController.doPrivileged(
-                new GetPropertyAction("java.net.preferIPv6Addresses"));
+        String str = GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
         if (str == null) {
             preferIPv6Address = PREFER_IPV4_VALUE;
         } else if (str.equalsIgnoreCase("true")) {
--- a/src/java.base/share/classes/java/net/NetworkInterface.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/java/net/NetworkInterface.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -321,17 +321,16 @@
         if (addr == null) {
             throw new NullPointerException();
         }
-        if (addr instanceof Inet4Address) {
-            Inet4Address inet4Address = (Inet4Address) addr;
-            if (inet4Address.holder.family != InetAddress.IPv4) {
+
+        if (addr.holder.family == InetAddress.IPv4) {
+            if (!(addr instanceof Inet4Address)) {
                 throw new IllegalArgumentException("invalid family type: "
-                        + inet4Address.holder.family);
+                        + addr.holder.family);
             }
-        } else if (addr instanceof Inet6Address) {
-            Inet6Address inet6Address = (Inet6Address) addr;
-            if (inet6Address.holder.family != InetAddress.IPv6) {
+        } else if (addr.holder.family == InetAddress.IPv6) {
+            if (!(addr instanceof Inet6Address)) {
                 throw new IllegalArgumentException("invalid family type: "
-                        + inet6Address.holder.family);
+                        + addr.holder.family);
             }
         } else {
             throw new IllegalArgumentException("invalid address type: " + addr);
@@ -394,6 +393,23 @@
         }
     }
 
+    /**
+     * Checks if the given address is bound to any of the interfaces on this
+     * machine.
+     *
+     * @param   addr
+     *          The {@code InetAddress} to search with.
+     * @return  true iff the addr parameter is currently bound to one of
+     *          the interfaces on this machine.
+     *
+     * @throws  SocketException
+     *          If an I/O error occurs.
+     */
+    /* package-private */ static boolean isBoundInetAddress(InetAddress addr)
+        throws SocketException {
+        return boundInetAddress0(addr);
+    }
+
     private static <T> Enumeration<T> enumerationFromArray(T[] a) {
         return new Enumeration<>() {
             int i = 0;
@@ -431,6 +447,9 @@
     private static native NetworkInterface getByIndex0(int index)
         throws SocketException;
 
+    private static native boolean boundInetAddress0(InetAddress addr)
+            throws SocketException;
+
     private static native NetworkInterface getByInetAddress0(InetAddress addr)
         throws SocketException;
 
--- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Mon Jul 08 16:04:25 2019 +0530
@@ -75,7 +75,7 @@
 \    -D<name>=<value>\n\
 \                  set a system property\n\
 \    -verbose:[class|module|gc|jni]\n\
-\                  enable verbose output\n\
+\                  enable verbose output for the given subsystem\n\
 \    -version      print product version to the error stream and exit\n\
 \    --version     print product version to the output stream and exit\n\
 \    -showversion  print product version to the error stream and continue\n\
@@ -129,9 +129,9 @@
 \                      append to end of bootstrap class path\n\
 \    -Xcheck:jni       perform additional checks for JNI functions\n\
 \    -Xcomp            forces compilation of methods on first invocation\n\
-\    -Xdebug           provided for backward compatibility\n\
+\    -Xdebug           does nothing. Provided for backward compatibility.\n\
 \    -Xdiag            show additional diagnostic messages\n\
-\    -Xfuture          enable strictest checks, anticipating future default\n\
+\    -Xfuture          enable strictest checks, anticipating future default.\n\
 \                      This option is deprecated and may be removed in a\n\
 \                      future release.\n\
 \    -Xint             interpreted mode execution only\n\
@@ -141,7 +141,9 @@
 \    -Xlog:<opts>      Configure or enable logging with the Java Virtual\n\
 \                      Machine (JVM) unified logging framework. Use -Xlog:help\n\
 \                      for details.\n\
-\    -Xloggc:<file>    log GC status to a file with time stamps\n\
+\    -Xloggc:<file>    log GC status to a file with time stamps.\n\
+\                      This option is deprecated and may be removed in a\n\
+\                      future release. It is replaced by -Xlog:gc:<file>.\n\
 \    -Xmixed           mixed mode execution (default)\n\
 \    -Xmn<size>        sets the initial and maximum size (in bytes) of the heap\n\
 \                      for the young generation (nursery)\n\
@@ -152,6 +154,8 @@
 \    -Xshare:auto      use shared class data if possible (default)\n\
 \    -Xshare:off       do not attempt to use shared class data\n\
 \    -Xshare:on        require using shared class data, otherwise fail.\n\
+\                      This is a testing option and may lead to intermittent\n\
+\                      failures. It should not be used in production environments.\n\
 \    -XshowSettings    show all settings and continue\n\
 \    -XshowSettings:all\n\
 \                      show all settings and continue\n\
@@ -191,7 +195,6 @@
 \    --patch-module <module>=<file>({0}<file>)*\n\
 \                      override or augment a module with classes and resources\n\
 \                      in JAR files or directories.\n\
-\    --disable-@files  disable further argument file expansion\n\
 \    --source <version>\n\
 \                      set the version of the source in source-file mode.\n\n\
 These extra options are subject to change without notice.\n
@@ -199,7 +202,7 @@
 # Translators please note do not translate the options themselves
 java.launcher.X.macosx.usage=\
 \n\
-The following options are Mac OS X specific:\n\
+The following options are macOS specific:\n\
 \    -XstartOnFirstThread\n\
 \                      run the main() method on the first (AppKit) thread\n\
 \    -Xdock:name=<application name>\n\
--- a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
 import java.nio.*;
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
-
+import java.util.Objects;
 
 /**
  * This class is defined here rather than in java.nio.channels.Channels
@@ -87,10 +87,8 @@
     public synchronized int read(byte[] bs, int off, int len)
         throws IOException
     {
-        if ((off < 0) || (off > bs.length) || (len < 0) ||
-            ((off + len) > bs.length) || ((off + len) < 0)) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0)
+        Objects.checkFromIndexSize(off, len, bs.length);
+        if (len == 0)
             return 0;
 
         ByteBuffer bb = ((this.bs == bs)
@@ -119,6 +117,26 @@
         return 0;
     }
 
+    public synchronized long skip(long n) throws IOException {
+        // special case where the channel is to a file
+        if (ch instanceof SeekableByteChannel && n > 0) {
+            SeekableByteChannel sbc = (SeekableByteChannel)ch;
+            try {
+                long pos = sbc.position();
+                long size = sbc.size();
+                if (pos >= size) {
+                   return 0L;
+                }
+                n = Math.min(n, size - pos);
+                sbc.position(pos + n);
+                return sbc.position() - pos;
+            } catch (ClosedChannelException cce) {
+                throw new IOException(cce);
+            }
+        }
+        return super.skip(n);
+    }
+
     public void close() throws IOException {
         ch.close();
     }
--- a/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java	Mon Jul 08 16:04:25 2019 +0530
@@ -249,9 +249,15 @@
             switch (requestID) {
             case FIRST_DAY_OF_WEEK:
                 value = calendarDataProvider.getFirstDayOfWeek(locale);
+                if (value == 0) {
+                    value = MONDAY; // default for the world ("001")
+                }
                 break;
             case MINIMAL_DAYS_IN_FIRST_WEEK:
                 value = calendarDataProvider.getMinimalDaysInFirstWeek(locale);
+                if (value == 0) {
+                    value = 1; // default for the world ("001")
+                }
                 break;
             default:
                 throw new InternalError("invalid requestID: " + requestID);
--- a/src/java.base/unix/native/libnet/NetworkInterface.c	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/unix/native/libnet/NetworkInterface.c	Mon Jul 08 16:04:25 2019 +0530
@@ -320,33 +320,9 @@
     return obj;
 }
 
-/*
- * Class:     java_net_NetworkInterface
- * Method:    getByInetAddress0
- * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
- */
-JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
-  (JNIEnv *env, jclass cls, jobject iaObj)
-{
-    netif *ifs, *curr;
-    jobject obj = NULL;
-    jboolean match = JNI_FALSE;
-    int family = getInetAddress_family(env, iaObj);
-    JNU_CHECK_EXCEPTION_RETURN(env, NULL);
-
-    if (family == java_net_InetAddress_IPv4) {
-        family = AF_INET;
-    } else if (family == java_net_InetAddress_IPv6) {
-        family = AF_INET6;
-    } else {
-        return NULL; // Invalid family
-    }
-    ifs = enumInterfaces(env);
-    if (ifs == NULL) {
-        return NULL;
-    }
-
-    curr = ifs;
+// Return the interface in ifs that iaObj is bound to, if any - otherwise NULL
+static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) {
+    netif* curr = ifs;
     while (curr != NULL) {
         netaddr *addrP = curr->addr;
 
@@ -359,11 +335,10 @@
                         ((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
                     int address2 = getInetAddress_addr(env, iaObj);
                     if ((*env)->ExceptionCheck(env)) {
-                        goto cleanup;
+                        return NULL;
                     }
                     if (address1 == address2) {
-                        match = JNI_TRUE;
-                        break;
+                        return curr;
                     }
                 } else if (family == AF_INET6) {
                     jbyte *bytes = (jbyte *)&(
@@ -383,30 +358,117 @@
                         i++;
                     }
                     if (i >= 16) {
-                        match = JNI_TRUE;
-                        break;
+                        return curr;
                     }
                 }
             }
 
-            if (match) {
-                break;
-            }
             addrP = addrP->next;
         }
-
-        if (match) {
-            break;
-        }
         curr = curr->next;
     }
 
+    return NULL;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    boundInetAddress0
+ * Signature: (Ljava/net/InetAddress;)boundInetAddress;
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0
+    (JNIEnv *env, jclass cls, jobject iaObj)
+{
+    netif *ifs = NULL;
+    jboolean bound = JNI_FALSE;
+    int sock;
+
+    int family = getInetAddress_family(env, iaObj);
+    JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+    if (family == java_net_InetAddress_IPv4) {
+        family = AF_INET;
+    } else if (family == java_net_InetAddress_IPv6) {
+        family = AF_INET6;
+    } else {
+        return JNI_FALSE; // Invalid family
+    }
+
+    if (family == AF_INET) {
+        sock = openSocket(env, AF_INET);
+        if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+            return JNI_FALSE;
+        }
+
+        // enumerate IPv4 addresses
+        if (sock >= 0) {
+            ifs = enumIPv4Interfaces(env, sock, ifs);
+            close(sock);
+
+            if ((*env)->ExceptionOccurred(env)) {
+                goto cleanup;
+            }
+        }
+        if (find_bound_interface(env, ifs, iaObj, family) != NULL)
+            bound = JNI_TRUE;
+    } else if (ipv6_available()) {
+        // If IPv6 is available then enumerate IPv6 addresses.
+        // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
+        // so we have to call ipv6_available()
+        sock = openSocket(env, AF_INET6);
+        if (sock < 0) {
+            return JNI_FALSE;
+        }
+
+        ifs = enumIPv6Interfaces(env, sock, ifs);
+        close(sock);
+
+        if ((*env)->ExceptionOccurred(env)) {
+            goto cleanup;
+        }
+
+        if (find_bound_interface(env, ifs, iaObj, family) != NULL)
+            bound = JNI_TRUE;
+    }
+
+cleanup:
+    freeif(ifs);
+
+    return bound;
+}
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    getByInetAddress0
+ * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
+  (JNIEnv *env, jclass cls, jobject iaObj)
+{
+    netif *ifs, *curr;
+    jobject obj = NULL;
+    int family = getInetAddress_family(env, iaObj);
+    JNU_CHECK_EXCEPTION_RETURN(env, NULL);
+
+    if (family == java_net_InetAddress_IPv4) {
+        family = AF_INET;
+    } else if (family == java_net_InetAddress_IPv6) {
+        family = AF_INET6;
+    } else {
+        return NULL; // Invalid family
+    }
+    ifs = enumInterfaces(env);
+    if (ifs == NULL) {
+        return NULL;
+    }
+
+    curr = find_bound_interface(env, ifs, iaObj, family);
+
     // if found create a NetworkInterface
-    if (match) {
+    if (curr != NULL) {
         obj = createNetworkInterface(env, curr);
     }
 
-cleanup:
     // release the interface list
     freeif(ifs);
 
--- a/src/java.base/windows/native/libnet/NetworkInterface.c	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/windows/native/libnet/NetworkInterface.c	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -25,6 +25,7 @@
 #include "net_util.h"
 #include "NetworkInterface.h"
 
+#include "java_net_InetAddress.h"
 #include "java_net_NetworkInterface.h"
 
 /*
@@ -347,7 +348,7 @@
     /*
      * Free the interface table and return the interface list
      */
-    if (tableP) {
+    if (tableP != NULL) {
         free(tableP);
     }
     *netifPP = netifP;
@@ -355,24 +356,13 @@
 }
 
 /*
- * Enumerate the IP addresses on an interface using the IP helper library
- * routine GetIfAddrTable and matching based on the index name. There are
- * more efficient routines but we use GetIfAddrTable because it's avaliable
- * on 98 and NT.
- *
- * Returns the count of addresses, or -1 if error. If no error occurs then
- * netaddrPP will return a list of netaddr structures with the IP addresses.
+ * Enumerate all addresses using the IP helper library
  */
-int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
+int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP)
 {
     MIB_IPADDRTABLE *tableP;
     ULONG size;
     DWORD ret;
-    DWORD i;
-    netaddr *netaddrP;
-    int count = 0;
-    unsigned long mask;
-
     /*
      * Use GetIpAddrTable to enumerate the IP Addresses
      */
@@ -396,7 +386,7 @@
         ret = GetIpAddrTable(tableP, &size, FALSE);
     }
     if (ret != NO_ERROR) {
-        if (tableP) {
+        if (tableP != NULL) {
             free(tableP);
         }
         JNU_ThrowByName(env, "java/lang/Error",
@@ -405,16 +395,35 @@
         // GetIpAddrTable in pure IPv6 environment
         return -2;
     }
+    *tablePP = tableP;
+    return 0;
+}
+
+/*
+ * Enumerate the IP addresses on an interface, given an IP address table
+ * and matching based on index.
+ *
+ * Returns the count of addresses, or -1 if error. If no error occurs then
+ * netaddrPP will return a list of netaddr structures with the IP addresses.
+ */
+int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP)
+{
+    DWORD i;
+    netaddr *netaddrP;
+    int count = 0;
+    unsigned long mask;
 
     /*
      * Iterate through the table to find the addresses with the
      * matching dwIndex. Ignore 0.0.0.0 addresses.
      */
+    if (tableP == NULL)
+        return 0;
     count = 0;
     netaddrP = NULL;
 
     i = 0;
-    while (i<tableP->dwNumEntries) {
+    while (i < tableP->dwNumEntries) {
         if (tableP->table[i].dwIndex == netifP->dwIndex &&
             tableP->table[i].dwAddr != 0) {
 
@@ -437,33 +446,33 @@
             case MIB_IF_TYPE_FDDI:
             case MIB_IF_TYPE_LOOPBACK:
             case IF_TYPE_IEEE80211:
-              /**
-               * Contrary to what it seems to indicate, dwBCastAddr doesn't
-               * contain the broadcast address but 0 or 1 depending on whether
-               * the broadcast address should set the bits of the host part
-               * to 0 or 1.
-               * Yes, I know it's stupid, but what can I say, it's MSFTs API.
-               */
-              curr->brdcast.sa4.sin_family = AF_INET;
-              if (tableP->table[i].dwBCastAddr == 1)
-                curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask);
-              else
-                curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask);
-              mask = ntohl(tableP->table[i].dwMask);
-              curr->mask = 0;
-              while (mask) {
-                mask <<= 1;
-                curr->mask++;
-              }
-              break;
+                /**
+                 * Contrary to what it seems to indicate, dwBCastAddr doesn't
+                 * contain the broadcast address but 0 or 1 depending on whether
+                 * the broadcast address should set the bits of the host part
+                 * to 0 or 1.
+                 * Yes, I know it's stupid, but what can I say, it's MSFTs API.
+                 */
+                curr->brdcast.sa4.sin_family = AF_INET;
+                if (tableP->table[i].dwBCastAddr == 1)
+                    curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask) | (0xffffffff ^ tableP->table[i].dwMask);
+                else
+                    curr->brdcast.sa4.sin_addr.s_addr = (tableP->table[i].dwAddr & tableP->table[i].dwMask);
+                mask = ntohl(tableP->table[i].dwMask);
+                curr->mask = 0;
+                while (mask) {
+                    mask <<= 1;
+                    curr->mask++;
+                }
+                break;
             case MIB_IF_TYPE_PPP:
             case MIB_IF_TYPE_SLIP:
             default:
-              /**
-               * these don't have broadcast/subnet
-               */
-              curr->mask = -1;
-                break;
+                /**
+                 * these don't have broadcast/subnet
+                 */
+                curr->mask = -1;
+                    break;
             }
 
             curr->next = netaddrP;
@@ -474,10 +483,30 @@
     }
 
     *netaddrPP = netaddrP;
+    return count;
+}
+
+
+/*
+ * Enumerate the IP addresses on an interface, using an IP address table
+ * retrieved using GetIPAddrTable and matching based on index.
+ *
+ * Returns the count of addresses, or -1 if error. If no error occurs then
+ * netaddrPP will return a list of netaddr structures with the IP addresses.
+ */
+int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) {
+    MIB_IPADDRTABLE *tableP;
+    int count;
+    int ret = lookupIPAddrTable(env, &tableP);
+    if (ret < 0) {
+      return NULL;
+    }
+    count = enumAddresses_win_ipaddrtable(env, netifP, netaddrPP, tableP);
     free(tableP);
     return count;
 }
 
+
 /*
  * Class:     java_net_NetworkInterface
  * Method:    init
@@ -758,6 +787,50 @@
     return netifObj;
 }
 
+
+/*
+ * Class:     java_net_NetworkInterface
+ * Method:    boundInetAddress0
+ * Signature: (Ljava/net/InetAddress;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0
+    (JNIEnv *env, jclass cls, jobject iaObj)
+{
+    jobject netifObj = NULL;
+    DWORD i;
+
+    int family = getInetAddress_family(env, iaObj);
+    JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+    if (family == java_net_InetAddress_IPv6) {
+        if (!ipv6_available())
+            return JNI_FALSE;
+        return Java_java_net_NetworkInterface_getByInetAddress0_XP(env, cls, iaObj) != NULL;
+    } else if (family == java_net_InetAddress_IPv4) {
+        jint addr = getInetAddress_addr(env, iaObj);
+        JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+        jboolean found = JNI_FALSE;
+        MIB_IPADDRTABLE *tableP;
+        if (lookupIPAddrTable(env, &tableP) >= 0 && tableP != NULL) {
+            for (i = 0; i < tableP->dwNumEntries; i++) {
+                if (tableP->table[i].dwAddr != 0 &&
+                    (unsigned long)addr == ntohl(tableP->table[i].dwAddr)) {
+                    found = JNI_TRUE;
+                    break;
+                }
+            }
+        }
+        if (tableP != NULL) {
+          free(tableP);
+        }
+        return found;
+    } else {
+      // Unknown address family
+      return JNI_FALSE;
+    }
+}
+
 /*
  * Class:     java_net_NetworkInterface
  * Method:    getByInetAddress0
@@ -767,11 +840,11 @@
     (JNIEnv *env, jclass cls, jobject iaObj)
 {
     netif *ifList, *curr;
+    MIB_IPADDRTABLE *tableP;
     jobject netifObj = NULL;
     jint addr = getInetAddress_addr(env, iaObj);
     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 
-    // Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
     if (ipv6_available()) {
         return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);
     }
@@ -785,42 +858,50 @@
      * Enumerate the addresses on each interface until we find a
      * matching address.
      */
-    curr = ifList;
-    while (curr != NULL) {
-        int count;
-        netaddr *addrList;
-        netaddr *addrP;
+    tableP = NULL;
+    if (lookupIPAddrTable(env, &tableP) >= 0) {
+        curr = ifList;
+        while (curr != NULL) {
+            int count;
+            netaddr *addrList;
+            netaddr *addrP;
+
+            /* enumerate the addresses on this interface */
+            count = enumAddresses_win_ipaddrtable(env, curr, &addrList, tableP);
+            if (count < 0) {
+                free_netif(ifList);
+                free(tableP);
+                return NULL;
+            }
 
-        /* enumerate the addresses on this interface */
-        count = enumAddresses_win(env, curr, &addrList);
-        if (count < 0) {
-            free_netif(ifList);
-            return NULL;
-        }
+            /* iterate through each address */
+            addrP = addrList;
 
-        /* iterate through each address */
-        addrP = addrList;
+            while (addrP != NULL) {
+                if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) {
+                    break;
+                }
+                addrP = addrP->next;
+            }
 
-        while (addrP != NULL) {
-            if ((unsigned long)addr == ntohl(addrP->addr.sa4.sin_addr.s_addr)) {
+            /*
+             * Address matched so create NetworkInterface for this interface
+             * and address list.
+             */
+            if (addrP != NULL) {
+                /* createNetworkInterface will free addrList */
+                netifObj = createNetworkInterface(env, curr, count, addrList);
                 break;
             }
-            addrP = addrP->next;
-        }
 
-        /*
-         * Address matched so create NetworkInterface for this interface
-         * and address list.
-         */
-        if (addrP != NULL) {
-            /* createNetworkInterface will free addrList */
-            netifObj = createNetworkInterface(env, curr, count, addrList);
-            break;
+            /* on next interface */
+            curr = curr->next;
         }
+    }
 
-        /* on next interface */
-        curr = curr->next;
-    }
+    /* release the IP address table */
+    if (tableP != NULL)
+        free(tableP);
 
     /* release the interface list */
     free_netif(ifList);
--- a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,9 @@
  * and getByAddress.
  */
 
+extern int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP);
 extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
+extern int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP);
 int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
 
 #ifdef DEBUG
@@ -239,6 +241,7 @@
 int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
 {
     DWORD ret;
+    MIB_IPADDRTABLE *tableP;
     IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL;
     ULONG len=ipinflen, count=0;
     netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr;
@@ -271,10 +274,15 @@
 
     // Retrieve IPv4 addresses with the IP Helper API
     curr = *netifPP;
+    ret = lookupIPAddrTable(env, &tableP);
+    if (ret < 0) {
+      return -1;
+    }
     while (curr != NULL) {
         netaddr *netaddrP;
-        ret = enumAddresses_win(env, curr, &netaddrP);
+        ret = enumAddresses_win_ipaddrtable(env, curr, &netaddrP, tableP);
         if (ret == -1) {
+            free(tableP);
             return -1;
         } else if (ret == -2) {
             if ((*env)->ExceptionCheck(env)) {
@@ -287,7 +295,7 @@
             curr = curr->next;
         }
     }
-
+    free(tableP);
     ret = getAdapters (env, &adapters);
     if (ret != ERROR_SUCCESS) {
         goto err;
--- a/src/java.management/share/classes/javax/management/remote/package.html	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.management/share/classes/javax/management/remote/package.html	Mon Jul 08 16:04:25 2019 +0530
@@ -67,7 +67,7 @@
         the optional part of the <em>JMX Remote API</em>
         are not included in the <em>Java SE Platform</em> 
         but are available from the <em>JMX Remote API 
-	<a href="http://java.sun.com/products/JavaManagement/download.html">
+	<a href="https://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html">
 	Reference Implementation</a></em>.</p>
 
 
--- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java	Mon Jul 08 16:04:25 2019 +0530
@@ -59,7 +59,6 @@
     private RequestPublishers() { }
 
     public static class ByteArrayPublisher implements BodyPublisher {
-        private volatile Flow.Publisher<ByteBuffer> delegate;
         private final int length;
         private final byte[] content;
         private final int offset;
@@ -99,7 +98,7 @@
         @Override
         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
             List<ByteBuffer> copy = copy(content, offset, length);
-            this.delegate = new PullPublisher<>(copy);
+            var delegate = new PullPublisher<>(copy);
             delegate.subscribe(subscriber);
         }
 
@@ -111,7 +110,6 @@
 
     // This implementation has lots of room for improvement.
     public static class IterablePublisher implements BodyPublisher {
-        private volatile Flow.Publisher<ByteBuffer> delegate;
         private final Iterable<byte[]> content;
         private volatile long contentLength;
 
@@ -174,7 +172,7 @@
         @Override
         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
             Iterable<ByteBuffer> iterable = this::iterator;
-            this.delegate = new PullPublisher<>(iterable);
+            var delegate = new PullPublisher<>(iterable);
             delegate.subscribe(subscriber);
         }
 
--- a/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java	Mon Jul 08 16:04:25 2019 +0530
@@ -128,8 +128,8 @@
  * <pre>
  *    // Create a context using default credentials
  *    // and the implementation specific default mechanism
- *    GSSManager manager ...
- *    GSSName targetName ...
+ *    GSSManager manager = ...
+ *    GSSName targetName = ...
  *    GSSContext context = manager.createContext(targetName, null, null,
  *                                           GSSContext.INDEFINITE_LIFETIME);
  *
@@ -141,21 +141,23 @@
  *
  *    // establish a context between peers
  *
- *    byte []inToken = new byte[0];
+ *    byte[] inToken = new byte[0];
+ *    byte[] outToken;
  *
  *    // Loop while there still is a token to be processed
  *
  *    while (!context.isEstablished()) {
  *
- *        byte[] outToken
- *            = context.initSecContext(inToken, 0, inToken.length);
+ *        outToken = context.initSecContext(inToken, 0, inToken.length);
  *
  *        // send the output token if generated
- *        if (outToken != null)
+ *        if (outToken != null) {
  *            sendToken(outToken);
+ *        }
  *
  *        if (!context.isEstablished()) {
  *            inToken = readToken();
+ *        }
  *    }
  *
  *     // display context information
@@ -165,21 +167,40 @@
  *     System.out.println("Initiator = " + context.getSrcName());
  *     System.out.println("Acceptor = " + context.getTargName());
  *
- *     if (context.getConfState())
- *             System.out.println("Confidentiality (i.e., privacy) is available");
+ *     if (context.getConfState()) {
+ *         System.out.println("Confidentiality (i.e., privacy) is available");
+ *     }
  *
- *     if (context.getIntegState())
- *             System.out.println("Integrity is available");
+ *     if (context.getIntegState()) {
+ *         System.out.println("Integrity is available");
+ *     }
  *
  *     // perform wrap on an application supplied message, appMsg,
  *     // using QOP = 0, and requesting privacy service
- *     byte [] appMsg ...
+ *     byte[] appMsg = ...
  *
  *     MessageProp mProp = new MessageProp(0, true);
  *
- *     byte []tok = context.wrap(appMsg, 0, appMsg.length, mProp);
+ *     outToken = context.wrap(appMsg, 0, appMsg.length, mProp);
+ *
+ *     sendToken(outToken);
+ *
+ *     // perform unwrap on an incoming application message, and check
+ *     // its privacy state and supplementary information
+ *     inToken = readToken();
+ *
+ *     mProp = new MessageProp(0, true);
  *
- *     sendToken(tok);
+ *     appMsg = context.unwrap(inToken, 0, inToken.length, mProp);
+ *
+ *     System.out.println("Was it encrypted? " + mProp.getPrivacy());
+ *     System.out.println("Duplicate Token? " + mProp.isDuplicateToken());
+ *     System.out.println("Old Token? " + mProp.isOldToken());
+ *     System.out.println("Unsequenced Token? " + mProp.isUnseqToken());
+ *     System.out.println("Gap Token? " + mProp.isGapToken());
+ *
+ *     // the application determines if the privacy state and supplementary
+ *     // information are acceptable
  *
  *     // release the local-end of the context
  *     context.dispose();
--- a/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java	Mon Jul 08 16:04:25 2019 +0530
@@ -197,6 +197,26 @@
             usage);
     }
 
+    // ===============  ATTENTION! Use with care  ==================
+    // According to https://tools.ietf.org/html/rfc3961#section-6.1,
+    // An unkeyed checksum should only be used "in limited circumstances
+    // where the lack of a key does not provide a window for an attack,
+    // preferably as part of an encrypted message".
+    public boolean verifyAnyChecksum(byte[] data, EncryptionKey key,
+            int usage)
+            throws KdcErrException, KrbCryptoException {
+        CksumType cksumEngine = CksumType.getInstance(cksumType);
+        if (!cksumEngine.isSafe()) {
+            return cksumEngine.verifyChecksum(data, checksum);
+        } else {
+            return cksumEngine.verifyKeyedChecksum(data,
+                    data.length,
+                    key.getBytes(),
+                    checksum,
+                    usage);
+        }
+    }
+
     /*
     public Checksum(byte[] data) throws KdcErrException, KrbCryptoException {
         this(Checksum.CKSUMTYPE_DEFAULT, data);
--- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java	Mon Jul 08 16:04:25 2019 +0530
@@ -158,8 +158,10 @@
                             Checksum repCksum = new Checksum(
                                     new DerInputStream(
                                             pa.getValue()).getDerValue());
+                            // The checksum is inside encKDCRepPart so we don't
+                            // care if it's keyed or not.
                             repPaReqEncPaRepValid =
-                                    repCksum.verifyKeyedChecksum(
+                                    repCksum.verifyAnyChecksum(
                                             req.asn1Encode(), replyKey,
                                             KeyUsage.KU_AS_REQ);
                         } catch (Exception e) {
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/CksumType.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/CksumType.java	Mon Jul 08 16:04:25 2019 +0530
@@ -156,6 +156,11 @@
     public abstract byte[] calculateKeyedChecksum(byte[] data, int size,
         byte[] key, int usage) throws KrbCryptoException;
 
+    public boolean verifyChecksum(byte[] data, byte[] checksum)
+            throws KrbCryptoException {
+        throw new UnsupportedOperationException("Not supported");
+    }
+
     public abstract boolean verifyKeyedChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException;
 
--- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java	Mon Jul 08 16:04:25 2019 +0530
@@ -101,4 +101,14 @@
         return false;
     }
 
+    @Override
+    public boolean verifyChecksum(byte[] data, byte[] checksum)
+            throws KrbCryptoException {
+        try {
+            byte[] calculated = MessageDigest.getInstance("MD5").digest(data);
+            return CksumType.isChecksumEqual(calculated, checksum);
+        } catch (Exception e) {
+            return false;
+        }
+    }
 }
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -40,7 +40,7 @@
  * because it is used from another package.
  *
  * @xsl.usage internal
- * @LastModified: Sept 2018
+ * @LastModified: July 2019
  */
 public final class ToHTMLStream extends ToStream
 {
@@ -719,7 +719,7 @@
     public final void endDocument() throws org.xml.sax.SAXException
     {
         if (m_doIndent) {
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         flushPending();
         if (m_doIndent && !m_isprevtext)
@@ -782,7 +782,7 @@
         if (m_doIndent) {
             // will add extra one if having namespace but no matter
             m_childNodeNum++;
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         ElemContext elemContext = m_elemContext;
 
@@ -923,7 +923,7 @@
         throws org.xml.sax.SAXException
     {
         if (m_doIndent) {
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         // deal with any pending issues
         if (m_cdataTagOpen)
@@ -1645,7 +1645,7 @@
     {
         if (m_doIndent) {
             m_childNodeNum++;
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         // Process any pending starDocument and startElement first.
         flushPending();
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -51,7 +51,7 @@
  * serializers (xml, html, text ...) that write output to a stream.
  *
  * @xsl.usage internal
- * @LastModified: Sept 2018
+ * @LastModified: July 2019
  */
 abstract public class ToStream extends SerializerBase {
 
@@ -1231,7 +1231,7 @@
                 m_elemContext.m_startTagOpen = false;
             }
 
-            if (!m_cdataTagOpen && shouldIndent())
+            if (!m_cdataTagOpen && shouldIndentForText())
                 indent();
 
             boolean writeCDataBrackets =
@@ -1270,6 +1270,7 @@
                     closeCDATA();
             }
 
+            m_isprevtext = true;
             // time to fire off CDATA event
             if (m_tracer != null)
                 super.fireCDATAEvent(ch, old_start, length);
@@ -1536,11 +1537,13 @@
     }
 
     /**
-     * Used to flush the buffered characters when indentation is on, this method
-     * will be called when the next node is traversed.
+     * Flushes the buffered characters when indentation is on. This method
+     * is called before the next node is traversed.
      *
+     * @param isText indicates whether the node to be traversed is text
+     * @throws org.xml.sax.SAXException
      */
-    final protected void flushCharactersBuffer() throws SAXException {
+    final protected void flushCharactersBuffer(boolean isText) throws SAXException {
         try {
             if (shouldFormatOutput() && m_charactersBuffer.isAnyCharactersBuffered()) {
                 if (m_elemContext.m_isCdataSection) {
@@ -1553,7 +1556,9 @@
                     return;
                 }
 
-                m_childNodeNum++;
+                if (!isText) {
+                    m_childNodeNum++;
+                }
                 boolean skipBeginningNewlines = false;
                 if (shouldIndentForText()) {
                     indent();
@@ -1846,7 +1851,7 @@
 
         if (m_doIndent) {
             m_childNodeNum++;
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
 
         if (m_needToCallStartDocument)
@@ -2117,7 +2122,7 @@
             return;
 
         if (m_doIndent) {
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         // namespaces declared at the current depth are no longer valid
         // so get rid of them
@@ -2309,7 +2314,7 @@
             return;
         if (m_doIndent) {
             m_childNodeNum++;
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         if (m_elemContext.m_startTagOpen)
         {
@@ -2491,8 +2496,7 @@
     public void startCDATA() throws org.xml.sax.SAXException
     {
         if (m_doIndent) {
-            m_childNodeNum++;
-            flushCharactersBuffer();
+            flushCharactersBuffer(true);
         }
 
         m_cdataStartCalled = true;
--- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -40,6 +40,7 @@
  * be viewed as internal or package private, this is not an API.
  *
  * @xsl.usage internal
+ * @LastModified: July 2019
  */
 public final class ToXMLStream extends ToStream
 {
@@ -200,7 +201,7 @@
     public void endDocument() throws org.xml.sax.SAXException
     {
         if (m_doIndent) {
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         flushPending();
         if (m_doIndent && !m_isprevtext)
@@ -267,7 +268,7 @@
 
         if (m_doIndent) {
             m_childNodeNum++;
-            flushCharactersBuffer();
+            flushCharactersBuffer(false);
         }
         flushPending();
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1447,6 +1447,9 @@
         if (tree.cases.isEmpty()) {
             log.error(tree.pos(),
                       Errors.SwitchExpressionEmpty);
+        } else if (caseTypes.isEmpty()) {
+            log.error(tree.pos(),
+                      Errors.SwitchExpressionNoResultExpressions);
         }
 
         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(caseTypePositions.toList(), caseTypes.toList()) : pt();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Jul 08 16:04:25 2019 +0530
@@ -299,6 +299,8 @@
         if (chk.checkUnique(tree.pos(), v, enclScope)) {
             chk.checkTransparentVar(tree.pos(), v, enclScope);
             enclScope.enter(v);
+        } else if (v.owner.kind == MTH) {
+            enclScope.enter(v);
         }
 
         annotate.annotateLater(tree.mods.annotations, localEnv, v, tree.pos());
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Jul 08 16:04:25 2019 +0530
@@ -775,9 +775,9 @@
 
     public JCExpression unannotatedType(boolean allowVar) {
         JCExpression result = term(TYPE);
-        Name restrictedTypeName;
-
-        if (!allowVar && (restrictedTypeName = restrictedTypeName(result, true)) != null) {
+        Name restrictedTypeName = restrictedTypeName(result, !allowVar);
+
+        if (restrictedTypeName != null && (!allowVar || restrictedTypeName != names.var)) {
             syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Jul 08 16:04:25 2019 +0530
@@ -223,6 +223,9 @@
 compiler.err.switch.expression.empty=\
     switch expression does not have any case clauses
 
+compiler.err.switch.expression.no.result.expressions=\
+    switch expression does not have any result expressions
+
 # 0: name
 compiler.err.call.must.be.first.stmt.in.ctor=\
     call to {0} must be first statement in constructor
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java	Mon Jul 08 16:04:25 2019 +0530
@@ -395,33 +395,49 @@
                 ("Unsupported digest algorithm in Signature parameters: " +
                  digestAlgorithm);
         }
+
         if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
             throw new InvalidAlgorithmParameterException("Only supports MGF1");
         }
+
+        // defaults to the digest algorithm unless overridden
+        String mgfDigestAlgo = digestAlgorithm;
+        AlgorithmParameterSpec mgfParams = params.getMGFParameters();
+        if (mgfParams != null) {
+            if (!(mgfParams instanceof MGF1ParameterSpec)) {
+                throw new InvalidAlgorithmParameterException
+                        ("Only MGF1ParameterSpec is supported");
+            }
+            mgfDigestAlgo = ((MGF1ParameterSpec)mgfParams).getDigestAlgorithm();
+        }
+
         if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
             throw new InvalidAlgorithmParameterException
                 ("Only supports TrailerFieldBC(1)");
         }
+
         int saltLen = params.getSaltLength();
         if (this.p11Key != null) {
-            int maxSaltLen = ((this.p11Key.length() + 7) >> 3) - digestLen.intValue() - 2;
+            int maxSaltLen = ((this.p11Key.length() + 7) >> 3) -
+                    digestLen.intValue() - 2;
 
             if (DEBUG) {
                 System.out.println("Max saltLen = " + maxSaltLen);
                 System.out.println("Curr saltLen = " + saltLen);
             }
             if (maxSaltLen < 0 || saltLen > maxSaltLen) {
-                throw new InvalidAlgorithmParameterException("Invalid with current key size");
+                throw new InvalidAlgorithmParameterException
+                        ("Invalid with current key size");
             }
-        } else {
-            if (DEBUG) System.out.println("No key available for validating saltLen");
+        } else if (DEBUG) {
+            System.out.println("No key available for validating saltLen");
         }
 
         // validated, now try to store the parameter internally
         try {
             this.mechanism.setParameter(
                     new CK_RSA_PKCS_PSS_PARAMS(digestAlgorithm, "MGF1",
-                        digestAlgorithm, saltLen));
+                            mgfDigestAlgo, saltLen));
             this.sigParams = params;
         } catch (IllegalArgumentException iae) {
             throw new InvalidAlgorithmParameterException(iae);
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_RSA_PKCS_PSS_PARAMS.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_RSA_PKCS_PSS_PARAMS.java	Mon Jul 08 16:04:25 2019 +0530
@@ -57,7 +57,7 @@
             throw new ProviderException("Only MGF1 is supported");
         }
         // no dash in PKCS#11 mechanism names
-        this.mgf = Functions.getMGFId("CKG_MGF1_" + hashAlg.replaceFirst("-", ""));
+        this.mgf = Functions.getMGFId("CKG_MGF1_" + mgfHash.replaceFirst("-", ""));
         this.sLen = sLen;
     }
 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Mon Jul 08 16:04:25 2019 +0530
@@ -475,7 +475,9 @@
                 methodData = new HotSpotMethodData(metaspaceMethodData, this);
                 String methodDataFilter = Option.TraceMethodDataFilter.getString();
                 if (methodDataFilter != null && this.format("%H.%n").contains(methodDataFilter)) {
-                    System.out.println(methodData.toString());
+                    String line = methodData.toString() + System.lineSeparator();
+                    byte[] lineBytes = line.getBytes();
+                    CompilerToVM.compilerToVM().writeDebugOutput(lineBytes, 0, lineBytes.length, true, true);
                 }
             }
         }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Mon Jul 08 16:04:25 2019 +0530
@@ -573,6 +573,10 @@
             // The type isn't known to implement the method.
             return null;
         }
+        if (resolvedMethod.canBeStaticallyBound()) {
+            // No assumptions are required.
+            return new AssumptionResult<>(resolvedMethod);
+        }
 
         if (resolvedMethod.canBeStaticallyBound()) {
             // No assumptions are required.
@@ -833,10 +837,8 @@
             // Primitive type resolution is context free.
             return true;
         }
-        if (elementType.getName().startsWith("Ljava/")) {
-            // Classes in a java.* package can only be defined by the
-            // boot class loader. This is enforced by ClassLoader.preDefineClass()
-            assert hasSameClassLoader(runtime().getJavaLangObject());
+        if (elementType.getName().startsWith("Ljava/") && hasSameClassLoader(runtime().getJavaLangObject())) {
+            // Classes in a java.* package defined by the boot class loader are always resolved.
             return true;
         }
         HotSpotResolvedObjectTypeImpl otherMirror = ((HotSpotResolvedObjectTypeImpl) accessingClass);
--- a/test/hotspot/jtreg/ProblemList-aot.txt	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/ProblemList-aot.txt	Mon Jul 08 16:04:25 2019 +0530
@@ -72,3 +72,11 @@
 serviceability/sa/TestRevPtrsForInvokeDynamic.java      8216181   generic-all
 serviceability/sa/TestType.java                         8216181   generic-all
 serviceability/sa/TestUniverse.java                     8216181   generic-all
+
+compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java  8167430 generic-all
+compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java              8167430 generic-all
+compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java            8167430 generic-all
+compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java            8167430 generic-all
+compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java    8167430 generic-all
+compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java  8167430 generic-all
+
--- a/test/hotspot/jtreg/TEST.groups	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/TEST.groups	Mon Jul 08 16:04:25 2019 +0530
@@ -328,6 +328,7 @@
  -runtime/appcds/ExtraSymbols.java \
  -runtime/appcds/LongClassListPath.java \
  -runtime/appcds/LotsOfClasses.java \
+ -runtime/appcds/RelativePath.java \
  -runtime/appcds/SharedArchiveConsistency.java \
  -runtime/appcds/UnusedCPDuringDump.java \
  -runtime/appcds/VerifierTest_1B.java
--- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java	Mon Jul 08 16:04:25 2019 +0530
@@ -113,7 +113,7 @@
             procArgs = new String[argcount];
             procArgs[argcount - 4] = "-XX:+UnlockExperimentalVMOptions";
             procArgs[argcount - 3] = "-XX:+UseShenandoahGC";
-            procArgs[argcount - 2] = "-XX:ShenandoahGCHeuristics=traversal";
+            procArgs[argcount - 2] = "-XX:ShenandoahGCMode=traversal";
             break;
         default:
             throw new RuntimeException("unexpected test type " + testType);
--- a/test/hotspot/jtreg/gc/CriticalNativeArgs.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/CriticalNativeArgs.java	Mon Jul 08 16:04:25 2019 +0530
@@ -40,13 +40,14 @@
  * @library /
  * @requires (os.arch =="x86_64" | os.arch == "amd64") & vm.gc.Shenandoah & !vm.graal.enabled
  * @summary test argument unpacking nmethod wrapper of critical native method
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive    -XX:+ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive    -XX:-ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive    -XX:+ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive    -XX:-ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
  *
  * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
  *
  * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC                                                                        -Xcomp -Xmx256M -XX:+CriticalJNINatives gc.CriticalNativeArgs
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCHeuristics=traversal  -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=traversal        -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.CriticalNativeArgs
  */
 public class CriticalNativeArgs {
     public static void main(String[] args) {
--- a/test/hotspot/jtreg/gc/shenandoah/TestAllocHumongousFragment.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestAllocHumongousFragment.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,22 +27,105 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=passive    -XX:-ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=passive    -XX:+ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=passive    -XX:-ShenandoahDegeneratedGC                           TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=passive    -XX:+ShenandoahDegeneratedGC                           TestAllocHumongousFragment
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestAllocHumongousFragment
+ */
+
+/*
+ * @test TestAllocHumongousFragment
+ * @summary Make sure Shenandoah can recover from humongous allocation fragmentation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocHumongousFragment
  *
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahAllocFailureALot  -XX:+ShenandoahVerify TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahOOMDuringEvacALot                       TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahAllocFailureALot                        TestAllocHumongousFragment
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xmx1g -Xms1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestAllocHumongousFragment
+ */
+
+/*
+ * @test TestAllocHumongousFragment
+ * @summary Make sure Shenandoah can recover from humongous allocation fragmentation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestAllocHumongousFragment
+ * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
  *
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=adaptive     TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=static       TestAllocHumongousFragment
- * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048 -XX:ShenandoahGCHeuristics=traversal    TestAllocHumongousFragment
+ * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestAllocHumongousFragment
+ *
+ * @run main/othervm -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g -XX:ShenandoahTargetNumRegions=2048
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestAllocHumongousFragment
  */
 
 import java.util.*;
--- a/test/hotspot/jtreg/gc/shenandoah/TestAllocIntArrays.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestAllocIntArrays.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,26 +27,118 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC                           TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC                           TestAllocIntArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestAllocIntArrays
+ */
+
+/*
+ * @test TestAllocIntArrays
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot  -XX:+ShenandoahVerify TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot                       TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot                        TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive                                                          TestAllocIntArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseTLAB -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ */
+
+/*
+ * @test TestAllocIntArrays
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestAllocIntArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocIntArrays
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive                           TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal                          TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static                             TestAllocIntArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact                            TestAllocIntArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestAllocIntArrays
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:-UseTLAB                            -XX:+ShenandoahVerify TestAllocIntArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestAllocIntArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestAllocIntArrays
  */
 
 import java.util.Random;
--- a/test/hotspot/jtreg/gc/shenandoah/TestAllocObjectArrays.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestAllocObjectArrays.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,26 +27,117 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC                           TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC                           TestAllocObjectArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestAllocObjectArrays
+
+/*
+ * @test TestAllocObjectArrays
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot  -XX:+ShenandoahVerify TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot                       TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot                        TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive                                                          TestAllocObjectArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseTLAB -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ */
+
+/*
+ * @test TestAllocObjectArrays
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestAllocObjectArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocObjectArrays
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static       TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact      TestAllocObjectArrays
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    TestAllocObjectArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestAllocObjectArrays
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:-UseTLAB                            -XX:+ShenandoahVerify TestAllocObjectArrays
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestAllocObjectArrays
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx1g -Xms1g
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestAllocObjectArrays
  */
 
 import java.util.Random;
--- a/test/hotspot/jtreg/gc/shenandoah/TestAllocObjects.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestAllocObjects.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,30 +27,138 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC     -XX:+ShenandoahVerify TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC                           TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC                           TestAllocObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestAllocObjects
+ */
+
+/*
+ * @test TestAllocObjects
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot  -XX:+ShenandoahVerify TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot                       TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot                        TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive                                                          TestAllocObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahSuspendibleWorkers
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestAllocObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestAllocObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahSuspendibleWorkers
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      -XX:+ShenandoahSuspendibleWorkers
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -XX:+ShenandoahSuspendibleWorkers
+ *      TestAllocObjects
+ */
+
+/*
+ * @test TestAllocObjects
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static       TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact      TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    TestAllocObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestAllocObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive   -XX:+ShenandoahSuspendibleWorkers TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static     -XX:+ShenandoahSuspendibleWorkers TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact    -XX:+ShenandoahSuspendibleWorkers TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal  -XX:+ShenandoahSuspendibleWorkers TestAllocObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahSuspendibleWorkers TestAllocObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestAllocObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahSuspendibleWorkers
+ *      TestAllocObjects
  */
 
 import java.util.Random;
--- a/test/hotspot/jtreg/gc/shenandoah/TestEvilSyncBug.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestEvilSyncBug.java	Mon Jul 08 16:04:25 2019 +0530
@@ -61,7 +61,6 @@
                             "-XX:+UnlockDiagnosticVMOptions",
                             "-XX:+UseShenandoahGC",
                             "-XX:ShenandoahGCHeuristics=aggressive",
-                            "-XX:+ShenandoahStoreCheck",
                             "TestEvilSyncBug", "test");
                     OutputAnalyzer output = new OutputAnalyzer(pb.start());
                     output.shouldHaveExitValue(0);
--- a/test/hotspot/jtreg/gc/shenandoah/TestGCThreadGroups.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestGCThreadGroups.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,21 +27,121 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m                                         -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:-UseDynamicNumberOfGCThreads            -Xmx16m                                         -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UnlockDiagnosticVMOptions -XX:+ForceDynamicNumberOfGCThreads -Xmx16m                   -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m -XX:ShenandoahGCHeuristics=passive      -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m -XX:ShenandoahGCHeuristics=adaptive     -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m -XX:ShenandoahGCHeuristics=static       -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m -XX:ShenandoahGCHeuristics=compact      -Dtarget=100  TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m -XX:ShenandoahGCHeuristics=aggressive   -Dtarget=100  TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4 -Xmx16m -XX:ShenandoahGCHeuristics=traversal    -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2 -Xmx16m -XX:ShenandoahGCHeuristics=passive      -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2 -Xmx16m -XX:ShenandoahGCHeuristics=adaptive     -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2 -Xmx16m -XX:ShenandoahGCHeuristics=static       -Dtarget=1000 TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2 -Xmx16m -XX:ShenandoahGCHeuristics=compact      -Dtarget=100  TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2 -Xmx16m -XX:ShenandoahGCHeuristics=aggressive   -Dtarget=100  TestGCThreadGroups
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2 -Xmx16m -XX:ShenandoahGCHeuristics=traversal    -Dtarget=1000 TestGCThreadGroups
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ */
+
+/**
+ * @test TestGCThreadGroups
+ * @summary Test Shenandoah GC uses concurrent/parallel threads correctly
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseDynamicNumberOfGCThreads
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:+ForceDynamicNumberOfGCThreads
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=100
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=100
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=100
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=100
+ *      TestGCThreadGroups
+ */
+
+/**
+ * @test TestGCThreadGroups
+ * @summary Test Shenandoah GC uses concurrent/parallel threads correctly
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:ConcGCThreads=2 -XX:ParallelGCThreads=4
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
+ *
+ * @run main/othervm -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:ConcGCThreads=4 -XX:ParallelGCThreads=2
+ *      -Dtarget=1000
+ *      TestGCThreadGroups
 */
 
 public class TestGCThreadGroups {
--- a/test/hotspot/jtreg/gc/shenandoah/TestHeapUncommit.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestHeapUncommit.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,34 +27,98 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=passive                 -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=passive                 -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=passive                 -XX:+ShenandoahDegeneratedGC                       TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=passive                 -XX:-ShenandoahDegeneratedGC                       TestHeapUncommit
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestHeapUncommit
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0                                                    -XX:+ShenandoahVerify TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=adaptive                -XX:+ShenandoahVerify TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=static                  -XX:+ShenandoahVerify TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=traversal               -XX:+ShenandoahVerify TestHeapUncommit
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestHeapUncommit
+ */
+
+/*
+ * @test TestHeapUncommit
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestHeapUncommit
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:-UseTLAB                                       -XX:+ShenandoahVerify TestHeapUncommit
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestHeapUncommit
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0                                                    TestHeapUncommit
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseTLAB -XX:+ShenandoahVerify
+ *      TestHeapUncommit
+ */
 
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=adaptive                TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=static                  TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=compact                 TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=aggressive              TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:ShenandoahGCHeuristics=traversal               TestHeapUncommit
+/*
+ * @test TestHeapUncommit
+ * @summary Acceptance tests: collector can withstand allocation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestHeapUncommit
  */
 
 /*
  * @test TestHeapUncommit
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled & (vm.bits == "64")
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0               -XX:+UseLargePages -XX:+ShenandoahVerify TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0               -XX:+UseLargePages                       TestHeapUncommit
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:-UseTLAB  -XX:+UseLargePages -XX:+ShenandoahVerify TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:+UseLargePages
+ *      -XX:+UseShenandoahGC
+ *      -XX:+ShenandoahVerify
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:+UseLargePages
+ *      -XX:+UseShenandoahGC
+ *      TestHeapUncommit
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahUncommit -XX:ShenandoahUncommitDelay=0 -XX:+UseLargePages
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseTLAB -XX:+ShenandoahVerify
+ *      TestHeapUncommit
  */
 
 import java.util.Random;
--- a/test/hotspot/jtreg/gc/shenandoah/TestLotsOfCycles.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestLotsOfCycles.java	Mon Jul 08 16:04:25 2019 +0530
@@ -26,18 +26,83 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=passive      -Dtarget=10000 -XX:+ShenandoahDegeneratedGC     TestLotsOfCycles
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=passive      -Dtarget=10000 -XX:-ShenandoahDegeneratedGC     TestLotsOfCycles
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      -Dtarget=10000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      -Dtarget=10000
+ *      TestLotsOfCycles
+ */
+
+/*
+ * @test TestLotsOfCycles
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      -Dtarget=1000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      -Dtarget=1000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -Dtarget=1000
+ *      TestLotsOfCycles
  *
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=aggressive   -Dtarget=1000  -XX:+ShenandoahOOMDuringEvacALot TestLotsOfCycles
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=aggressive   -Dtarget=1000  -XX:+ShenandoahAllocFailureALot  TestLotsOfCycles
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=aggressive   -Dtarget=1000                                   TestLotsOfCycles
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -Dtarget=10000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      -Dtarget=10000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -Dtarget=1000
+ *     TestLotsOfCycles
+ */
+
+/*
+ * @test TestLotsOfCycles
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=adaptive     -Dtarget=10000 TestLotsOfCycles
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=traversal    -Dtarget=10000 TestLotsOfCycles
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      -Dtarget=1000
+ *      TestLotsOfCycles
  *
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=static       -Dtarget=10000 TestLotsOfCycles
- * @run main/othervm/timeout=480 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx16m -XX:ShenandoahGCHeuristics=compact      -Dtarget=1000  TestLotsOfCycles
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      -Dtarget=1000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -Dtarget=1000
+ *      TestLotsOfCycles
+ *
+ * @run main/othervm/timeout=480 -Xmx16m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -Dtarget=10000
+ *      TestLotsOfCycles
  */
 
 public class TestLotsOfCycles {
--- a/test/hotspot/jtreg/gc/shenandoah/TestObjItrWithHeapDump.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestObjItrWithHeapDump.java	Mon Jul 08 16:04:25 2019 +0530
@@ -55,25 +55,27 @@
             System.exit(0);
         }
 
-        String[] heuristics = new String[] {
-                "adaptive",
-                "compact",
-                "static",
-                "aggressive",
-                "passive",
-                "traversal",
+        String[][][] modeHeuristics = new String[][][] {
+             {{"normal"},    {"adaptive", "compact", "static", "aggressive"}},
+             {{"traversal"}, {"adaptive", "aggressive"}},
+             {{"passive"},   {"passive"}}
         };
 
-        for (String h : heuristics) {
-            testWith("-XX:+UnlockDiagnosticVMOptions",
-                     "-XX:+UnlockExperimentalVMOptions",
-                     "-XX:+UseShenandoahGC",
-                     "-XX:-ShenandoahDegeneratedGC",
-                     "-XX:ShenandoahGCHeuristics=" + h,
-                     "-Xlog:gc+classhisto=trace",
-                     "-XX:-ExplicitGCInvokesConcurrent",
-                     "-Xmx512M"
-            );
+        for (String[][] mh : modeHeuristics) {
+            String mode = mh[0][0];
+            String[] heuristics = mh[1];
+            for (String h : heuristics) {
+                testWith("-XX:+UnlockDiagnosticVMOptions",
+                         "-XX:+UnlockExperimentalVMOptions",
+                         "-XX:+UseShenandoahGC",
+                         "-XX:-ShenandoahDegeneratedGC",
+                         "-XX:ShenandoahGCMode=" + mode,
+                         "-XX:ShenandoahGCHeuristics=" + h,
+                         "-Xlog:gc+classhisto=trace",
+                         "-XX:-ExplicitGCInvokesConcurrent",
+                         "-Xmx512M"
+                );
+            }
         }
     }
 }
--- a/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java	Mon Jul 08 16:04:25 2019 +0530
@@ -64,12 +64,6 @@
                 "adaptive",
                 "compact",
                 "static",
-                "traversal",
-        };
-
-        String[] disabled = new String[] {
-                "aggressive",
-                "passive",
         };
 
         for (String h : enabled) {
@@ -94,17 +88,44 @@
             );
         }
 
-        for (String h : disabled) {
-            testWith("Short period with " + h,
-                    false,
-                    "-Xlog:gc",
-                    "-XX:+UnlockDiagnosticVMOptions",
-                    "-XX:+UnlockExperimentalVMOptions",
-                    "-XX:+UseShenandoahGC",
-                    "-XX:ShenandoahGCHeuristics=" + h,
-                    "-XX:ShenandoahGuaranteedGCInterval=1000"
-            );
-        }
+        testWith("Short period with traversal mode",
+                 true,
+                 "-Xlog:gc",
+                 "-XX:+UnlockDiagnosticVMOptions",
+                 "-XX:+UnlockExperimentalVMOptions",
+                 "-XX:+UseShenandoahGC",
+                 "-XX:ShenandoahGCMode=traversal",
+                 "-XX:ShenandoahGuaranteedGCInterval=1000"
+        );
+
+        testWith("Long period with traversal mode",
+                 false,
+                 "-Xlog:gc",
+                 "-XX:+UnlockDiagnosticVMOptions",
+                 "-XX:+UnlockExperimentalVMOptions",
+                 "-XX:+UseShenandoahGC",
+                 "-XX:ShenandoahGCMode=traversal",
+                 "-XX:ShenandoahGuaranteedGCInterval=100000" // deliberately too long
+        );
+
+        testWith("Short period with aggressive",
+                 false,
+                 "-Xlog:gc",
+                 "-XX:+UnlockDiagnosticVMOptions",
+                 "-XX:+UnlockExperimentalVMOptions",
+                 "-XX:+UseShenandoahGC",
+                 "-XX:ShenandoahGCHeuristics=aggressive",
+                 "-XX:ShenandoahGuaranteedGCInterval=1000"
+        );
+        testWith("Short period with passive",
+                 false,
+                 "-Xlog:gc",
+                 "-XX:+UnlockDiagnosticVMOptions",
+                 "-XX:+UnlockExperimentalVMOptions",
+                 "-XX:+UseShenandoahGC",
+                 "-XX:ShenandoahGCMode=passive",
+                 "-XX:ShenandoahGuaranteedGCInterval=1000"
+        );
     }
 
 }
--- a/test/hotspot/jtreg/gc/shenandoah/TestRefprocSanity.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestRefprocSanity.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,11 +27,38 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g                                                             TestRefprocSanity
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:+ShenandoahVerify                                       TestRefprocSanity
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g                       -XX:ShenandoahGCHeuristics=aggressive TestRefprocSanity
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:+ShenandoahVerify -XX:ShenandoahGCHeuristics=traversal  TestRefprocSanity
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g                       -XX:ShenandoahGCHeuristics=traversal  TestRefprocSanity
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:+ShenandoahVerify
+ *      TestRefprocSanity
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      TestRefprocSanity
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestRefprocSanity
+ */
+
+/*
+ * @test TestRefprocSanity
+ * @summary Test that null references/referents work fine
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestRefprocSanity
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestRefprocSanity
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestRefprocSanity
  */
 
 import java.lang.ref.*;
--- a/test/hotspot/jtreg/gc/shenandoah/TestRegionSampling.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestRegionSampling.java	Mon Jul 08 16:04:25 2019 +0530
@@ -25,16 +25,50 @@
  * @test TestRegionSampling
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g                                         -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static       -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact      -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahRegionSampling TestRegionSampling
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestRegionSampling
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestRegionSampling
+ */
+
+/*
+ * @test TestRegionSampling
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestRegionSampling
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahRegionSampling TestRegionSampling
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahRegionSampling TestRegionSampling
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestRegionSampling
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestRegionSampling
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestRegionSampling
+ */
+
+/*
+ * @test TestRegionSampling
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestRegionSampling
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ShenandoahRegionSampling
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestRegionSampling
+ *
  */
 
 public class TestRegionSampling {
--- a/test/hotspot/jtreg/gc/shenandoah/TestRetainObjects.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestRetainObjects.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,24 +27,98 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC                       TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC                       TestRetainObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestRetainObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot  TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive                                    TestRetainObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestRetainObjects
+ */
+
+/*
+ * @test TestRetainObjects
+ * @summary Acceptance tests: collector can deal with retained objects
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestRetainObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestRetainObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestRetainObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static       TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact      TestRetainObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    TestRetainObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseTLAB -XX:+ShenandoahVerify
+ *      TestRetainObjects
+ */
+
+/*
+ * @test TestRetainObjects
+ * @summary Acceptance tests: collector can deal with retained objects
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestRetainObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:-UseTLAB                            -XX:+ShenandoahVerify TestRetainObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestRetainObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestRetainObjects
  */
 
 public class TestRetainObjects {
--- a/test/hotspot/jtreg/gc/shenandoah/TestSieveObjects.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestSieveObjects.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,24 +27,98 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC                       TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC                       TestSieveObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestSieveObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahOOMDuringEvacALot TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive   -XX:+ShenandoahAllocFailureALot  TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=aggressive                                    TestSieveObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestSieveObjects
+ */
+
+/*
+ * @test TestSieveObjects
+ * @summary Acceptance tests: collector can deal with retained objects
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestSieveObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestSieveObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestSieveObjects
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=adaptive     TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=static       TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=compact      TestSieveObjects
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:ShenandoahGCHeuristics=traversal    TestSieveObjects
+ * @run main/othervm/timeout=240 -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:-UseTLAB -XX:+ShenandoahVerify
+ *      TestSieveObjects
+ */
+
+/*
+ * @test TestSieveObjects
+ * @summary Acceptance tests: collector can deal with retained objects
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      TestSieveObjects
  *
- * @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -Xms1g -XX:-UseTLAB                -XX:+ShenandoahVerify TestSieveObjects
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestSieveObjects
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestSieveObjects
  */
 
 import java.util.concurrent.ThreadLocalRandom;
--- a/test/hotspot/jtreg/gc/shenandoah/TestStringDedup.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestStringDedup.java	Mon Jul 08 16:04:25 2019 +0530
@@ -21,7 +21,28 @@
  *
  */
 
- /*
+/*
+ * @test TestStringDedup
+ * @summary Test Shenandoah string deduplication implementation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ *
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestStringDedup
+ *
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestStringDedup
+ */
+
+/*
  * @test TestStringDedup
  * @summary Test Shenandoah string deduplication implementation
  * @key gc
@@ -30,15 +51,37 @@
  * @modules java.base/jdk.internal.misc:open
  * @modules java.base/java.lang:open
  *          java.management
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC -XX:+UseStringDeduplication -Xmx256M -Xlog:gc+stats TestStringDedup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC -XX:+UseStringDeduplication -Xmx256M -Xlog:gc+stats TestStringDedup
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive   -XX:+UseStringDeduplication -Xmx256M -Xlog:gc+stats TestStringDedup
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestStringDedup
+ *
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC
+ *      TestStringDedup
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC                                         -XX:+UseStringDeduplication -Xmx256M -Xlog:gc+stats TestStringDedup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal    -XX:+UseStringDeduplication -Xmx256M -Xlog:gc+stats TestStringDedup
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestStringDedup
+ */
+
+/*
+ * @test TestStringDedup
+ * @summary Test Shenandoah string deduplication implementation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact      -XX:+UseStringDeduplication -Xmx256M -Xlog:gc+stats TestStringDedup
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestStringDedup
+ *
+ * @run main/othervm -Xmx256m -Xlog:gc+stats -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestStringDedup
  */
 
 import java.lang.reflect.*;
--- a/test/hotspot/jtreg/gc/shenandoah/TestStringDedupStress.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestStringDedupStress.java	Mon Jul 08 16:04:25 2019 +0530
@@ -21,6 +21,82 @@
  *
  */
 
+/*
+ * @test TestStringDedupStress
+ * @summary Test Shenandoah string deduplication implementation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestStringDedupStress
+ */
+
+/*
+ * @test TestStringDedupStress
+ * @summary Test Shenandoah string deduplication implementation
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
+ *          java.management
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC
+ *      -DtargetStrings=3000000
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC
+ *      -XX:ShenandoahUpdateRefsEarly=off
+ *      -DtargetStrings=3000000
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -XX:ShenandoahUpdateRefsEarly=off
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:ShenandoahUpdateRefsEarly=off
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
+ *
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:ShenandoahUpdateRefsEarly=off -XX:+ShenandoahOOMDuringEvacALot
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
+ */
+
  /*
  * @test TestStringDedupStress
  * @summary Test Shenandoah string deduplication implementation
@@ -30,75 +106,27 @@
  * @modules java.base/jdk.internal.misc:open
  * @modules java.base/java.lang:open
  *          java.management
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -DtargetStrings=3000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=aggressive -DtargetStrings=2000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000
- *                   -Xlog:gc
- *                    TestStringDedupStress
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestStringDedupStress
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=static -DtargetStrings=4000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=compact
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=passive -XX:+ShenandoahDegeneratedGC
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=passive -XX:-ShenandoahDegeneratedGC
- *                   -Xlog:gc
- *                   TestStringDedupStress
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=traversal
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=3000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=compact -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=2000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=aggressive -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=2000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=static -XX:ShenandoahUpdateRefsEarly=off
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=aggressive -XX:ShenandoahUpdateRefsEarly=off -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
- *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats
- *                   -XX:ShenandoahGCHeuristics=traversal -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000
- *                   -Xlog:gc
- *                   TestStringDedupStress
+ * @run main/othervm -Xmx1g -Xlog:gc+stats -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseStringDeduplication
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      -DtargetStrings=2000000
+ *      TestStringDedupStress
  */
 
 import java.lang.management.*;
--- a/test/hotspot/jtreg/gc/shenandoah/TestStringInternCleanup.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestStringInternCleanup.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,22 +27,74 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC                       TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC                       TestStringInternCleanup
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestStringInternCleanup
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      TestStringInternCleanup
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestStringInternCleanup
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=aggressive                         TestStringInternCleanup
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestStringInternCleanup
+ */
+
+/*
+ * @test TestStringInternCleanup
+ * @summary Check that Shenandoah cleans up interned strings
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestStringInternCleanup
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify TestStringInternCleanup
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      TestStringInternCleanup
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestStringInternCleanup
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestStringInternCleanup
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=adaptive                           TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=static                             TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=compact                            TestStringInternCleanup
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+ClassUnloadingWithConcurrentMark -Xmx64m -XX:ShenandoahGCHeuristics=traversal                          TestStringInternCleanup
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:-ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC
+ *      TestStringInternCleanup
+ */
+
+/*
+ * @test TestStringInternCleanup
+ * @summary Check that Shenandoah cleans up interned strings
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:-ClassUnloadingWithConcurrentMark -Xmx64m                                                               TestStringInternCleanup
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      TestStringInternCleanup
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahVerify
+ *      TestStringInternCleanup
+ *
+ * @run main/othervm -Xmx64m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+ClassUnloadingWithConcurrentMark
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestStringInternCleanup
  */
 
 public class TestStringInternCleanup {
--- a/test/hotspot/jtreg/gc/shenandoah/TestVerifyJCStress.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestVerifyJCStress.java	Mon Jul 08 16:04:25 2019 +0530
@@ -28,35 +28,49 @@
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  * @modules java.base/jdk.internal.misc
  *          java.management
- * @run main/othervm  -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
- *                    -XX:+UseShenandoahGC -Xmx1g -Xms1g
- *                    -XX:+ShenandoahStoreCheck -XX:+ShenandoahVerify -XX:+VerifyObjectEquals
- *                    -XX:ShenandoahGCHeuristics=passive -XX:+ShenandoahDegeneratedGC
- *                    TestVerifyJCStress
+ *
+ * @run main/othervm -Xmx1g -Xms1g -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify -XX:+VerifyObjectEquals
+ *      TestVerifyJCStress
  *
- * @run main/othervm  -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
- *                    -XX:+UseShenandoahGC -Xmx1g -Xms1g
- *                    -XX:+ShenandoahStoreCheck -XX:+ShenandoahVerify -XX:+VerifyObjectEquals
- *                    -XX:ShenandoahGCHeuristics=passive -XX:-ShenandoahDegeneratedGC
- *                    TestVerifyJCStress
+ * @run main/othervm -Xmx1g -Xms1g -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify -XX:+VerifyObjectEquals
+ *      TestVerifyJCStress
+ */
+
+/*
+ * @test TestVerifyJCStress
+ * @summary Tests that we pass at least one jcstress-like test with all verification turned on
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @modules java.base/jdk.internal.misc
+ *          java.management
  *
- * @run main/othervm  -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
- *                    -XX:+UseShenandoahGC -Xmx1g -Xms1g
- *                    -XX:+ShenandoahStoreCheck -XX:+ShenandoahVerify -XX:+VerifyObjectEquals -XX:+ShenandoahVerifyOptoBarriers
- *                    -XX:ShenandoahGCHeuristics=adaptive
- *                    TestVerifyJCStress
+ * @run main/othervm -Xmx1g -Xms1g -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify -XX:+VerifyObjectEquals -XX:+ShenandoahVerifyOptoBarriers
+ *      TestVerifyJCStress
  *
- * @run main/othervm  -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
- *                    -XX:+UseShenandoahGC -Xmx1g -Xms1g
- *                    -XX:+ShenandoahStoreCheck -XX:+ShenandoahVerify -XX:+VerifyObjectEquals -XX:+ShenandoahVerifyOptoBarriers
- *                    -XX:ShenandoahGCHeuristics=static
- *                    TestVerifyJCStress
+ * @run main/othervm -Xmx1g -Xms1g -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -XX:+ShenandoahVerify -XX:+VerifyObjectEquals -XX:+ShenandoahVerifyOptoBarriers
+ *      TestVerifyJCStress
+ */
+
+/*
+ * @test TestVerifyJCStress
+ * @summary Tests that we pass at least one jcstress-like test with all verification turned on
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @modules java.base/jdk.internal.misc
+ *          java.management
  *
- * @run main/othervm  -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
- *                    -XX:+UseShenandoahGC -Xmx1g -Xms1g
- *                    -XX:+ShenandoahStoreCheck -XX:+ShenandoahVerify -XX:+VerifyObjectEquals -XX:+ShenandoahVerifyOptoBarriers
- *                    -XX:ShenandoahGCHeuristics=traversal
- *                    TestVerifyJCStress
+ * @run main/othervm -Xmx1g -Xms1g -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify -XX:+VerifyObjectEquals -XX:+ShenandoahVerifyOptoBarriers
+ *      TestVerifyJCStress
  */
 
 import java.util.*;
--- a/test/hotspot/jtreg/gc/shenandoah/TestWrongArrayMember.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/TestWrongArrayMember.java	Mon Jul 08 16:04:25 2019 +0530
@@ -26,8 +26,8 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC                                      TestWrongArrayMember
- * @run main/othervm -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal TestWrongArrayMember
+ * @run main/othervm -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC                                TestWrongArrayMember
+ * @run main/othervm -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal TestWrongArrayMember
  */
 
 public class TestWrongArrayMember {
--- a/test/hotspot/jtreg/gc/shenandoah/jni/TestJNIGlobalRefs.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/jni/TestJNIGlobalRefs.java	Mon Jul 08 16:04:25 2019 +0530
@@ -25,8 +25,21 @@
  * @summary Test JNI Global Refs with Shenandoah
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xlog:gc -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahVerify TestJNIGlobalRefs
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xlog:gc -XX:ShenandoahGCHeuristics=aggressive                       TestJNIGlobalRefs
+ *
+ * @run main/othervm/native -Xmx1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahVerify
+ *      TestJNIGlobalRefs
+ */
+
+/* @test TestJNIGlobalRefs
+ * @summary Test JNI Global Refs with Shenandoah
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm/native -Xmx1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestJNIGlobalRefs
  */
 
 import java.util.Arrays;
--- a/test/hotspot/jtreg/gc/shenandoah/jni/TestPinnedGarbage.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/jni/TestPinnedGarbage.java	Mon Jul 08 16:04:25 2019 +0530
@@ -26,12 +26,30 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx512m -XX:+ShenandoahVerify -XX:ShenandoahGCHeuristics=passive    -XX:+ShenandoahDegeneratedGC TestPinnedGarbage
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx512m -XX:+ShenandoahVerify -XX:ShenandoahGCHeuristics=passive    -XX:-ShenandoahDegeneratedGC TestPinnedGarbage
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahVerify -XX:+ShenandoahDegeneratedGC
+ *      TestPinnedGarbage
  *
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx512m                       -XX:ShenandoahGCHeuristics=aggressive TestPinnedGarbage
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahVerify -XX:-ShenandoahDegeneratedGC
+ *      TestPinnedGarbage
+ */
+
+/* @test TestPinnedGarbage
+ * @summary Test that garbage in the pinned region does not crash VM
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx512m -XX:+ShenandoahVerify                                       TestPinnedGarbage
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestPinnedGarbage
+ *
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -Xmx512m
+ *      -XX:+UseShenandoahGC
+ *      -XX:+ShenandoahVerify
+ *      TestPinnedGarbage
  */
 
 import java.util.Arrays;
--- a/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestChurnNotifications.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestChurnNotifications.java	Mon Jul 08 16:04:25 2019 +0530
@@ -26,15 +26,57 @@
  * @summary Check that MX notifications are reported for all cycles
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahDegeneratedGC -Dprecise=true  TestChurnNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive      -XX:-ShenandoahDegeneratedGC -Dprecise=true  TestChurnNotifications
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -Dprecise=true
+ *      TestChurnNotifications
  *
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive   -Dprecise=false TestChurnNotifications
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -Dprecise=true
+ *      TestChurnNotifications
+ */
+
+/*
+ * @test TestChurnNotifications
+ * @summary Check that MX notifications are reported for all cycles
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -Dprecise=false
+ *      TestChurnNotifications
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -Dprecise=false
+ *      TestChurnNotifications
  *
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive     -Dprecise=false TestChurnNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static       -Dprecise=false TestChurnNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact      -Dprecise=false TestChurnNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal    -Dprecise=false TestChurnNotifications
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      -Dprecise=false
+ *      TestChurnNotifications
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      -Dprecise=false
+ *      TestChurnNotifications
+ */
+
+/*
+ * @test TestChurnNotifications
+ * @summary Check that MX notifications are reported for all cycles
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -Dprecise=false
+ *      TestChurnNotifications
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -Dprecise=false
+ *      TestChurnNotifications
  */
 
 import java.util.*;
--- a/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestPauseNotifications.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/mxbeans/TestPauseNotifications.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,15 +27,53 @@
  * @key gc
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  *
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive       -XX:+ShenandoahDegeneratedGC TestPauseNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive       -XX:-ShenandoahDegeneratedGC TestPauseNotifications
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      TestPauseNotifications
  *
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive    TestPauseNotifications
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      TestPauseNotifications
+ */
+
+/*
+ * @test TestPauseNotifications
+ * @summary Check that MX notifications are reported for all cycles
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      TestPauseNotifications
  *
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive      TestPauseNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static        TestPauseNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact       TestPauseNotifications
- * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal     TestPauseNotifications
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      TestPauseNotifications
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static
+ *      TestPauseNotifications
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      TestPauseNotifications
+ */
+
+/*
+ * @test TestPauseNotifications
+ * @summary Check that MX notifications are reported for all cycles
+ * @key gc
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      TestPauseNotifications
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      TestPauseNotifications
  */
 
 import java.util.*;
--- a/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java	Mon Jul 08 16:04:25 2019 +0530
@@ -124,30 +124,31 @@
             return;
         }
 
-        String[] heuristics = new String[] {
-                "adaptive",
-                "compact",
-                "static",
-                "traversal",
-                "aggressive",
-                "passive",
+        String[][][] modeHeuristics = new String[][][] {
+             {{"normal"},    {"adaptive", "compact", "static", "aggressive"}},
+             {{"traversal"}, {"adaptive", "aggressive"}},
+             {{"passive"},   {"passive"}}
         };
 
-        for (String h : heuristics) {
-            // Forceful enabling should work
-            passWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading");
-            passWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloadingWithConcurrentMark");
+        for (String[][] mh : modeHeuristics) {
+            String mode = mh[0][0];
+            String[] heuristics = mh[1];
+            for (String h : heuristics) {
+                // Forceful enabling should work
+                passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading");
+                passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloadingWithConcurrentMark");
 
-            // Even when concurrent unloading is disabled, Full GC has to recover
-            passWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark");
-            passWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");
-            passWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");
+                // Even when concurrent unloading is disabled, Full GC has to recover
+                passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark");
+                passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");
+                passWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:+ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=0");
 
-            // Should OOME when unloading forcefully disabled, even if local flags try to enable it back
-            failWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading");
-            failWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark");
-            failWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");
-            failWith("-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");
+                // Should OOME when unloading forcefully disabled, even if local flags try to enable it back
+                failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading");
+                failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark");
+                failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:+ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");
+                failWith("-XX:ShenandoahGCMode=" + mode, "-XX:ShenandoahGCHeuristics=" + h, "-XX:-ClassUnloading", "-XX:-ClassUnloadingWithConcurrentMark", "-XX:ShenandoahUnloadClassesFrequency=1");
+            }
         }
     }
 }
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGC.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGC.java	Mon Jul 08 16:04:25 2019 +0530
@@ -129,7 +129,7 @@
                     "-XX:+UseShenandoahGC",
                     "-Xlog:gc",
                     "-XX:+ExplicitGCInvokesConcurrent",
-                    "-XX:ShenandoahGCHeuristics=traversal",
+                    "-XX:ShenandoahGCMode=traversal",
                     TestExplicitGC.class.getName(),
                     "test");
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestHeuristicsUnlock.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestHeuristicsUnlock.java	Mon Jul 08 16:04:25 2019 +0530
@@ -44,14 +44,14 @@
     }
 
     public static void main(String[] args) throws Exception {
-        testWith("adaptive", Mode.PRODUCT);
-        testWith("static", Mode.PRODUCT);
-        testWith("compact", Mode.PRODUCT);
+        testWith("-XX:ShenandoahGCHeuristics=adaptive", Mode.PRODUCT);
+        testWith("-XX:ShenandoahGCHeuristics=static", Mode.PRODUCT);
+        testWith("-XX:ShenandoahGCHeuristics=compact", Mode.PRODUCT);
 
-        testWith("traversal", Mode.EXPERIMENTAL);
+        testWith("-XX:ShenandoahGCMode=traversal", Mode.EXPERIMENTAL);
 
-        testWith("aggressive", Mode.DIAGNOSTIC);
-        testWith("passive", Mode.DIAGNOSTIC);
+        testWith("-XX:ShenandoahGCHeuristics=aggressive", Mode.DIAGNOSTIC);
+        testWith("-XX:ShenandoahGCHeuristics=passive", Mode.DIAGNOSTIC);
     }
 
     private static void testWith(String h, Mode mode) throws Exception {
@@ -60,7 +60,7 @@
                     "-XX:-UnlockDiagnosticVMOptions",
                     "-XX:-UnlockExperimentalVMOptions",
                     "-XX:+UseShenandoahGC",
-                    "-XX:ShenandoahGCHeuristics=" + h,
+                    h,
                     "-version"
             );
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
@@ -80,7 +80,7 @@
                     "-XX:+UnlockDiagnosticVMOptions",
                     "-XX:-UnlockExperimentalVMOptions",
                     "-XX:+UseShenandoahGC",
-                    "-XX:ShenandoahGCHeuristics=" + h,
+                    h,
                     "-version"
             );
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
@@ -100,7 +100,7 @@
                     "-XX:-UnlockDiagnosticVMOptions",
                     "-XX:+UnlockExperimentalVMOptions",
                     "-XX:+UseShenandoahGC",
-                    "-XX:ShenandoahGCHeuristics=" + h,
+                    h,
                     "-version"
             );
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java	Mon Jul 08 16:04:25 2019 +0530
@@ -65,7 +65,7 @@
             conf.add("-XX:+UnlockDiagnosticVMOptions");
             conf.add("-XX:+UnlockExperimentalVMOptions");
             conf.add("-XX:+UseShenandoahGC");
-            conf.add("-XX:ShenandoahGCHeuristics=passive");
+            conf.add("-XX:ShenandoahGCMode=passive");
 
             StringBuilder sb = new StringBuilder();
             for (String[] l : opts) {
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java	Mon Jul 08 16:04:25 2019 +0530
@@ -51,13 +51,13 @@
                 "ShenandoahCloneBarrier",
         };
 
-        shouldFailAll("adaptive",   concurrent);
-        shouldFailAll("static",     concurrent);
-        shouldFailAll("compact",    concurrent);
-        shouldFailAll("aggressive", concurrent);
-        shouldFailAll("traversal",  traversal);
-        shouldPassAll("passive",    concurrent);
-        shouldPassAll("passive",    traversal);
+        shouldFailAll("-XX:ShenandoahGCHeuristics=adaptive",   concurrent);
+        shouldFailAll("-XX:ShenandoahGCHeuristics=static",     concurrent);
+        shouldFailAll("-XX:ShenandoahGCHeuristics=compact",    concurrent);
+        shouldFailAll("-XX:ShenandoahGCHeuristics=aggressive", concurrent);
+        shouldFailAll("-XX:ShenandoahGCMode=traversal",        traversal);
+        shouldPassAll("-XX:ShenandoahGCMode=passive",          concurrent);
+        shouldPassAll("-XX:ShenandoahGCMode=passive",          traversal);
     }
 
     private static void shouldFailAll(String h, String[] barriers) throws Exception {
@@ -66,7 +66,7 @@
                     "-XX:+UnlockDiagnosticVMOptions",
                     "-XX:+UnlockExperimentalVMOptions",
                     "-XX:+UseShenandoahGC",
-                    "-XX:ShenandoahGCHeuristics=" + h,
+                    h,
                     "-XX:-" + b,
                     "-version"
             );
@@ -83,7 +83,7 @@
                     "-XX:+UnlockDiagnosticVMOptions",
                     "-XX:+UnlockExperimentalVMOptions",
                     "-XX:+UseShenandoahGC",
-                    "-XX:ShenandoahGCHeuristics=" + h,
+                    h,
                     "-XX:-" + b,
                     "-version"
             );
--- a/test/hotspot/jtreg/gc/stress/CriticalNativeStress.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/stress/CriticalNativeStress.java	Mon Jul 08 16:04:25 2019 +0530
@@ -43,12 +43,13 @@
  * @library /
  * @requires (os.arch =="x86_64" | os.arch == "amd64") & vm.gc.Shenandoah & !vm.graal.enabled
  * @summary test argument pinning by nmethod wrapper of critical native method
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive    -XX:-ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive    -XX:+ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive    -XX:-ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive    -XX:+ShenandoahDegeneratedGC -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
  *
  * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
  * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC                                       -Xcomp -Xmx256M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
- * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal  -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal        -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
+ * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive -Xcomp -Xmx512M -XX:+CriticalJNINatives gc.stress.CriticalNativeStress
  */
 public class CriticalNativeStress {
     private static Random rand = new Random();
--- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithShenandoah.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithShenandoah.java	Mon Jul 08 16:04:25 2019 +0530
@@ -34,19 +34,105 @@
  * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled
  * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects.
  *
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahVerify -XX:+ShenandoahDegeneratedGC gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive      -XX:+ShenandoahVerify -XX:-ShenandoahDegeneratedGC gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahVerify -XX:+ShenandoahDegeneratedGC
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahVerify -XX:-ShenandoahDegeneratedGC
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ */
+
+/*
+ * @test TestGCBasherWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled
+ * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects.
  *
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive                         -XX:+ShenandoahOOMDuringEvacALot gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive                         -XX:+ShenandoahAllocFailureALot  gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive                                                          gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ */
+
+/*
+ * @test TestGCBasherWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled
+ * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects.
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
  *
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ */
+
+/*
+ * @test TestGCBasherWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled
+ * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects.
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
  *
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive                           gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal                          gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact                            gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ */
+
+/*
+ * @test TestGCBasherWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled
+ * @summary Stress the Shenandoah GC by trying to make old objects more likely to be garbage than young objects.
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
+ *
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx1g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      gc.stress.gcbasher.TestGCBasherWithShenandoah 120000
  */
 public class TestGCBasherWithShenandoah {
     public static void main(String[] args) throws IOException {
--- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java	Mon Jul 08 16:04:25 2019 +0530
@@ -30,10 +30,25 @@
  * @library /
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  * @summary Stress Shenandoah's JNI handling by calling GetPrimitiveArrayCritical while concurrently filling up old gen.
- * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+ShenandoahVerify -XX:+UseShenandoahGC gc.stress.gclocker.TestGCLockerWithShenandoah
- * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions                                                      -XX:+UseShenandoahGC gc.stress.gclocker.TestGCLockerWithShenandoah
- * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions                       -XX:+UseShenandoahGC -XX:+ShenandoahOOMDuringEvacALot -XX:ShenandoahGCHeuristics=aggressive gc.stress.gclocker.TestGCLockerWithShenandoah
- * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions                       -XX:+UseShenandoahGC -XX:+ShenandoahAllocFailureALot  -XX:ShenandoahGCHeuristics=aggressive gc.stress.gclocker.TestGCLockerWithShenandoah
+ *
+ * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.gclocker.TestGCLockerWithShenandoah
+ *
+ * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC
+ *      gc.stress.gclocker.TestGCLockerWithShenandoah
+ *
+ * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      gc.stress.gclocker.TestGCLockerWithShenandoah
+ *
+ * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      gc.stress.gclocker.TestGCLockerWithShenandoah
  */
 public class TestGCLockerWithShenandoah {
     public static void main(String[] args) {
--- a/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithShenandoah.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithShenandoah.java	Mon Jul 08 16:04:25 2019 +0530
@@ -31,22 +31,93 @@
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  * @summary Stress the GC by trying to make old objects more likely to be garbage than young objects.
  *
- * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive       -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive       -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive       -XX:+ShenandoahDegeneratedGC                       gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=passive       -XX:-ShenandoahDegeneratedGC                       gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC -XX:+ShenandoahVerify
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:+ShenandoahDegeneratedGC
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=passive
+ *      -XX:-ShenandoahDegeneratedGC
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ */
+
+/*
+ * @test TestGCOldWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @summary Stress the GC by trying to make old objects more likely to be garbage than young objects.
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
  *
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive    -XX:+ShenandoahOOMDuringEvacALot gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive    -XX:+ShenandoahAllocFailureALot  gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive                                     gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ */
+
+/*
+ * @test TestGCOldWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @summary Stress the GC by trying to make old objects more likely to be garbage than young objects.
  *
- * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive     -XX:+ShenandoahVerify gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal    -XX:+ShenandoahVerify gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahOOMDuringEvacALot
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      -XX:+ShenandoahAllocFailureALot
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
  *
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=adaptive      gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=static        gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact       gc.stress.gcold.TestGCOld 50 1 20 10 10000
- * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal     gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -XX:ShenandoahGCHeuristics=aggressive
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm/timeout=600 -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
+ *
+ * @run main/othervm -Xmx384M -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      gc.stress.gcold.TestGCOld 50 1 20 10 10000
  */
 
 public class TestGCOldWithShenandoah {
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithShenandoah.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithShenandoah.java	Mon Jul 08 16:04:25 2019 +0530
@@ -31,9 +31,30 @@
  * @library /
  * @requires vm.gc.Shenandoah & !vm.graal.enabled
  * @summary Stress the Shenandoah GC full GC by allocating objects of different lifetimes concurrently with System.gc().
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+ShenandoahVerify -XX:+UseShenandoahGC gc.stress.systemgc.TestSystemGCWithShenandoah 270
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+ShenandoahVerify -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal gc.stress.systemgc.TestSystemGCWithShenandoah 270
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions                                                      -XX:+UseShenandoahGC gc.stress.systemgc.TestSystemGCWithShenandoah 270
+ *
+ * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.systemgc.TestSystemGCWithShenandoah 270
+ *
+ * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC
+ *      gc.stress.systemgc.TestSystemGCWithShenandoah 270
+ */
+
+/*
+ * @test TestSystemGCWithShenandoah
+ * @key gc
+ * @key stress
+ * @library /
+ * @requires vm.gc.Shenandoah & !vm.graal.enabled
+ * @summary Stress the Shenandoah GC full GC by allocating objects of different lifetimes concurrently with System.gc().
+ *
+ * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal
+ *      -XX:+ShenandoahVerify
+ *      gc.stress.systemgc.TestSystemGCWithShenandoah 270
+ *
  */
 public class TestSystemGCWithShenandoah {
     public static void main(String[] args) throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invocationC1Tests.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, 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 8226956
+ * @summary Run invocation tests against C1 compiler
+ * @library /test/lib
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @compile shared/AbstractGenerator.java shared/AccessCheck.java shared/AccessType.java
+ *          shared/Caller.java shared/ExecutorGenerator.java shared/Utils.java
+ *          shared/ByteArrayClassLoader.java shared/Checker.java shared/GenericClassGenerator.java
+ * @compile invokespecial/Checker.java invokespecial/ClassGenerator.java invokespecial/Generator.java
+ *          invokevirtual/Checker.java invokevirtual/ClassGenerator.java invokevirtual/Generator.java
+ *          invokeinterface/Checker.java invokeinterface/ClassGenerator.java invokeinterface/Generator.java
+ *
+ * @run main/othervm/timeout=1800 invocationC1Tests
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class invocationC1Tests {
+
+    public static void runTest(String whichTests, String classFileVersion) throws Exception {
+        System.out.println("\nC1 invocation tests, Tests: " + whichTests +
+                           ", class file version: " + classFileVersion);
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, "-Xmx128M",
+            "-Xcomp", "-XX:TieredStopAtLevel=1", whichTests,
+            "--classfile_version=" + classFileVersion);
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        try {
+            output.shouldContain("EXECUTION STATUS: PASSED");
+            output.shouldHaveExitValue(0);
+        } catch (Throwable e) {
+            System.out.println(
+                "\nNote that an entry such as 'B.m/C.m' in the failure chart means that" +
+                " the test case failed because method B.m was invoked but the test " +
+                "expected method C.m to be invoked. Similarly, a result such as 'AME/C.m'" +
+                " means that an AbstractMethodError exception was thrown but the test" +
+                " case expected method C.m to be invoked.");
+            System.out.println(
+                "\nAlso note that passing --dump to invoke*.Generator will" +
+                " dump the generated classes (for debugging purposes).\n");
+            System.exit(1);
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+        // Get current major class file version and test with it.
+        byte klassbuf[] = InMemoryJavaCompiler.compile("blah", "public class blah { }");
+        int major_version = klassbuf[6] << 8 | klassbuf[7];
+        runTest("invokespecial.Generator", String.valueOf(major_version));
+        runTest("invokeinterface.Generator", String.valueOf(major_version));
+
+      // Uncomment this test once JDK-8226588 is fixed
+        // runTest("invokevirtual.Generator", String.valueOf(major_version));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invocationGraalTests.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019, 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 8226956
+ * @requires vm.jvmci
+ * @summary Run invocation tests against Graal compiler
+ * @library /test/lib
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ * @compile shared/AbstractGenerator.java shared/AccessCheck.java shared/AccessType.java
+ *          shared/Caller.java shared/ExecutorGenerator.java shared/Utils.java
+ *          shared/ByteArrayClassLoader.java shared/Checker.java shared/GenericClassGenerator.java
+ * @compile invokespecial/Checker.java invokespecial/ClassGenerator.java invokespecial/Generator.java
+ *          invokevirtual/Checker.java invokevirtual/ClassGenerator.java invokevirtual/Generator.java
+ *          invokeinterface/Checker.java invokeinterface/ClassGenerator.java invokeinterface/Generator.java
+ *
+ * @run main/othervm/timeout=1800 invocationGraalTests
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class invocationGraalTests {
+
+    public static void runTest(String whichTests, String classFileVersion) throws Exception {
+        System.out.println("\nGraal invocation tests, Tests: " + whichTests +
+                           ", class file version: " + classFileVersion);
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, "-Xmx128M",
+            "-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "-XX:+UseJVMCICompiler",
+            whichTests, "--classfile_version=" + classFileVersion);
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        try {
+            output.shouldContain("EXECUTION STATUS: PASSED");
+            output.shouldHaveExitValue(0);
+        } catch (Throwable e) {
+            System.out.println(
+                "\nNote that an entry such as 'B.m/C.m' in the failure chart means that" +
+                " the test case failed because method B.m was invoked but the test " +
+                "expected method C.m to be invoked. Similarly, a result such as 'AME/C.m'" +
+                " means that an AbstractMethodError exception was thrown but the test" +
+                " case expected method C.m to be invoked.");
+            System.out.println(
+                "\nAlso note that passing --dump to invoke*.Generator will" +
+                " dump the generated classes (for debugging purposes).\n");
+            System.exit(1);
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+        // Get current major class file version and test with it.
+        byte klassbuf[] = InMemoryJavaCompiler.compile("blah", "public class blah { }");
+        int major_version = klassbuf[6] << 8 | klassbuf[7];
+        runTest("invokevirtual.Generator", String.valueOf(major_version));
+        runTest("invokespecial.Generator", String.valueOf(major_version));
+        runTest("invokeinterface.Generator", String.valueOf(major_version));
+    }
+}
--- a/test/hotspot/jtreg/runtime/InvocationTests/invokeinterface/Checker.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterface/Checker.java	Mon Jul 08 16:04:25 2019 +0530
@@ -67,15 +67,13 @@
                 int modifiers = method.getModifiers();
 
                 // Check whether obtained method is public and isn't abstract
-                if ( Modifier.isPublic(modifiers))
-                {
+                if ( Modifier.isPublic(modifiers)) {
                     if (Modifier.isAbstract(modifiers)) {
                         return "java.lang.AbstractMethodError";
                     } else {
-                        return String.format("%s.%s"
-                            , method.getDeclaringClass().getSimpleName()
-                            , methodName
-                            );
+                        return String.format("%s.%s",
+                            method.getDeclaringClass().getSimpleName(),
+                            methodName);
                     }
                 } else {
                     // IAE is thrown when located method isn't PUBLIC
--- a/test/hotspot/jtreg/runtime/InvocationTests/invokespecial/Checker.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokespecial/Checker.java	Mon Jul 08 16:04:25 2019 +0530
@@ -34,16 +34,12 @@
     }
 
     public String check (Class callerClass) {
-        /*
-         * If objectref is null, the invokespecial instruction throws a NullPointerException.
-         */
+        // If objectref is null, the invokespecial instruction throws a NullPointerException.
         if (dynamicTargetClass == null) {
             return "java.lang.NullPointerException";
         }
 
-        /*
-         * TODO: find a citiation from spec for this case
-         */
+        // TODO: find a citation from spec for this case
         Method resolvedMethod;
         try {
             // May throw VerifyError
@@ -56,15 +52,13 @@
             return "java.lang.NoSuchMethodError";
         }
 
-       /*
-        * If:
-        *   - the resolved method is protected (4.7)
-        *   - it is a member of a superclass of the current class
-        *   - the method is not declared in the same run-time package (5.3) as the current class
-        * then:
-        *   the class of objectref must be either the current class or a subclass of the
-        * current class.
-        */
+       // If:
+       //   - the resolved method is protected (4.7)
+       //   - it is a member of a superclass of the current class
+       //   - the method is not declared in the same run-time package (5.3) as the current class
+       // then:
+       //   the class of objectref must be either the current class or a subclass of the
+       // current class.
 
         if (Modifier.isProtected(resolvedMethod.getModifiers())) {
             Method methodInSuperclass = getMethodInHierarchy(resolvedMethod.getDeclaringClass().getSuperclass());
--- a/test/hotspot/jtreg/runtime/InvocationTests/invokevirtual/Checker.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtual/Checker.java	Mon Jul 08 16:04:25 2019 +0530
@@ -88,7 +88,7 @@
             return null;
         }
 
-        // Dynamic target doesn't have desired method, so check it's superclass
+        // Dynamic target doesn't have desired method, so check its superclass
         if (dynamicTargetMethod == null) {
             return getOverriddenMethod(staticTarget, dynamicTarget.getSuperclass());
         } else {
@@ -109,11 +109,9 @@
             String staticTargetPkg = getClassPackageName(staticTarget);
             String dynamicTargetPkg = getClassPackageName(dynamicTarget);
 
-            if ( isPublic || isProtected
-                 || ( !isPublic && !isProtected && !isPrivate
-                      && staticTargetPkg.equals(dynamicTargetPkg)
-                    ))
-            {
+            if (isPublic || isProtected
+                || (!isPublic && !isProtected && !isPrivate
+                    && staticTargetPkg.equals(dynamicTargetPkg))) {
                 return dynamicTargetMethod;
             }
         }
--- a/test/hotspot/jtreg/runtime/InvocationTests/shared/AbstractGenerator.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/AbstractGenerator.java	Mon Jul 08 16:04:25 2019 +0530
@@ -31,9 +31,6 @@
 import java.util.List;
 import java.util.ArrayList;
 
-/**
- *
- */
 public abstract class AbstractGenerator {
     protected final boolean dumpClasses;
     protected final boolean executeTests;
--- a/test/hotspot/jtreg/runtime/InvocationTests/shared/AccessCheck.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/AccessCheck.java	Mon Jul 08 16:04:25 2019 +0530
@@ -26,8 +26,7 @@
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
-/**
- *
+/*
  * @author vi158347
  */
 public class AccessCheck {
--- a/test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java	Mon Jul 08 16:04:25 2019 +0530
@@ -28,9 +28,15 @@
 
 public class AppCDSOptions extends CDSOptions {
     public String appJar;
+    public String appJarDir;
 
     public AppCDSOptions setAppJar(String appJar) {
         this.appJar = appJar;
         return this;
     }
+
+    public AppCDSOptions setAppJarDir(String appJarDir) {
+        this.appJarDir = appJarDir;
+        return this;
+    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java	Mon Jul 08 16:04:25 2019 +0530
@@ -36,6 +36,9 @@
  */
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
 import jdk.test.lib.process.OutputAnalyzer;
 
 public class AppendClasspath {
@@ -53,9 +56,24 @@
         "HelloMore")
       .assertNormalExit();
 
+    // PASS: 2) runtime has an non-existing jar in the -cp
+    String classDir = System.getProperty("test.classes");
+    String newFile = "non-exist.jar";
+    String nonExistPath = classDir + File.separator + newFile;
+    String classPath = appJar + File.pathSeparator + nonExistPath;
+    File nonExistJar = new File(classDir, newFile);
+    if (nonExistJar.exists()) {
+        nonExistJar.delete();
+    }
+    TestCommon.run(
+        "-cp", classPath,
+        "-Xlog:class+path=trace",
+        "Hello")
+      .assertNormalExit();
+
     final String errorMessage1 = "Unable to use shared archive";
     final String errorMessage2 = "shared class paths mismatch";
-    // FAIL: 2) runtime with classpath different from the one used in dump time
+    // FAIL: 1) runtime with classpath different from the one used in dump time
     // (runtime has an extra jar file prepended to the class path)
     TestCommon.run(
         "-Xlog:cds",
@@ -63,7 +81,7 @@
         "HelloMore")
         .assertAbnormalExit(errorMessage1, errorMessage2);
 
-    // FAIL: 3) runtime with classpath part of the one used in dump time
+    // FAIL: 2) runtime with classpath part of the one used in dump time
     TestCommon.testDump(appJar + File.pathSeparator + appJar2,
                                       TestCommon.list("Hello"));
     TestCommon.run(
@@ -72,12 +90,26 @@
         "Hello")
         .assertAbnormalExit(errorMessage1, errorMessage2);
 
-    // FAIL: 4) runtime with same set of jar files in the classpath but
+    // FAIL: 3) runtime with same set of jar files in the classpath but
     // with different order
     TestCommon.run(
         "-Xlog:cds",
         "-cp", appJar2 + File.pathSeparator + appJar,
         "HelloMore")
         .assertAbnormalExit(errorMessage1, errorMessage2);
-  }
+
+    // FAIL: 4) non-existing jar during dump time but jar exists during runtime
+    TestCommon.testDump(classPath, TestCommon.list("Hello"));
+
+    Files.copy(Paths.get(classDir, "hello.jar"),
+        Paths.get(classDir, newFile),
+        StandardCopyOption.REPLACE_EXISTING);
+
+    TestCommon.run(
+        "-cp", classPath,
+        "-Xlog:class+path=trace",
+        "Hello")
+        .assertAbnormalExit(errorMessage1, errorMessage2);
+
+    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java	Mon Jul 08 16:04:25 2019 +0530
@@ -34,6 +34,7 @@
  * @run driver BootClassPathMismatch
  */
 
+import jdk.test.lib.Platform;
 import jdk.test.lib.cds.CDSOptions;
 import jdk.test.lib.cds.CDSTestUtils;
 import jdk.test.lib.process.OutputAnalyzer;
@@ -41,7 +42,9 @@
 import java.nio.file.Files;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.StandardCopyOption;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.attribute.FileTime;
 
 
 public class BootClassPathMismatch {
@@ -126,6 +129,55 @@
                 "-cp", appJar, "-verbose:class",
                 "-Xbootclasspath/a:" + appJar, "Hello")
             .assertNormalExit("[class,load] Hello source: shared objects file");
+
+        // test relative path to appJar
+        String newJar = TestCommon.composeRelPath(appJar);
+        TestCommon.run(
+                "-cp", newJar, "-verbose:class",
+                "-Xbootclasspath/a:" + newJar, "Hello")
+            .assertNormalExit("[class,load] Hello source: shared objects file");
+
+        int idx = appJar.lastIndexOf(File.separator);
+        String jarName = appJar.substring(idx + 1);
+        String jarDir = appJar.substring(0, idx);
+        // relative path starting with "."
+        TestCommon.runWithRelativePath(
+            jarDir,
+            "-Xshare:on",
+            "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+            "-cp", "." + File.separator + jarName,
+            "-Xbootclasspath/a:" + "." + File.separator + jarName,
+            "-Xlog:class+load=trace,class+path=info",
+            "Hello")
+            .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+                });
+
+        // relative path starting with ".."
+        idx = jarDir.lastIndexOf(File.separator);
+        String jarSubDir = jarDir.substring(idx + 1);
+        TestCommon.runWithRelativePath(
+            jarDir,
+            "-Xshare:on",
+            "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+            "-cp", ".." + File.separator + jarSubDir + File.separator + jarName,
+            "-Xbootclasspath/a:" + ".." + File.separator + jarSubDir + File.separator + jarName,
+            "-Xlog:class+load=trace,class+path=info",
+            "Hello")
+            .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+                });
+
+        // test sym link to appJar
+        if (!Platform.isWindows()) {
+            File linkedJar = TestCommon.createSymLink(appJar);
+            TestCommon.run(
+                    "-cp", linkedJar.getPath(), "-verbose:class",
+                    "-Xbootclasspath/a:" + linkedJar.getPath(), "Hello")
+                .assertNormalExit("[class,load] Hello source: shared objects file");
+        }
     }
 
     /* Archive contains boot classes only, runtime add -Xbootclasspath/a path.
@@ -158,6 +210,12 @@
                 "-Xlog:cds",
                 "-cp", appJar, "-Xbootclasspath/a:" + appJar, "Hello")
             .assertAbnormalExit(mismatchMessage);
+
+        // test relative path to appJar
+        String newJar = TestCommon.composeRelPath(appJar);
+        TestCommon.run(
+                "-cp", newJar, "-Xbootclasspath/a:" + newJar, "Hello")
+            .assertAbnormalExit(mismatchMessage);
     }
 
     private static void copyHelloToNewDir() throws Exception {
@@ -168,13 +226,25 @@
         } catch (FileAlreadyExistsException e) { }
 
         // copy as hello.jar
+        Path dstPath = Paths.get(dstDir, "hello.jar");
         Files.copy(Paths.get(classDir, "hello.jar"),
-            Paths.get(dstDir, "hello.jar"),
+            dstPath,
             StandardCopyOption.REPLACE_EXISTING);
 
+        File helloJar = dstPath.toFile();
+        long modTime = helloJar.lastModified();
+
         // copy as hello.jar1
+        Path dstPath2 = Paths.get(dstDir, "hello.jar1");
         Files.copy(Paths.get(classDir, "hello.jar"),
-            Paths.get(dstDir, "hello.jar1"),
+            dstPath2,
             StandardCopyOption.REPLACE_EXISTING);
+
+        // On Windows, we rely on the file size, creation time, and
+        // modification time in order to differentiate between 2 files.
+        // Setting a different modification time on hello.jar1 so that this test
+        // runs more reliably on Windows.
+        modTime += 10000;
+        Files.setAttribute(dstPath2, "lastModifiedTime", FileTime.fromMillis(modTime));
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java	Mon Jul 08 16:04:25 2019 +0530
@@ -105,12 +105,13 @@
         "-XX:+PrintSharedArchiveAndExit")
       .ifNoMappingFailure(output -> check(output, 1, true, lastCheckMsg, "Run time APP classpath is shorter than the one at dump time: ."));
 
-    log("Use an invalid App CP -- all the JAR paths should be checked");
+    log("Use an invalid App CP -- all the JAR paths should be checked.\n" +
+        "Non-existing jar files will be ignored.");
     String invalidCP = "non-existing-dir" + File.pathSeparator + cp;
     TestCommon.run(
         "-cp", invalidCP,
         "-XX:+PrintSharedArchiveAndExit")
-      .ifNoMappingFailure(output -> check(output, 1, true, lastCheckMsg, "APP classpath mismatch, actual: -Djava.class.path=" + invalidCP));
+      .ifNoMappingFailure(output -> check(output, 0, true, lastCheckMsg));
 
     log("Changed modification time of hello.jar -- all the JAR paths should be checked");
     (new File(appJar)).setLastModified(System.currentTimeMillis() + 2000);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/RelativePath.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test relative paths specified in the -cp.
+ * @requires vm.cds
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @compile test-classes/Hello.java
+ * @compile test-classes/HelloMore.java
+ * @run driver RelativePath
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import java.util.Arrays;
+import jdk.test.lib.Platform;
+
+public class RelativePath {
+
+  private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+  public static void main(String[] args) throws Exception {
+    String appJar = JarBuilder.getOrCreateHelloJar();
+    String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore");
+
+    // dump an archive with only the jar name in the -cp
+    int idx = appJar.lastIndexOf(File.separator);
+    String jarName = appJar.substring(idx + 1);
+    String jarDir = appJar.substring(0, idx);
+    TestCommon.testDump(jarDir, jarName, TestCommon.list("Hello"));
+
+    // copy the jar file to another dir. Specify the jar file without
+    // a directory path.
+    Path srcPath = Paths.get(appJar);
+    Path destDir = Files.createTempDirectory(USER_DIR, "deploy");
+    Path destPath = destDir.resolve(jarName);
+    Files.copy(srcPath, destPath, REPLACE_EXISTING, COPY_ATTRIBUTES);
+    TestCommon.runWithRelativePath(
+        destDir.toString(),
+        "-Xshare:on",
+        "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+        "-cp", jarName + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // Long path test
+    // Create a long directory path and copy the appJar there.
+    final int MAX_PATH = 260;
+    destDir = Paths.get(jarDir);
+    int subDirLen = MAX_PATH - jarDir.length() - 3;
+    if (subDirLen > 0) {
+        char[] chars = new char[subDirLen];
+        Arrays.fill(chars, 'x');
+        String subPath = new String(chars);
+        destDir = Paths.get(jarDir, subPath);
+    }
+    File longDir = destDir.toFile();
+    longDir.mkdir();
+    String destJar = longDir.getPath() + File.separator + jarName;
+    Files.copy(Paths.get(appJar), Paths.get(destJar), REPLACE_EXISTING);
+    // Create an archive with the appJar in the long directory path.
+    TestCommon.testDump(destJar, TestCommon.list("Hello"));
+
+    // Run with -cp containing the appJar and another jar appended.
+    TestCommon.run(
+        "-cp", destJar + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // Dump an archive with a specified JAR file in -classpath
+    TestCommon.testDump(appJar, TestCommon.list("Hello"));
+
+    // compose a relative path to the hello.jar
+    String newHello = TestCommon.composeRelPath(appJar);
+
+    // create a sym link to the original hello.jar
+    File linkedHello = null;
+    if (!Platform.isWindows()) {
+        linkedHello = TestCommon.createSymLink(appJar);
+    }
+
+    // PASS:1) same appJar but referred to via a relative path
+    TestCommon.run(
+        "-cp", newHello + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+      .assertNormalExit();
+
+    // PASS:2) relative path starting with "."
+    TestCommon.runWithRelativePath(
+        jarDir,
+        "-Xshare:on",
+        "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+        "-cp", "." + File.separator + jarName + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // PASS:3) relative path starting with ".."
+    idx = jarDir.lastIndexOf(File.separator);
+    String jarSubDir = jarDir.substring(idx + 1);
+    TestCommon.runWithRelativePath(
+        jarDir,
+        "-Xshare:on",
+        "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+        "-cp", ".." + File.separator + jarSubDir + File.separator + jarName
+               + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // PASS:4) a jar linked to the original hello.jar
+    if (!Platform.isWindows()) {
+        TestCommon.run(
+            "-cp", linkedHello.getPath() + File.pathSeparator + appJar2,
+            "HelloMore")
+          .assertNormalExit();
+    }
+
+    final String errorMessage1 = "Unable to use shared archive";
+    final String errorMessage2 = "shared class paths mismatch";
+    // FAIL: 1) runtime with classpath different from the one used in dump time
+    // (runtime has an extra jar file prepended to the class path)
+    TestCommon.run(
+        "-cp", appJar2 + File.pathSeparator + newHello,
+        "HelloMore")
+        .assertAbnormalExit(errorMessage1, errorMessage2);
+
+    }
+}
--- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Mon Jul 08 16:04:25 2019 +0530
@@ -128,6 +128,10 @@
         return createArchive(appJar, classList, suffix);
     }
 
+    public static OutputAnalyzer dump(String appJarDir, String appJar, String classList[],
+                                               String... suffix) throws Exception {
+        return createArchive(appJarDir, appJar, classList, suffix);
+    }
 
     // Create AppCDS archive using most common args - convenience method
     public static OutputAnalyzer createArchive(String appJar, String classList[],
@@ -138,6 +142,15 @@
         return createArchive(opts);
     }
 
+    public static OutputAnalyzer createArchive(String appJarDir, String appJar, String classList[],
+                                               String... suffix) throws Exception {
+        AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
+        opts.setAppJarDir(appJarDir);
+        opts.setClassList(classList);
+        opts.addSuffix(suffix);
+        return createArchive(opts);
+    }
+
     // Simulate -Xshare:dump with -XX:ArchiveClassesAtExit. See comments around patchJarForDynamicDump()
     private static final Class tmp = DynamicDumpHelper.class;
 
@@ -222,6 +235,9 @@
 
         String[] cmdLine = cmd.toArray(new String[cmd.size()]);
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
+        if (opts.appJarDir != null) {
+            pb.directory(new File(opts.appJarDir));
+        }
         return executeAndLog(pb, "dump");
     }
 
@@ -360,6 +376,9 @@
 
         String[] cmdLine = cmd.toArray(new String[cmd.size()]);
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
+        if (opts.appJarDir != null) {
+            pb.directory(new File(opts.appJarDir));
+        }
         return executeAndLog(pb, "exec");
     }
 
@@ -378,6 +397,13 @@
         return new Result(opts, runWithArchive(opts));
     }
 
+    public static Result runWithRelativePath(String jarDir, String... suffix) throws Exception {
+        AppCDSOptions opts = (new AppCDSOptions());
+        opts.setAppJarDir(jarDir);
+        opts.addSuffix(suffix);
+        return new Result(opts, runWithArchive(opts));
+    }
+
     public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception {
         AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
         opts.addSuffix(suffix);
@@ -443,6 +469,20 @@
         return output;
     }
 
+    public static OutputAnalyzer testDump(String appJarDir, String appJar, String classList[],
+                                          String... suffix) throws Exception {
+        OutputAnalyzer output = dump(appJarDir, appJar, classList, suffix);
+        if (DYNAMIC_DUMP) {
+            if (isUnableToMap(output)) {
+                throw new SkippedException(UnableToMapMsg);
+            }
+            output.shouldContain("Written dynamic archive");
+        } else {
+            output.shouldContain("Loading classes to share");
+        }
+        output.shouldHaveExitValue(0);
+        return output;
+    }
 
     /**
      * Simple test -- dump and execute appJar with the given classList in classlist.
@@ -590,4 +630,32 @@
             }
         }
     }
+
+    public static String composeRelPath(String appJar) {
+         int idx = appJar.lastIndexOf(File.separator);
+         String jarName = appJar.substring(idx + 1);
+         String jarDir = appJar.substring(0, idx);
+         String lastDir = jarDir.substring(jarDir.lastIndexOf(File.separator));
+         String relPath = jarDir + File.separator + ".." + File.separator + lastDir;
+         String newJar = relPath + File.separator + jarName;
+         return newJar;
+    }
+
+
+    public static File createSymLink(String appJar) throws Exception {
+         int idx = appJar.lastIndexOf(File.separator);
+         String jarName = appJar.substring(idx + 1);
+         String jarDir = appJar.substring(0, idx);
+         File origJar = new File(jarDir, jarName);
+         String linkedJarName = "linked_" + jarName;
+         File linkedJar = null;
+         if (!Platform.isWindows()) {
+             linkedJar = new File(jarDir, linkedJarName);
+             if (linkedJar.exists()) {
+                 linkedJar.delete();
+             }
+             Files.createSymbolicLink(linkedJar.toPath(), origJar.toPath());
+         }
+         return linkedJar;
+    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/dynamicArchive/DynamicArchiveTestBase.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/dynamicArchive/DynamicArchiveTestBase.java	Mon Jul 08 16:04:25 2019 +0530
@@ -108,7 +108,7 @@
             cmdLine = TestCommon.concat(cmdLine, "-XX:SharedArchiveFile=" + baseArchiveName);
         }
         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
-        return execProcess("dump", cmdLine);
+        return execProcess("dump", null, cmdLine);
     }
 
     public static Result dump2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
@@ -188,7 +188,23 @@
             "-Xshare:on",
             "-XX:SharedArchiveFile=" + archiveFiles);
         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
-        return execProcess("exec", cmdLine);
+        return execProcess("exec", null, cmdLine);
+    }
+
+    public static Result runWithRelativePath(String baseArchiveName, String topArchiveName,
+                              String jarDir, String ... cmdLineSuffix)
+        throws Exception {
+        if (baseArchiveName == null && topArchiveName == null) {
+            throw new RuntimeException("Both baseArchiveName and topArchiveName cannot be null at the same time.");
+        }
+        String archiveFiles = (baseArchiveName == null) ? topArchiveName :
+            (topArchiveName == null) ? baseArchiveName :
+            baseArchiveName + File.pathSeparator + topArchiveName;
+        String[] cmdLine = TestCommon.concat(
+            "-Xshare:on",
+            "-XX:SharedArchiveFile=" + archiveFiles);
+        cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
+        return execProcess("exec", jarDir, cmdLine);
     }
 
     public static Result run2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
@@ -221,11 +237,14 @@
    }
 
 
-    private static Result execProcess(String mode, String[] cmdLine) throws Exception {
+    private static Result execProcess(String mode, String jarDir, String[] cmdLine) throws Exception {
         if (!executedIn_run) {
             throw new Exception("Test error: dynamic archive tests must be executed via DynamicArchiveTestBase.run()");
         }
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
+        if (jarDir != null) {
+            pb.directory(new File(jarDir));
+        }
         OutputAnalyzer output = TestCommon.executeAndLog(pb, mode);
         CDSOptions opts = new CDSOptions();
         String xShareMode = getXshareMode(cmdLine);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/dynamicArchive/RelativePath.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test relative paths specified in the -cp.
+ * @requires vm.cds
+ * @library /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @compile ../test-classes/Hello.java
+ * @compile ../test-classes/HelloMore.java
+ * @run driver RelativePath
+ */
+
+import java.io.File;
+
+public class RelativePath extends DynamicArchiveTestBase {
+
+    public static void main(String[] args) throws Exception {
+        runTest(AppendClasspath::testDefaultBase);
+    }
+
+    static void testDefaultBase() throws Exception {
+        String topArchiveName = getNewArchiveName("top");
+        doTest(topArchiveName);
+    }
+
+    private static void doTest(String topArchiveName) throws Exception {
+        String appJar = JarBuilder.getOrCreateHelloJar();
+        String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore");
+
+        int idx = appJar.lastIndexOf(File.separator);
+        String jarName = appJar.substring(idx + 1);
+        String jarDir = appJar.substring(0, idx);
+        // relative path starting with "."
+        runWithRelativePath(null, topArchiveName, jarDir,
+            "-Xlog:class+load",
+            "-Xlog:cds+dynamic=debug,cds=debug",
+            "-cp", "." + File.separator + "hello.jar" + File.pathSeparator + appJar2,
+            "HelloMore")
+            .assertNormalExit(output -> {
+                    output.shouldContain("Hello source: shared objects file")
+                          .shouldContain("Hello World ... More")
+                          .shouldHaveExitValue(0);
+                });
+
+        // relative path starting with ".."
+        idx = jarDir.lastIndexOf(File.separator);
+        String jarSubDir = jarDir.substring(idx + 1);
+        runWithRelativePath(null, topArchiveName, jarDir,
+            "-Xlog:class+load",
+            "-Xlog:cds+dynamic=debug,cds=debug",
+            "-cp",
+            ".." + File.separator + jarSubDir + File.separator + "hello.jar" + File.pathSeparator + appJar2,
+            "HelloMore")
+            .assertNormalExit(output -> {
+                    output.shouldContain("Hello source: shared objects file")
+                          .shouldContain("Hello World ... More")
+                          .shouldHaveExitValue(0);
+                });
+
+    }
+}
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC04/tc04t001/tc04t001.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC04/tc04t001/tc04t001.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -119,19 +119,10 @@
 
     /* check if event is for tested object */
     if (jni->IsSameObject(object_M, obj)) {
-        jvmtiMonitorUsage usageInfo;
-
         if (lockSyncLock(jvmti)) {
             enterEventsCount++;
             unlockSyncLock(jvmti);
         }
-
-        if (!NSK_JVMTI_VERIFY(jvmti->GetObjectMonitorUsage(obj, &usageInfo))) {
-            nsk_jvmti_setFailStatus();
-        } else if (usageInfo.owner != NULL) {
-            if (!NSK_JVMTI_VERIFY(jvmti->InterruptThread(usageInfo.owner)))
-                nsk_jvmti_setFailStatus();
-        }
     }
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/FollowReferences/followref003/followref003.cpp	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/FollowReferences/followref003/followref003.cpp	Mon Jul 08 16:04:25 2019 +0530
@@ -810,7 +810,7 @@
             }
             break;
 
-        case JVMTI_REFERENCE_ARRAY_ELEMENT:
+        case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
         case JVMTI_HEAP_REFERENCE_JNI_GLOBAL:
         case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS:
         case JVMTI_HEAP_REFERENCE_MONITOR:
--- a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -60,7 +60,7 @@
 
 /*
  * @test
- * @bug 6439439 8087303 8174025
+ * @bug 6439439 8087303 8174025 8223291
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  * @run testng/othervm -DrunSecMngr=true common.prettyprint.PrettyPrintTest
  * @run testng/othervm common.prettyprint.PrettyPrintTest
@@ -382,7 +382,6 @@
     private Document toXmlDocument(String xmlString) throws Exception {
         InputSource xmlInputSource = new InputSource(new StringReader(xmlString));
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setValidating(true);
         DocumentBuilder xmlDocumentBuilder = dbf.newDocumentBuilder();
         Document node = xmlDocumentBuilder.parse(xmlInputSource);
         return node;
--- a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/xmltest1.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/xmltest1.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,3 +1,1 @@
-<a>
-    <![CDATA[ ]]>
-</a>
+<a><![CDATA[ ]]></a>
--- a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/xmltest2.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/xmltest2.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,3 @@
-<a>
-    <![CDATA[  abc def 
+<a><![CDATA[  abc def 
 line2 &a 
- test]]>
-</a>
+ test]]></a>
--- a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/xmltest8.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/xmltest8.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,6 +1,5 @@
 <root>
-         t
-    <![CDATA[ ]]>
+     t<![CDATA[ ]]>
     t   
     
     <child1/>
--- a/test/jaxp/javax/xml/jaxp/unittest/transform/OutputPropertiesTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jaxp/javax/xml/jaxp/unittest/transform/OutputPropertiesTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -24,21 +24,79 @@
 package transform;
 
 import java.io.StringReader;
+import java.io.StringWriter;
 import java.util.Properties;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 import org.testng.Assert;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
 
 /*
  * @test
- * @bug 8219705
+ * @bug 8219705 8223291
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  * @run testng transform.OutputPropertiesTest
  * @summary Verifies the output properties are set correctly
  */
 public class OutputPropertiesTest {
+    /*
+       DataProvider: for testing indentation
+       Data: xml, expected result
+     */
+    @DataProvider(name = "Indentation")
+    public Object[][] getData() {
+        String mix = "\n" +
+                "        abc\n" +
+                "        mix\n" +
+                "        xyz\n" +
+                "    ";
+        return new Object[][]{
+            {"abc<![CDATA[data]]>xyz", "abcdataxyz"},
+            {"abc<![CDATA[ & ]]>xyz", "abc & xyz"},
+            {"<![CDATA[data]]>", "data"},
+            {"abc<mix>mix</mix>xyz", mix}
+        };
+    }
+
+
+    /**
+     * bug 8223291
+     * Verifies that no extra indentation is added for CDATA.
+     * @param xml the xml content to be tested
+     * @param expected the expected result
+     * @throws Exception
+     */
+    @Test(dataProvider = "Indentation")
+    public void testIndentation(String xml, String expected) throws Exception
+    {
+        StreamSource source = new StreamSource(new StringReader("<foo><bar>" + xml + "</bar></foo>"));
+        StreamResult result = new StreamResult(new StringWriter());
+
+        Transformer tform = TransformerFactory.newInstance().newTransformer();
+        tform.setOutputProperty(OutputKeys.INDENT, "yes");
+        tform.transform(source, result);
+
+        String xml1 = result.getWriter().toString();
+
+        Document document = DocumentBuilderFactory.newInstance()
+            .newDocumentBuilder()
+            .parse(new InputSource(new StringReader(xml1)));
+
+        String resultData = document.getElementsByTagName("bar")
+            .item(0)
+            .getTextContent();
+
+        Assert.assertEquals(resultData, expected);
+    }
+
     @Test
     public void testOutputProperties() throws Exception {
         String xslData = "<?xml version='1.0'?>"
@@ -70,4 +128,5 @@
                     prNames[i] + ": actual: " + value + ", expected: " + prValues[i]);
         }
     }
+
 }
--- a/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/lang/reflect/exeCallerAccessTest/CallerAccessTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -28,9 +28,12 @@
  * @summary Test uses custom launcher that starts VM using JNI that verifies
  *          reflection API with null caller class
  * @library /test/lib
+ * @requires os.family != "aix"
  * @run main/native CallerAccessTest
  */
 
+// Test disabled on AIX since we cannot invoke the JVM on the primordial thread.
+
 import java.io.File;
 import java.util.Map;
 import jdk.test.lib.Platform;
--- a/test/jdk/java/net/HttpCookie/IllegalCookieNameTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/net/HttpCookie/IllegalCookieNameTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,25 +23,35 @@
 
 /* @test
  * @bug 7183292
+ * @library /test/lib
  * @modules jdk.httpserver
+ * @run main IllegalCookieNameTest
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true IllegalCookieNameTest
  */
 import java.net.*;
 import java.util.*;
 import java.io.*;
 import com.sun.net.httpserver.*;
+import jdk.test.lib.net.URIBuilder;
 
 public class IllegalCookieNameTest {
-    public static void main(String[] args) throws IOException {
+    public static void main(String[] args) throws Exception {
         HttpServer s = null;
         try {
-            InetSocketAddress addr = new InetSocketAddress(0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            InetSocketAddress addr = new InetSocketAddress(loopback, 0);
             s = HttpServer.create(addr, 10);
             s.createContext("/", new HHandler());
             s.start();
-            String u = "http://127.0.0.1:" + s.getAddress().getPort() + "/";
+            String u = URIBuilder.newBuilder()
+                .scheme("http")
+                .loopback()
+                .port(s.getAddress().getPort())
+                .path("/")
+                .build().toString();
             CookieHandler.setDefault(new TestCookieHandler());
             URL url = new URL(u);
-            HttpURLConnection c = (HttpURLConnection) url.openConnection();
+            HttpURLConnection c = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
             c.getHeaderFields();
             System.out.println ("OK");
         } finally {
--- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -258,14 +258,27 @@
     public static URL url(HttpProtocolType protocol, InetSocketAddress address,
                           String path) throws MalformedURLException {
         return new URL(protocol(protocol),
-                       address.getHostString(),
+                       address.getAddress().getHostAddress(),
                        address.getPort(), path);
     }
 
     public static Proxy proxy(HTTPTestServer server, HttpAuthType authType) {
-        return (authType == HttpAuthType.PROXY)
-               ? new Proxy(Proxy.Type.HTTP, server.getAddress())
-               : null;
+        if (authType != HttpAuthType.PROXY) return null;
+
+        InetSocketAddress proxyAddress = server.getProxyAddress();
+        if (!proxyAddress.isUnresolved()) {
+            // Forces the proxy to use an unresolved address created
+            // from the actual IP address to avoid using the proxy
+            // address hostname which would result in resolving to
+            // a posibly different address. For instance we want to
+            // avoid cases such as:
+            //    ::1 => "localhost" => 127.0.0.1
+            proxyAddress = InetSocketAddress.
+                createUnresolved(proxyAddress.getAddress().getHostAddress(),
+                                 proxyAddress.getPort());
+        }
+
+        return new Proxy(Proxy.Type.HTTP, proxyAddress);
     }
 
     public static HttpURLConnection openConnection(URL url,
--- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java	Mon Jul 08 16:04:25 2019 +0530
@@ -391,6 +391,10 @@
         return serverImpl.getAddress();
     }
 
+    public InetSocketAddress getProxyAddress() {
+        return serverImpl.getAddress();
+    }
+
     public void stop() {
         serverImpl.stop(0);
         if (redirect != null) {
@@ -1019,7 +1023,7 @@
         }
 
         @Override
-        public InetSocketAddress getAddress() {
+        public InetSocketAddress getProxyAddress() {
             return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort());
         }
 
@@ -1047,7 +1051,7 @@
             Socket clientConnection = null;
             try {
                 while (true) {
-                    System.out.println("Tunnel: Waiting for client");
+                    System.out.println("Tunnel: Waiting for client at: " + ss);
                     Socket previous = clientConnection;
                     try {
                         clientConnection = ss.accept();
--- a/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/net/NetworkInterface/NetworkInterfaceRetrievalTests.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,21 @@
 
 /**
  * @test
- * @bug 8179559
+ * @bug 8179559 8225239
  */
 
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.util.Enumeration;
+import java.lang.reflect.Method;
 
 public class NetworkInterfaceRetrievalTests {
     public static void main(String[] args) throws Exception {
         int checkFailureCount = 0;
 
+        Method isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class);
+        isBound.setAccessible(true);
+
         try {
             Enumeration<NetworkInterface> en = NetworkInterface
                     .getNetworkInterfaces();
@@ -58,6 +62,13 @@
                         checkFailureCount++;
                     }
 
+                    // Any bound address should return true when calling isBoundInetAddress
+                    if (!((boolean)isBound.invoke(null, addr))) {
+                        System.out.println("Retreived net if bound addr " + addr
+                                + "NOT shown as bound using NetworkInterface.isBoundAddress "
+                                + "***********");
+                        checkFailureCount++;
+                    }
                 }
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ByteArrayPublishers.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, 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 8222968
+ * @summary ByteArrayPublisher is not thread-safe resulting in broken re-use of HttpRequests
+ * @run main/othervm ByteArrayPublishers
+ */
+
+import java.net.InetAddress;
+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.util.ArrayList;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.CompletableFuture;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import static java.net.http.HttpRequest.BodyPublisher;
+import static java.net.http.HttpRequest.BodyPublishers;
+
+public class ByteArrayPublishers {
+    private static final BodyPublisher BODY_PUBLISHER =
+        BodyPublishers.ofByteArray("abcdefghijklmnopqrstuvwxyz".getBytes());
+
+    static int LOOPS = 100;
+
+    public static void main(String[] args) throws Exception {
+        HttpServer server = null;
+        try {
+            InetAddress loopBack = InetAddress.getLoopbackAddress();
+            String lpBackStr = loopBack.getHostAddress();
+            InetSocketAddress serverAddr = new InetSocketAddress(loopBack, 0);
+            server = HttpServer.create(serverAddr, 500);
+            server.createContext("/", (HttpExchange e) -> {
+                    e.getRequestBody().readAllBytes();
+                    String response = "Hello world";
+                    e.sendResponseHeaders(200, response.length());
+                    e.getResponseBody().write(response.getBytes(StandardCharsets.ISO_8859_1));
+                    e.close();
+            });
+            server.start();
+            var address = server.getAddress();
+            URI dest = new URI("http://" + lpBackStr + ":"
+                + Integer.toString(address.getPort()) + "/");
+
+            HttpClient client = createClient();
+
+            ArrayList<CompletableFuture<HttpResponse<Void>>> futures = new ArrayList<>(LOOPS);
+            LinkedBlockingQueue<Object> results = new LinkedBlockingQueue<Object>();
+            for (int i=0;i<LOOPS;i++) {
+                futures.add(
+                    client.sendAsync(createRequest(dest), HttpResponse.BodyHandlers.discarding())
+                          .handle((v, t) -> {
+                                if (t != null)
+                                    results.add(t);
+                                else
+                                    results.add(v);
+                                return null;
+                          }));
+            }
+
+            for (int i=0; i<LOOPS; i++) {
+                Object o = results.take();
+                if (o instanceof Exception) {
+                    throw new RuntimeException((Exception)o);
+                }
+            }
+        } finally {
+            server.stop(1);
+        }
+    }
+
+    private static HttpRequest createRequest(URI uri) throws URISyntaxException {
+        HttpRequest.Builder builder = HttpRequest.newBuilder(uri)
+                .method("POST", BODY_PUBLISHER)
+                .version(HttpClient.Version.HTTP_1_1);
+        builder.header("content-type", "text/plain");
+        return builder.build();
+    }
+
+    private static HttpClient createClient() {
+        return HttpClient.newBuilder()
+                .version(HttpClient.Version.HTTP_1_1)
+                .build();
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Flow.Publisher;
+import java.util.stream.Stream;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersFromPublisher
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    public BodyPublishersFromPublisher() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        Stream<ByteBuffer> buffers =
+                Stream.generate(() -> S.bufferOfNRandomBytes(1024))
+                      .limit(nElements);
+        Publisher<ByteBuffer> pub = S.publisherOfStream(buffers);
+        return BodyPublishers.fromPublisher(pub);
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return BodyPublishers.fromPublisher(S.newErroredPublisher());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersNoBody.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Flow.Publisher;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersNoBody
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    public BodyPublishersNoBody() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        return BodyPublishers.noBody();
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return null;
+    }
+
+    @Override
+    public long maxElementsFromPublisher() {
+        return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArray.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Flow.Publisher;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersOfByteArray
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    private static final int ELEMENT_SIZE = 16 * 1024;
+
+    public BodyPublishersOfByteArray() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        byte[] b = S.arrayOfNRandomBytes(nElements * ELEMENT_SIZE);
+        return BodyPublishers.ofByteArray(b);
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return null;
+    }
+
+    @Override
+    public long maxElementsFromPublisher() {
+        return 21;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArrays.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.concurrent.Flow.Publisher;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersOfByteArrays
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    private static final int ELEMENT_SIZE = 16 * 1024;
+
+    public BodyPublishersOfByteArrays() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        byte[] bytes = S.arrayOfNRandomBytes(ELEMENT_SIZE);
+        return BodyPublishers.ofByteArrays(
+                Collections.nCopies((int) nElements, bytes));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.Flow.Publisher;
+import java.util.concurrent.atomic.AtomicLong;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersOfFile
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    private static final int ELEMENT_SIZE = 16 * 1024;
+    private static final AtomicLong UNIQUE_NUMBERS = new AtomicLong();
+
+    public BodyPublishersOfFile() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        try {
+            Path f = createFile(nElements * ELEMENT_SIZE);
+            return BodyPublishers.ofFile(f);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private static Path createFile(long nBytes) throws IOException {
+        String name = "f" + UNIQUE_NUMBERS.getAndIncrement();
+        Path f = Files.createFile(Path.of(name));
+        return Files.write(f, S.arrayOfNRandomBytes(nBytes));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return null;
+    }
+
+    @Override
+    public long maxElementsFromPublisher() {
+        return 21;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.io.InputStream;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Flow.Publisher;
+import java.util.function.Supplier;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersOfInputStream
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    public BodyPublishersOfInputStream() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        Supplier<InputStream> s = () -> S.inputStreamOfNReads((int) nElements);
+        return BodyPublishers.ofInputStream(s);
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.net.http.HttpRequest.BodyPublishers;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Flow.Publisher;
+
+/* See TckDriver.java for more information */
+public class BodyPublishersOfSubByteArray
+        extends FlowPublisherVerification<ByteBuffer> {
+
+    private static final int ELEMENT_SIZE = 16 * 1024;
+
+    public BodyPublishersOfSubByteArray() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFlowPublisher(long nElements) {
+        int prefixLen = S.randomIntUpTo(13);
+        int postfixLen = S.randomIntUpTo(17);
+        byte[] b = S.arrayOfNRandomBytes(nElements * ELEMENT_SIZE);
+        byte[] contents = new byte[prefixLen + b.length + postfixLen];
+        System.arraycopy(b, 0, contents, prefixLen, b.length);
+        return BodyPublishers.ofByteArray(contents, prefixLen, b.length);
+    }
+
+    @Override
+    public Publisher<ByteBuffer> createFailedFlowPublisher() {
+        return null;
+    }
+
+    @Override
+    public long maxElementsFromPublisher() {
+        return 21;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersBuffering
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersBuffering() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.buffering(BodySubscribers.discarding(),
+                                         S.randomIntUpTo(1024) + 1);
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersDiscarding
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersDiscarding() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.discarding();
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersFromLineSubscriber
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersFromLineSubscriber() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.fromLineSubscriber(
+                S.nonCompliantSubscriber());
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.scatterBuffer(
+                S.bufferOfNRandomASCIIBytes(element % 17));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersFromSubscriber
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersFromSubscriber() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        Subscriber<List<ByteBuffer>> sub = S.nonCompliantSubscriber();
+        return BodySubscribers.fromSubscriber(sub);
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.scatterBuffer(
+                S.bufferOfNRandomASCIIBytes(element % 17));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersMapping
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersMapping() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.mapping(BodySubscribers.ofByteArray(),
+                                       bytes -> bytes.length);
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfByteArray
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfByteArray() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofByteArray();
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfByteArrayConsumer
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfByteArrayConsumer() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofByteArrayConsumer(bytes -> { });
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfFile
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfFile() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofFile(Path.of("f1.bin"));
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfInputStream
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfInputStream() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofInputStream();
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfLines
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfLines() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofLines(StandardCharsets.UTF_8);
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.scatterBuffer(
+                S.bufferOfNRandomASCIIBytes(element % 17));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscriber;
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow.Publisher;
+import java.util.concurrent.Flow.Subscriber;
+import java.util.concurrent.Flow.Subscription;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfPublisher
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfPublisher() {
+        super(new TestEnvironment(450L));
+    }
+
+    /* The reason for overriding this method is that BodySubscribers.ofPublisher
+       is somewhat tricky. It is not an independent Subscriber, but rather
+       an adaptor from Subscriber to Publisher. Until the Subscriber that
+       subscribed to that resulting Publisher requests anything, nothing
+       happens. */
+    @Override
+    public void triggerFlowRequest(
+            Subscriber<? super List<ByteBuffer>> subscriber)
+    {
+        BodySubscriber<Publisher<List<ByteBuffer>>> sub =
+                (BodySubscriber<Publisher<List<ByteBuffer>>>) subscriber;
+        CompletionStage<Publisher<List<ByteBuffer>>> body = sub.getBody();
+        Publisher<List<ByteBuffer>> pub = body.toCompletableFuture().join();
+        pub.subscribe(new Subscriber<>() {
+
+            @Override
+            public void onSubscribe(Subscription subscription) {
+                subscription.request(Integer.MAX_VALUE);
+            }
+
+            @Override public void onNext(List<ByteBuffer> item) { }
+            @Override public void onError(Throwable throwable) { }
+            @Override public void onComplete() { }
+        });
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofPublisher();
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscriber;
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Flow.Publisher;
+import java.util.concurrent.Flow.Subscriber;
+import java.util.concurrent.Flow.Subscription;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfPublisher1
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfPublisher1() {
+        super(new TestEnvironment(450L));
+    }
+
+    /* The reason for overriding this method is that BodySubscribers.ofPublisher
+       is somewhat tricky. It is not an independent Subscriber, but rather
+       an adaptor from Subscriber to Publisher. Until the Subscriber that
+       subscribed to that resulting Publisher requests anything, nothing
+       happens. */
+    @Override
+    public void triggerFlowRequest(
+            Subscriber<? super List<ByteBuffer>> subscriber)
+    {
+        BodySubscriber<Publisher<List<ByteBuffer>>> sub =
+                (BodySubscriber<Publisher<List<ByteBuffer>>>) subscriber;
+        CompletionStage<Publisher<List<ByteBuffer>>> body = sub.getBody();
+        Publisher<List<ByteBuffer>> pub = body.toCompletableFuture().join();
+        pub.subscribe(new Subscriber<>() {
+
+            Subscription sub;
+
+            @Override
+            public void onSubscribe(Subscription subscription) {
+                (sub = subscription).request(1);
+            }
+
+            @Override public void onNext(List<ByteBuffer> item) {
+                sub.request(1);
+            }
+
+            @Override public void onError(Throwable throwable) { }
+            @Override public void onComplete() { }
+        });
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofPublisher();
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.net.http.HttpResponse.BodySubscriber;
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Publisher;
+import java.util.stream.Stream;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfPublisherPublisher
+        extends FlowPublisherVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfPublisherPublisher() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<List<ByteBuffer>> createFlowPublisher(long nElements) {
+        BodySubscriber<Publisher<List<ByteBuffer>>> sub =
+                BodySubscribers.ofPublisher();
+        Stream<List<ByteBuffer>> buffers =
+                Stream.generate(() -> S.listOfBuffersFromBufferOfNBytes(1024))
+                      .limit(nElements);
+        Publisher<List<ByteBuffer>> pub = S.publisherOfStream(buffers);
+        pub.subscribe(sub);
+        return sub.getBody().toCompletableFuture().join();
+    }
+
+    @Override
+    public Publisher<List<ByteBuffer>> createFailedFlowPublisher() {
+        BodySubscriber<Publisher<List<ByteBuffer>>> sub =
+                BodySubscribers.ofPublisher();
+        Publisher<List<ByteBuffer>> pub = S.newErroredPublisher();
+        pub.subscribe(sub);
+        return sub.getBody().toCompletableFuture().join();
+    }
+
+    @Override
+    public long maxElementsFromPublisher() {
+        return 21;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersOfString
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersOfString() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        return BodySubscribers.ofString(StandardCharsets.UTF_8);
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.scatterBuffer(
+                S.bufferOfNRandomASCIIBytes(element % 17));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification;
+
+import java.net.http.HttpResponse.BodySubscribers;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.concurrent.Flow.Subscriber;
+
+/* See TckDriver.java for more information */
+public class BodySubscribersReplacing
+        extends FlowSubscriberBlackboxVerification<List<ByteBuffer>> {
+
+    public BodySubscribersReplacing() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Subscriber<List<ByteBuffer>> createFlowSubscriber() {
+        /* it doesn't matter what we are replacing with */
+        return BodySubscribers.replacing(Boolean.TRUE);
+    }
+
+    @Override
+    public List<ByteBuffer> createElement(int element) {
+        return S.listOfBuffersFromBufferOfNBytes(element % 17);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Random;
+import java.util.concurrent.Flow.Publisher;
+import java.util.concurrent.Flow.Subscriber;
+import java.util.concurrent.Flow.Subscription;
+import java.util.stream.Stream;
+
+/*
+ * S for Support.
+ *
+ * Auxiliary methods for tests that check conformance with reactive streams
+ * specification.
+ *
+ * Short name is for the sake of convenience calling this class' static methods.
+ * It could've been called Support or TckSupport, but then we would need to
+ * place this class in its own package so as to use "import static".
+ */
+public class S {
+
+    private static final Random RANDOM = new SecureRandom();
+
+    private S() { }
+
+    public static List<ByteBuffer> listOfBuffersFromBufferOfNBytes(int nBytes) {
+        return scatterBuffer(bufferOfNRandomBytes(nBytes));
+    }
+
+    /*
+     * Spreads the remaining contents of the given byte buffer across a number
+     * of buffers put into a list.
+     */
+    public static List<ByteBuffer> scatterBuffer(ByteBuffer src) {
+        List<ByteBuffer> buffers = new ArrayList<>();
+        while (src.hasRemaining()) {
+            // We do not allow empty buffers ~~~~~~~~~~~~~~~~v
+            int capacity = RANDOM.nextInt(src.remaining()) + 1;
+            ByteBuffer b = ByteBuffer.allocate(capacity);
+            for (int i = 0; i < capacity; i++) {
+                b.put(src.get());
+            }
+            b.flip();
+            buffers.add(b);
+        }
+        return List.copyOf(buffers);
+    }
+
+    public static ByteBuffer bufferOfNRandomBytes(int capacity) {
+        return ByteBuffer.wrap(arrayOfNRandomBytes(capacity));
+    }
+
+    public static byte[] arrayOfNRandomBytes(int nBytes) {
+        byte[] contents = new byte[nBytes];
+        RANDOM.nextBytes(contents);
+        return contents;
+    }
+
+    public static InputStream inputStreamOfNReads(long n) {
+        return new NReadsInputStream(n);
+    }
+
+    /*
+     * Convenience method for testing publishers.
+     */
+    public static byte[] arrayOfNRandomBytes(long nBytes) {
+        return arrayOfNRandomBytes((int) nBytes);
+    }
+
+    public static ByteBuffer bufferOfNRandomASCIIBytes(int capacity) {
+        String alphaNumeric = "abcdefghijklmnopqrstuvwxyz1234567890";
+        StringBuilder builder = new StringBuilder(capacity);
+        for (int i = 0; i < capacity; i++) {
+            int idx = RANDOM.nextInt(alphaNumeric.length());
+            builder.append(alphaNumeric.charAt(idx));
+        }
+        return ByteBuffer.wrap(builder.toString().getBytes(
+                StandardCharsets.US_ASCII));
+    }
+
+    /*
+     * Returns a simple non-compliant Subscriber.
+     *
+     * This Subscriber is useful for testing our adaptors and wrappers, to make
+     * sure they do not delegate RS compliance to the underlying (and foreign to
+     * java.net.http codebase) Subscribers, but rather comply themselves.
+     *
+     * Here's an example:
+     *
+     *     public void onSubscribe(Subscription s) {
+     *         delegate.onSubscribe(s);
+     *     }
+     *
+     * The snippet above cannot be considered a good implementation of a
+     * Subscriber if `delegate` is an unknown Subscriber. In this case the
+     * implementation should independently check all the rules from the RS spec
+     * related to subscribers.
+     */
+    public static <T> Subscriber<T> nonCompliantSubscriber() {
+        return new Subscriber<>() {
+
+            @Override
+            public void onSubscribe(Subscription subscription) {
+                subscription.request(Long.MAX_VALUE);
+            }
+
+            @Override
+            public void onNext(T item) { }
+
+            @Override
+            public void onError(Throwable throwable) { }
+
+            @Override
+            public void onComplete() { }
+        };
+    }
+
+    public static int randomIntUpTo(int bound) {
+        return RANDOM.nextInt(bound);
+    }
+
+    /*
+     * Signals an error to its subscribers immediately after subscription.
+     */
+    public static <T> Publisher<T> newErroredPublisher() {
+        return subscriber -> {
+            subscriber.onSubscribe(new Subscription() {
+                @Override
+                public void request(long n) { }
+
+                @Override
+                public void cancel() { }
+            });
+            subscriber.onError(new IOException());
+        };
+    }
+
+    /*
+     * Publishes the elements obtained from the stream and signals completion.
+     * Can be cancelled, but cannot signal an error.
+     *
+     * This trivial ad-hoc implementation of Publisher was created so as to
+     * publish lists of byte buffers. We can publish ByteBuffer, but we can't
+     * seem to publish List<ByteBuffer> since there's no readily available
+     * publisher of those, nor there's a simple adaptor.
+     */
+    public static <T> Publisher<T> publisherOfStream(Stream<? extends T> stream)
+    {
+        if (stream == null) {
+            throw new NullPointerException();
+        }
+        return new Publisher<T>() {
+            @Override
+            public void subscribe(Subscriber<? super T> subscriber) {
+                if (subscriber == null) {
+                    throw new NullPointerException();
+                }
+                Subscription subscription = new Subscription() {
+
+                    boolean inOnNext; // recursion control
+                    volatile boolean cancelled;
+                    long demand;
+                    final Iterator<? extends T> supply = stream.iterator();
+
+                    @Override
+                    public void request(long n) {
+                        demand = demand + n < 0 ? Long.MAX_VALUE : demand + n;
+                        if (inOnNext) {
+                            return;
+                        }
+                        if (cancelled)
+                            return;
+                        if (n <= 0) {
+                            cancelled = true;
+                            subscriber.onError(new IllegalArgumentException(
+                                    "non-positive subscription request"));
+                            return;
+                        }
+                        while (supply.hasNext() && demand > 0 && !cancelled) {
+                            demand--;
+                            inOnNext = true;
+                            try {
+                                T item = supply.next();
+                                subscriber.onNext(item);
+                            } finally {
+                                inOnNext = false;
+                            }
+                        }
+                        if (!supply.hasNext()) {
+                            cancelled = true;
+                            subscriber.onComplete();
+                        }
+                    }
+
+                    @Override
+                    public void cancel() {
+                        cancelled = true;
+                    }
+                };
+                subscriber.onSubscribe(subscription);
+            }
+        };
+    }
+
+    static final class NReadsInputStream extends InputStream {
+
+        private static final int EOF = -1;
+        private long readsLeft;
+
+        NReadsInputStream(long n) {
+            if (n < 0) {
+                throw new IllegalArgumentException(String.valueOf(n));
+            }
+            this.readsLeft = n;
+        }
+
+        @Override
+        public int read() {
+            if (readsLeft == 0L) {
+                return EOF;
+            }
+            readsLeft--;
+            return S.randomIntUpTo(256);
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) {
+            Objects.checkFromIndexSize(off, len, b.length);
+            // Must return 0 if len == 0,
+            // even if there are no more reads left
+            if (len == 0) {
+                return 0;
+            }
+            if (readsLeft == 0L) {
+                return EOF;
+            }
+            readsLeft--;
+            // At least one byte MUST be read, but we can read
+            // less than `len` bytes
+            int r = RANDOM.nextInt(len) + 1;
+            for (int i = 0; i < r; i++) {
+                b[i] = (byte) randomIntUpTo(256);
+            }
+            return r;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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 org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.FlowPublisherVerification;
+
+import java.util.concurrent.Flow.Publisher;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+/* See TckDriver.java for more information */
+public class SPublisherOfStream
+        extends FlowPublisherVerification<Long> {
+
+    public SPublisherOfStream() {
+        super(new TestEnvironment(450L));
+    }
+
+    @Override
+    public Publisher<Long> createFlowPublisher(long nElements) {
+        Stream<Long> s = LongStream.range(0, nElements).boxed();
+        return S.publisherOfStream(s);
+    }
+
+    @Override
+    public Publisher<Long> createFailedFlowPublisher() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019, 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 org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class STest {
+
+    @DataProvider(name = "bufferSizes")
+    public static Object[][] bufferSizes() {
+        return new Object[][]{
+                { 1},
+                { 2},
+                { 3},
+                { 4},
+                {16},
+                {17},
+        };
+    }
+
+    @DataProvider
+    public static Object[][] inputStream() {
+        return new Object[][] {
+                {  0,   1},
+                {  1,   2},
+                {  1,   3},
+                {  1,   4},
+                {  2,   1},
+                {  2,   2},
+                {  2,   3},
+                {  2,   4},
+                {  2,  13},
+                {  3,   1},
+                {  3,   2},
+                {  3,   3},
+                {  3,   4},
+                {  3,  17},
+                {  4,   1},
+                {  4,   2},
+                {  4,   3},
+                {  4,   4},
+                {  4,   5},
+                { 13,   1},
+                { 13,   2},
+                { 13,  13},
+                { 16,  18},
+                { 17,   2},
+                {255,   1},
+                {256, 255},
+                {257, 267},
+        };
+    }
+
+    @Test
+    public void testScatter0() {
+        List<ByteBuffer> buffers = S.scatterBuffer(
+                ByteBuffer.allocate(0));
+        assertEquals(buffers.size(), 0);
+    }
+
+    @Test(dataProvider = "bufferSizes")
+    public void testScatterN(int n) {
+        final ByteBuffer src = S.bufferOfNRandomBytes(n);
+        final int srcLength = src.remaining();
+        ByteBuffer copy = ByteBuffer.wrap(Arrays.copyOf(src.array(),
+                                                        src.array().length));
+        List<ByteBuffer> buffers = S.scatterBuffer(src);
+        int m = 0;
+        for (ByteBuffer b : buffers) {
+            m += b.remaining();
+            while (b.hasRemaining() & copy.hasRemaining()) {
+                assertEquals(b.get(), copy.get());
+            }
+        }
+        assertEquals(m, srcLength);
+    }
+
+    @Test(dataProvider = "inputStream")
+    public void testInputStreamOfNReads(int n, int capacity) throws IOException {
+        InputStream s = S.inputStreamOfNReads(n);
+        int count = 0;
+        byte[] b = new byte[capacity];
+        while (s.read(b) != -1) {
+            count++;
+        }
+        assertEquals(count, n);
+        assertTrue(s.read() == -1);
+        assertTrue(s.read(b) == -1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019, 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 8226602
+ * @summary Tests convenience reactive primitives with RS TCK
+ *
+ * @library ../reactivestreams-tck
+ * @build S
+ *
+ * @compile -encoding UTF-8 SPublisherOfStream.java
+ *
+ * @compile -encoding UTF-8 BodyPublishersFromPublisher.java
+ * @compile -encoding UTF-8 BodyPublishersNoBody.java
+ * @compile -encoding UTF-8 BodyPublishersOfByteArray.java
+ * @compile -encoding UTF-8 BodyPublishersOfByteArrays.java
+ * @compile -encoding UTF-8 BodyPublishersOfFile.java
+ * @compile -encoding UTF-8 BodyPublishersOfInputStream.java
+ * @compile -encoding UTF-8 BodyPublishersOfSubByteArray.java
+ *
+ * @compile -encoding UTF-8 BodySubscribersBuffering.java
+ * @compile -encoding UTF-8 BodySubscribersDiscarding.java
+ * @compile -encoding UTF-8 BodySubscribersFromLineSubscriber.java
+ * @compile -encoding UTF-8 BodySubscribersFromSubscriber.java
+ * @compile -encoding UTF-8 BodySubscribersMapping.java
+ * @compile -encoding UTF-8 BodySubscribersOfByteArray.java
+ * @compile -encoding UTF-8 BodySubscribersOfByteArrayConsumer.java
+ * @compile -encoding UTF-8 BodySubscribersOfFile.java
+ * @compile -encoding UTF-8 BodySubscribersOfInputStream.java
+ * @compile -encoding UTF-8 BodySubscribersOfLines.java
+ * @compile -encoding UTF-8 BodySubscribersOfPublisher.java
+ * @compile -encoding UTF-8 BodySubscribersOfPublisher1.java
+ * @compile -encoding UTF-8 BodySubscribersOfPublisherPublisher.java
+ * @compile -encoding UTF-8 BodySubscribersOfString.java
+ * @compile -encoding UTF-8 BodySubscribersReplacing.java
+ *
+ * @run testng/othervm STest
+ * @run testng/othervm SPublisherOfStream
+ *
+ * @run testng/othervm BodyPublishersFromPublisher
+ * @run testng/othervm BodyPublishersNoBody
+ * @run testng/othervm BodyPublishersOfByteArray
+ * @run testng/othervm BodyPublishersOfByteArrays
+ * @run testng/othervm BodyPublishersOfFile
+ * @run testng/othervm BodyPublishersOfInputStream
+ * @run testng/othervm BodyPublishersOfSubByteArray
+ *
+ * @run testng/othervm BodySubscribersBuffering
+ * @run testng/othervm BodySubscribersDiscarding
+ * @run testng/othervm BodySubscribersFromLineSubscriber
+ * @run testng/othervm BodySubscribersFromSubscriber
+ * @run testng/othervm BodySubscribersMapping
+ * @run testng/othervm BodySubscribersOfByteArray
+ * @run testng/othervm BodySubscribersOfByteArrayConsumer
+ * @run testng/othervm BodySubscribersOfFile
+ * @run testng/othervm BodySubscribersOfInputStream
+ * @run testng/othervm BodySubscribersOfLines
+ * @run testng/othervm BodySubscribersOfPublisher
+ * @run testng/othervm BodySubscribersOfPublisher1
+ * @run testng/othervm BodySubscribersOfPublisherPublisher
+ * @run testng/othervm BodySubscribersOfString
+ * @run testng/othervm BodySubscribersReplacing
+ *
+ * @key randomness
+ */
+public class TckDriver {
+   /*
+        #### General Information
+
+        1. This JTREG test aggregates multiple TestNG tests. This is because
+        these tests share a common library (reactivestreams-tck), and we don't
+        want this library to be compiled separately for each of those tests.
+
+        2. Tests that use RS TCK are compiled with the UTF-8 encoding. This is
+        performed for the sake of reactivestreams-tck. We don't want to patch
+        the TCK because of the extra merging work in the future, should we bring
+        update(s) from the RS repo.
+
+        #### Tests
+
+        1. The purpose of each test should be easily digestible. The name of the
+        test is derived from the very entity the test exercises. For example,
+
+            the BodyPublishersOfFile test exercises the BodyPublisher obtained
+            by calling BodyPublishers.ofFile(Path)
+
+            the BodySubscribersOfFile test exercises the BodySubscriber obtained
+            by calling BodySubscribers.ofFile(Path)
+
+        2. RS TCK requires PublisherVerification tests to produce publishers
+        capable of emitting a certain number of elements. In order to achieve
+        this, we use some knowledge of the internal workings of our publishers.
+        An example would be a chunk size a publisher uses to deliver a portion
+        of data. Without knowing that it is not possible to guarantee that the
+        publisher will emit a particular number of elements.
+
+        3. Typically our publishers cannot be created in a known failed state.
+        In this case the corresponding `createFailedFlowPublisher` method
+        returns `null`.
+
+        4. SubscriberBlackBoxVerification uses the `createElement(int element)`
+        method. Our implementations usually cap the amount of data created by
+        this method, because it's not known beforehand how big the `element`
+        value is. Hence, sometimes there's code like as follows:
+
+            @Override
+            public List<ByteBuffer> createElement(int element) {
+                return scatterBuffer(
+                        bufferOfNRandomASCIIBytes(element % 17));
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
+            }
+
+        5. The amount of testing RS TCK performs on a publisher seems to depend
+        on the number of elements this publisher reports it can emit. Sometimes
+        a code like the following can be seen in the tests:
+
+                @Override public long maxElementsFromPublisher() {
+                    return 21;
+                ~~~~~~~~~~~^
+                }
+
+        This magic number is a result of trial and error and seems to unlock
+        most of the tests. Reporting big values (e.g. Long.MAX_VALUE - 1) is
+        not an option for most of our publishers because they require to have
+        all the elements upfront.
+
+        6. It doesn't seem currently feasible to provide SubscriberWhiteboxVerification
+        tests as a) it's not clear how much better the coverage is and b) it's
+        significantly harder to code that.
+
+        #### S (Support)
+
+        Support utilities are being tested (STest) too.
+    */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams;
+
+import java.util.concurrent.Flow;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Bridge between Reactive Streams API and the Java 9 {@link java.util.concurrent.Flow} API.
+ */
+public final class FlowAdapters {
+    /** Utility class. */
+    private FlowAdapters() {
+        throw new IllegalStateException("No instances!");
+    }
+
+    /**
+     * Converts a Flow Publisher into a Reactive Streams Publisher.
+     * @param <T> the element type
+     * @param flowPublisher the source Flow Publisher to convert
+     * @return the equivalent Reactive Streams Publisher
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> org.reactivestreams.Publisher<T> toPublisher(
+            Flow.Publisher<? extends T> flowPublisher) {
+        requireNonNull(flowPublisher, "flowPublisher");
+        final org.reactivestreams.Publisher<T> publisher;
+        if (flowPublisher instanceof FlowPublisherFromReactive) {
+            publisher = (org.reactivestreams.Publisher<T>)(((FlowPublisherFromReactive<T>)flowPublisher).reactiveStreams);
+        } else if (flowPublisher instanceof org.reactivestreams.Publisher) {
+            publisher = (org.reactivestreams.Publisher<T>)flowPublisher;
+        } else {
+            publisher = new ReactivePublisherFromFlow<T>(flowPublisher);
+        }
+        return publisher;
+    }
+
+    /**
+     * Converts a Reactive Streams Publisher into a Flow Publisher.
+     * @param <T> the element type
+     * @param reactiveStreamsPublisher the source Reactive Streams Publisher to convert
+     * @return the equivalent Flow Publisher
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Flow.Publisher<T> toFlowPublisher(
+            org.reactivestreams.Publisher<? extends T> reactiveStreamsPublisher
+    ) {
+        requireNonNull(reactiveStreamsPublisher, "reactiveStreamsPublisher");
+        final Flow.Publisher<T> flowPublisher;
+        if (reactiveStreamsPublisher instanceof ReactivePublisherFromFlow) {
+            flowPublisher = (Flow.Publisher<T>)(((ReactivePublisherFromFlow<T>)reactiveStreamsPublisher).flow);
+        } else if (reactiveStreamsPublisher instanceof Flow.Publisher) {
+            flowPublisher = (Flow.Publisher<T>)reactiveStreamsPublisher;
+        } else {
+            flowPublisher = new FlowPublisherFromReactive<T>(reactiveStreamsPublisher);
+        }
+        return flowPublisher;
+    }
+
+    /**
+     * Converts a Flow Processor into a Reactive Streams Processor.
+     * @param <T> the input value type
+     * @param <U> the output value type
+     * @param flowProcessor the source Flow Processor to convert
+     * @return the equivalent Reactive Streams Processor
+     */
+    @SuppressWarnings("unchecked")
+    public static <T, U> org.reactivestreams.Processor<T, U> toProcessor(
+            Flow.Processor<? super T, ? extends U> flowProcessor
+    ) {
+        requireNonNull(flowProcessor, "flowProcessor");
+        final org.reactivestreams.Processor<T, U> processor;
+        if (flowProcessor instanceof FlowToReactiveProcessor) {
+            processor = (org.reactivestreams.Processor<T, U>)(((FlowToReactiveProcessor<T, U>)flowProcessor).reactiveStreams);
+        } else if (flowProcessor instanceof org.reactivestreams.Processor) {
+            processor = (org.reactivestreams.Processor<T, U>)flowProcessor;
+        } else {
+            processor = new ReactiveToFlowProcessor<T, U>(flowProcessor);
+        }
+        return processor;
+    }
+
+    /**
+     * Converts a Reactive Streams Processor into a Flow Processor.
+     * @param <T> the input value type
+     * @param <U> the output value type
+     * @param reactiveStreamsProcessor the source Reactive Streams Processor to convert
+     * @return the equivalent Flow Processor
+     */
+    @SuppressWarnings("unchecked")
+    public static <T, U> Flow.Processor<T, U> toFlowProcessor(
+            org.reactivestreams.Processor<? super T, ? extends U> reactiveStreamsProcessor
+        ) {
+        requireNonNull(reactiveStreamsProcessor, "reactiveStreamsProcessor");
+        final Flow.Processor<T, U> flowProcessor;
+        if (reactiveStreamsProcessor instanceof ReactiveToFlowProcessor) {
+            flowProcessor = (Flow.Processor<T, U>)(((ReactiveToFlowProcessor<T, U>)reactiveStreamsProcessor).flow);
+        } else if (reactiveStreamsProcessor instanceof Flow.Processor) {
+            flowProcessor = (Flow.Processor<T, U>)reactiveStreamsProcessor;
+        } else {
+            flowProcessor = new FlowToReactiveProcessor<T, U>(reactiveStreamsProcessor);
+        }
+        return flowProcessor;
+    }
+
+    /**
+     * Converts a Reactive Streams Subscriber into a Flow Subscriber.
+     * @param <T> the input and output value type
+     * @param reactiveStreamsSubscriber the Reactive Streams Subscriber instance to convert
+     * @return the equivalent Flow Subscriber
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Flow.Subscriber<T> toFlowSubscriber(org.reactivestreams.Subscriber<T> reactiveStreamsSubscriber) {
+        requireNonNull(reactiveStreamsSubscriber, "reactiveStreamsSubscriber");
+        final Flow.Subscriber<T> flowSubscriber;
+        if (reactiveStreamsSubscriber instanceof ReactiveToFlowSubscriber) {
+            flowSubscriber = (Flow.Subscriber<T>)((ReactiveToFlowSubscriber<T>)reactiveStreamsSubscriber).flow;
+        } else if (reactiveStreamsSubscriber instanceof Flow.Subscriber) {
+            flowSubscriber = (Flow.Subscriber<T>)reactiveStreamsSubscriber;
+        } else {
+            flowSubscriber = new FlowToReactiveSubscriber<T>(reactiveStreamsSubscriber);
+        }
+        return flowSubscriber;
+    }
+
+    /**
+     * Converts a Flow Subscriber into a Reactive Streams Subscriber.
+     * @param <T> the input and output value type
+     * @param flowSubscriber the Flow Subscriber instance to convert
+     * @return the equivalent Reactive Streams Subscriber
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> org.reactivestreams.Subscriber<T> toSubscriber(Flow.Subscriber<T> flowSubscriber) {
+        requireNonNull(flowSubscriber, "flowSubscriber");
+        final org.reactivestreams.Subscriber<T> subscriber;
+        if (flowSubscriber instanceof FlowToReactiveSubscriber) {
+            subscriber = (org.reactivestreams.Subscriber<T>)((FlowToReactiveSubscriber<T>)flowSubscriber).reactiveStreams;
+        } else if (flowSubscriber instanceof org.reactivestreams.Subscriber) {
+            subscriber = (org.reactivestreams.Subscriber<T>)flowSubscriber;
+        } else {
+            subscriber = new ReactiveToFlowSubscriber<T>(flowSubscriber);
+        }
+        return subscriber;
+    }
+
+    /**
+     * Wraps a Reactive Streams Subscription and converts the calls to a Flow Subscription.
+     */
+    static final class FlowToReactiveSubscription implements Flow.Subscription {
+        final org.reactivestreams.Subscription reactiveStreams;
+
+        public FlowToReactiveSubscription(org.reactivestreams.Subscription reactive) {
+            this.reactiveStreams = reactive;
+        }
+
+        @Override
+        public void request(long n) {
+            reactiveStreams.request(n);
+        }
+
+        @Override
+        public void cancel() {
+            reactiveStreams.cancel();
+        }
+
+    }
+
+    /**
+     * Wraps a Flow Subscription and converts the calls to a Reactive Streams Subscription.
+     */
+    static final class ReactiveToFlowSubscription implements org.reactivestreams.Subscription {
+        final Flow.Subscription flow;
+
+        public ReactiveToFlowSubscription(Flow.Subscription flow) {
+            this.flow = flow;
+        }
+
+        @Override
+        public void request(long n) {
+            flow.request(n);
+        }
+
+        @Override
+        public void cancel() {
+            flow.cancel();
+        }
+
+
+    }
+
+    /**
+     * Wraps a Reactive Streams Subscriber and forwards methods of the Flow Subscriber to it.
+     * @param <T> the element type
+     */
+    static final class FlowToReactiveSubscriber<T> implements Flow.Subscriber<T> {
+        final org.reactivestreams.Subscriber<? super T> reactiveStreams;
+
+        public FlowToReactiveSubscriber(org.reactivestreams.Subscriber<? super T> reactive) {
+            this.reactiveStreams = reactive;
+        }
+
+        @Override
+        public void onSubscribe(Flow.Subscription subscription) {
+            reactiveStreams.onSubscribe((subscription == null) ? null : new ReactiveToFlowSubscription(subscription));
+        }
+
+        @Override
+        public void onNext(T item) {
+            reactiveStreams.onNext(item);
+        }
+
+        @Override
+        public void onError(Throwable throwable) {
+            reactiveStreams.onError(throwable);
+        }
+
+        @Override
+        public void onComplete() {
+            reactiveStreams.onComplete();
+        }
+
+    }
+
+    /**
+     * Wraps a Flow Subscriber and forwards methods of the Reactive Streams Subscriber to it.
+     * @param <T> the element type
+     */
+    static final class ReactiveToFlowSubscriber<T> implements org.reactivestreams.Subscriber<T> {
+        final Flow.Subscriber<? super T> flow;
+
+        public ReactiveToFlowSubscriber(Flow.Subscriber<? super T> flow) {
+            this.flow = flow;
+        }
+
+        @Override
+        public void onSubscribe(org.reactivestreams.Subscription subscription) {
+            flow.onSubscribe((subscription == null) ? null : new FlowToReactiveSubscription(subscription));
+        }
+
+        @Override
+        public void onNext(T item) {
+            flow.onNext(item);
+        }
+
+        @Override
+        public void onError(Throwable throwable) {
+            flow.onError(throwable);
+        }
+
+        @Override
+        public void onComplete() {
+            flow.onComplete();
+        }
+
+    }
+
+    /**
+     * Wraps a Flow Processor and forwards methods of the Reactive Streams Processor to it.
+     * @param <T> the input type
+     * @param <U> the output type
+     */
+    static final class ReactiveToFlowProcessor<T, U> implements org.reactivestreams.Processor<T, U> {
+        final Flow.Processor<? super T, ? extends U> flow;
+
+        public ReactiveToFlowProcessor(Flow.Processor<? super T, ? extends U> flow) {
+            this.flow = flow;
+        }
+
+        @Override
+        public void onSubscribe(org.reactivestreams.Subscription subscription) {
+            flow.onSubscribe((subscription == null) ? null : new FlowToReactiveSubscription(subscription));
+        }
+
+        @Override
+        public void onNext(T t) {
+            flow.onNext(t);
+        }
+
+        @Override
+        public void onError(Throwable t) {
+            flow.onError(t);
+        }
+
+        @Override
+        public void onComplete() {
+            flow.onComplete();
+        }
+
+        @Override
+        public void subscribe(org.reactivestreams.Subscriber<? super U> s) {
+            flow.subscribe((s == null) ? null : new FlowToReactiveSubscriber<U>(s));
+        }
+    }
+
+    /**
+     * Wraps a Reactive Streams Processor and forwards methods of the Flow Processor to it.
+     * @param <T> the input type
+     * @param <U> the output type
+     */
+    static final class FlowToReactiveProcessor<T, U> implements Flow.Processor<T, U> {
+        final org.reactivestreams.Processor<? super T, ? extends U> reactiveStreams;
+
+        public FlowToReactiveProcessor(org.reactivestreams.Processor<? super T, ? extends U> reactive) {
+            this.reactiveStreams = reactive;
+        }
+
+        @Override
+        public void onSubscribe(Flow.Subscription subscription) {
+            reactiveStreams.onSubscribe((subscription == null) ? null : new ReactiveToFlowSubscription(subscription));
+        }
+
+        @Override
+        public void onNext(T t) {
+            reactiveStreams.onNext(t);
+        }
+
+        @Override
+        public void onError(Throwable t) {
+            reactiveStreams.onError(t);
+        }
+
+        @Override
+        public void onComplete() {
+            reactiveStreams.onComplete();
+        }
+
+        @Override
+        public void subscribe(Flow.Subscriber<? super U> s) {
+            reactiveStreams.subscribe((s == null) ? null : new ReactiveToFlowSubscriber<U>(s));
+        }
+    }
+
+    /**
+     * Reactive Streams Publisher that wraps a Flow Publisher.
+     * @param <T> the element type
+     */
+    static final class ReactivePublisherFromFlow<T> implements org.reactivestreams.Publisher<T> {
+        final Flow.Publisher<? extends T> flow;
+
+        public ReactivePublisherFromFlow(Flow.Publisher<? extends T> flowPublisher) {
+            this.flow = flowPublisher;
+        }
+
+        @Override
+        public void subscribe(org.reactivestreams.Subscriber<? super T> reactive) {
+            flow.subscribe((reactive == null) ? null : new FlowToReactiveSubscriber<T>(reactive));
+        }
+    }
+
+    /**
+     * Flow Publisher that wraps a Reactive Streams Publisher.
+     * @param <T> the element type
+     */
+    static final class FlowPublisherFromReactive<T> implements Flow.Publisher<T> {
+
+        final org.reactivestreams.Publisher<? extends T> reactiveStreams;
+
+        public FlowPublisherFromReactive(org.reactivestreams.Publisher<? extends T> reactivePublisher) {
+            this.reactiveStreams = reactivePublisher;
+        }
+
+        @Override
+        public void subscribe(Flow.Subscriber<? super T> flow) {
+            reactiveStreams.subscribe((flow == null) ? null : new ReactiveToFlowSubscriber<T>(flow));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams;
+
+/**
+ * A Processor represents a processing stage—which is both a {@link Subscriber}
+ * and a {@link Publisher} and obeys the contracts of both.
+ *
+ * @param <T> the type of element signaled to the {@link Subscriber}
+ * @param <R> the type of element signaled by the {@link Publisher}
+ */
+public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams;
+
+/**
+ * A {@link Publisher} is a provider of a potentially unbounded number of sequenced elements, publishing them according to
+ * the demand received from its {@link Subscriber}(s).
+ * <p>
+ * A {@link Publisher} can serve multiple {@link Subscriber}s subscribed {@link #subscribe(Subscriber)} dynamically
+ * at various points in time.
+ *
+ * @param <T> the type of element signaled.
+ */
+public interface Publisher<T> {
+
+    /**
+     * Request {@link Publisher} to start streaming data.
+     * <p>
+     * This is a "factory method" and can be called multiple times, each time starting a new {@link Subscription}.
+     * <p>
+     * Each {@link Subscription} will work for only a single {@link Subscriber}.
+     * <p>
+     * A {@link Subscriber} should only subscribe once to a single {@link Publisher}.
+     * <p>
+     * If the {@link Publisher} rejects the subscription attempt or otherwise fails it will
+     * signal the error via {@link Subscriber#onError}.
+     *
+     * @param s the {@link Subscriber} that will consume signals from this {@link Publisher}
+     */
+    public void subscribe(Subscriber<? super T> s);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams;
+
+/**
+ * Will receive call to {@link #onSubscribe(Subscription)} once after passing an instance of {@link Subscriber} to {@link Publisher#subscribe(Subscriber)}.
+ * <p>
+ * No further notifications will be received until {@link Subscription#request(long)} is called.
+ * <p>
+ * After signaling demand:
+ * <ul>
+ * <li>One or more invocations of {@link #onNext(Object)} up to the maximum number defined by {@link Subscription#request(long)}</li>
+ * <li>Single invocation of {@link #onError(Throwable)} or {@link Subscriber#onComplete()} which signals a terminal state after which no further events will be sent.
+ * </ul>
+ * <p>
+ * Demand can be signaled via {@link Subscription#request(long)} whenever the {@link Subscriber} instance is capable of handling more.
+ *
+ * @param <T> the type of element signaled.
+ */
+public interface Subscriber<T> {
+    /**
+     * Invoked after calling {@link Publisher#subscribe(Subscriber)}.
+     * <p>
+     * No data will start flowing until {@link Subscription#request(long)} is invoked.
+     * <p>
+     * It is the responsibility of this {@link Subscriber} instance to call {@link Subscription#request(long)} whenever more data is wanted.
+     * <p>
+     * The {@link Publisher} will send notifications only in response to {@link Subscription#request(long)}.
+     *
+     * @param s
+     *            {@link Subscription} that allows requesting data via {@link Subscription#request(long)}
+     */
+    public void onSubscribe(Subscription s);
+
+    /**
+     * Data notification sent by the {@link Publisher} in response to requests to {@link Subscription#request(long)}.
+     *
+     * @param t the element signaled
+     */
+    public void onNext(T t);
+
+    /**
+     * Failed terminal state.
+     * <p>
+     * No further events will be sent even if {@link Subscription#request(long)} is invoked again.
+     *
+     * @param t the throwable signaled
+     */
+    public void onError(Throwable t);
+
+    /**
+     * Successful terminal state.
+     * <p>
+     * No further events will be sent even if {@link Subscription#request(long)} is invoked again.
+     */
+    public void onComplete();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams;
+
+/**
+ * A {@link Subscription} represents a one-to-one lifecycle of a {@link Subscriber} subscribing to a {@link Publisher}.
+ * <p>
+ * It can only be used once by a single {@link Subscriber}.
+ * <p>
+ * It is used to both signal desire for data and cancel demand (and allow resource cleanup).
+ *
+ */
+public interface Subscription {
+    /**
+     * No events will be sent by a {@link Publisher} until demand is signaled via this method.
+     * <p>
+     *  It can be called however often and whenever needed—but if the outstanding cumulative demand ever becomes Long.MAX_VALUE or more,
+     *  it may be treated by the {@link Publisher} as "effectively unbounded".
+     * <p>
+     * Whatever has been requested can be sent by the {@link Publisher} so only signal demand for what can be safely handled.
+     * <p>
+     * A {@link Publisher} can send less than is requested if the stream ends but
+     * then must emit either {@link Subscriber#onError(Throwable)} or {@link Subscriber#onComplete()}.
+     *
+     * @param n the strictly positive number of elements to requests to the upstream {@link Publisher}
+     */
+    public void request(long n);
+
+    /**
+     * Request the {@link Publisher} to stop sending data and clean up resources.
+     * <p>
+     * Data may still be sent to meet previously signalled demand after calling cancel.
+     */
+    public void cancel();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.example.unicast;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+
+import java.util.Iterator;
+import java.util.Collections;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * AsyncIterablePublisher is an implementation of Reactive Streams `Publisher`
+ * which executes asynchronously, using a provided `Executor` and produces elements
+ * from a given `Iterable` in a "unicast" configuration to its `Subscribers`.
+ *
+ * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden.
+ */
+public class AsyncIterablePublisher<T> implements Publisher<T> {
+  private final static int DEFAULT_BATCHSIZE = 1024;
+
+  private final Iterable<T> elements; // This is our data source / generator
+  private final Executor executor; // This is our thread pool, which will make sure that our Publisher runs asynchronously to its Subscribers
+  private final int batchSize; // In general, if one uses an `Executor`, one should be nice nad not hog a thread for too long, this is the cap for that, in elements
+
+  public AsyncIterablePublisher(final Iterable<T> elements, final Executor executor) {
+    this(elements, DEFAULT_BATCHSIZE, executor);
+  }
+
+  public AsyncIterablePublisher(final Iterable<T> elements, final int batchSize, final Executor executor) {
+    if (elements == null) throw null;
+    if (executor == null) throw null;
+    if (batchSize < 1) throw new IllegalArgumentException("batchSize must be greater than zero!");
+    this.elements = elements;
+    this.executor = executor;
+    this.batchSize = batchSize;
+  }
+
+  @Override
+  public void subscribe(final Subscriber<? super T> s) {
+    // As per rule 1.11, we have decided to support multiple subscribers in a unicast configuration
+    // for this `Publisher` implementation.
+    // As per 2.13, this method must return normally (i.e. not throw)
+    new SubscriptionImpl(s).init();
+  }
+
+  // These represent the protocol of the `AsyncIterablePublishers` SubscriptionImpls
+  static interface Signal {};
+  enum Cancel implements Signal { Instance; };
+  enum Subscribe implements Signal { Instance; };
+  enum Send implements Signal { Instance; };
+  static final class Request implements Signal {
+    final long n;
+    Request(final long n) {
+      this.n = n;
+    }
+  };
+
+  // This is our implementation of the Reactive Streams `Subscription`,
+  // which represents the association between a `Publisher` and a `Subscriber`.
+  final class SubscriptionImpl implements Subscription, Runnable {
+    final Subscriber<? super T> subscriber; // We need a reference to the `Subscriber` so we can talk to it
+    private boolean cancelled = false; // This flag will track whether this `Subscription` is to be considered cancelled or not
+    private long demand = 0; // Here we track the current demand, i.e. what has been requested but not yet delivered
+    private Iterator<T> iterator; // This is our cursor into the data stream, which we will send to the `Subscriber`
+
+    SubscriptionImpl(final Subscriber<? super T> subscriber) {
+      // As per rule 1.09, we need to throw a `java.lang.NullPointerException` if the `Subscriber` is `null`
+      if (subscriber == null) throw null;
+      this.subscriber = subscriber;
+    }
+
+    // This `ConcurrentLinkedQueue` will track signals that are sent to this `Subscription`, like `request` and `cancel`
+    private final ConcurrentLinkedQueue<Signal> inboundSignals = new ConcurrentLinkedQueue<Signal>();
+
+    // We are using this `AtomicBoolean` to make sure that this `Subscription` doesn't run concurrently with itself,
+    // which would violate rule 1.3 among others (no concurrent notifications).
+    private final AtomicBoolean on = new AtomicBoolean(false);
+
+    // This method will register inbound demand from our `Subscriber` and validate it against rule 3.9 and rule 3.17
+    private void doRequest(final long n) {
+      if (n < 1)
+        terminateDueTo(new IllegalArgumentException(subscriber + " violated the Reactive Streams rule 3.9 by requesting a non-positive number of elements."));
+      else if (demand + n < 1) {
+        // As governed by rule 3.17, when demand overflows `Long.MAX_VALUE` we treat the signalled demand as "effectively unbounded"
+        demand = Long.MAX_VALUE;  // Here we protect from the overflow and treat it as "effectively unbounded"
+        doSend(); // Then we proceed with sending data downstream
+      } else {
+        demand += n; // Here we record the downstream demand
+        doSend(); // Then we can proceed with sending data downstream
+      }
+    }
+
+    // This handles cancellation requests, and is idempotent, thread-safe and not synchronously performing heavy computations as specified in rule 3.5
+    private void doCancel() {
+      cancelled = true;
+    }
+
+    // Instead of executing `subscriber.onSubscribe` synchronously from within `Publisher.subscribe`
+    // we execute it asynchronously, this is to avoid executing the user code (`Iterable.iterator`) on the calling thread.
+    // It also makes it easier to follow rule 1.9
+    private void doSubscribe() {
+      try {
+        iterator = elements.iterator();
+        if (iterator == null)
+          iterator = Collections.<T>emptyList().iterator(); // So we can assume that `iterator` is never null
+      } catch(final Throwable t) {
+        subscriber.onSubscribe(new Subscription() { // We need to make sure we signal onSubscribe before onError, obeying rule 1.9
+          @Override public void cancel() {}
+          @Override public void request(long n) {}
+        });
+        terminateDueTo(t); // Here we send onError, obeying rule 1.09
+      }
+
+      if (!cancelled) {
+        // Deal with setting up the subscription with the subscriber
+        try {
+          subscriber.onSubscribe(this);
+        } catch(final Throwable t) { // Due diligence to obey 2.13
+          terminateDueTo(new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onSubscribe.", t));
+        }
+
+        // Deal with already complete iterators promptly
+        boolean hasElements = false;
+        try {
+          hasElements = iterator.hasNext();
+        } catch(final Throwable t) {
+          terminateDueTo(t); // If hasNext throws, there's something wrong and we need to signal onError as per 1.2, 1.4,
+        }
+
+        // If we don't have anything to deliver, we're already done, so lets do the right thing and
+        // not wait for demand to deliver `onComplete` as per rule 1.2 and 1.3
+        if (!hasElements) {
+          try {
+            doCancel(); // Rule 1.6 says we need to consider the `Subscription` cancelled when `onComplete` is signalled
+            subscriber.onComplete();
+          } catch(final Throwable t) { // As per rule 2.13, `onComplete` is not allowed to throw exceptions, so we do what we can, and log this.
+            (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onComplete.", t)).printStackTrace(System.err);
+          }
+        }
+      }
+    }
+
+    // This is our behavior for producing elements downstream
+    private void doSend() {
+      try {
+        // In order to play nice with the `Executor` we will only send at-most `batchSize` before
+        // rescheduing ourselves and relinquishing the current thread.
+        int leftInBatch = batchSize;
+        do {
+          T next;
+          boolean hasNext;
+          try {
+            next = iterator.next(); // We have already checked `hasNext` when subscribing, so we can fall back to testing -after- `next` is called.
+            hasNext = iterator.hasNext(); // Need to keep track of End-of-Stream
+          } catch (final Throwable t) {
+            terminateDueTo(t); // If `next` or `hasNext` throws (they can, since it is user-provided), we need to treat the stream as errored as per rule 1.4
+            return;
+          }
+          subscriber.onNext(next); // Then we signal the next element downstream to the `Subscriber`
+          if (!hasNext) { // If we are at End-of-Stream
+            doCancel(); // We need to consider this `Subscription` as cancelled as per rule 1.6
+            subscriber.onComplete(); // Then we signal `onComplete` as per rule 1.2 and 1.5
+          }
+        } while (!cancelled           // This makes sure that rule 1.8 is upheld, i.e. we need to stop signalling "eventually"
+                 && --leftInBatch > 0 // This makes sure that we only send `batchSize` number of elements in one go (so we can yield to other Runnables)
+                 && --demand > 0);    // This makes sure that rule 1.1 is upheld (sending more than was demanded)
+
+        if (!cancelled && demand > 0) // If the `Subscription` is still alive and well, and we have demand to satisfy, we signal ourselves to send more data
+          signal(Send.Instance);
+      } catch(final Throwable t) {
+        // We can only get here if `onNext` or `onComplete` threw, and they are not allowed to according to 2.13, so we can only cancel and log here.
+        doCancel(); // Make sure that we are cancelled, since we cannot do anything else since the `Subscriber` is faulty.
+        (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onNext or onComplete.", t)).printStackTrace(System.err);
+      }
+    }
+
+    // This is a helper method to ensure that we always `cancel` when we signal `onError` as per rule 1.6
+    private void terminateDueTo(final Throwable t) {
+      cancelled = true; // When we signal onError, the subscription must be considered as cancelled, as per rule 1.6
+      try {
+        subscriber.onError(t); // Then we signal the error downstream, to the `Subscriber`
+      } catch(final Throwable t2) { // If `onError` throws an exception, this is a spec violation according to rule 1.9, and all we can do is to log it.
+        (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err);
+      }
+    }
+
+    // What `signal` does is that it sends signals to the `Subscription` asynchronously
+    private void signal(final Signal signal) {
+      if (inboundSignals.offer(signal)) // No need to null-check here as ConcurrentLinkedQueue does this for us
+        tryScheduleToExecute(); // Then we try to schedule it for execution, if it isn't already
+    }
+
+    // This is the main "event loop" if you so will
+    @Override public final void run() {
+      if(on.get()) { // establishes a happens-before relationship with the end of the previous run
+        try {
+          final Signal s = inboundSignals.poll(); // We take a signal off the queue
+          if (!cancelled) { // to make sure that we follow rule 1.8, 3.6 and 3.7
+
+            // Below we simply unpack the `Signal`s and invoke the corresponding methods
+            if (s instanceof Request)
+              doRequest(((Request)s).n);
+            else if (s == Send.Instance)
+              doSend();
+            else if (s == Cancel.Instance)
+              doCancel();
+            else if (s == Subscribe.Instance)
+              doSubscribe();
+          }
+        } finally {
+          on.set(false); // establishes a happens-before relationship with the beginning of the next run
+          if(!inboundSignals.isEmpty()) // If we still have signals to process
+            tryScheduleToExecute(); // Then we try to schedule ourselves to execute again
+        }
+      }
+    }
+
+    // This method makes sure that this `Subscription` is only running on one Thread at a time,
+    // this is important to make sure that we follow rule 1.3
+    private final void tryScheduleToExecute() {
+      if(on.compareAndSet(false, true)) {
+        try {
+          executor.execute(this);
+        } catch(Throwable t) { // If we can't run on the `Executor`, we need to fail gracefully
+          if (!cancelled) {
+            doCancel(); // First of all, this failure is not recoverable, so we need to follow rule 1.4 and 1.6
+            try {
+              terminateDueTo(new IllegalStateException("Publisher terminated due to unavailable Executor.", t));
+            } finally {
+              inboundSignals.clear(); // We're not going to need these anymore
+              // This subscription is cancelled by now, but letting it become schedulable again means
+              // that we can drain the inboundSignals queue if anything arrives after clearing
+              on.set(false);
+            }
+          }
+        }
+      }
+    }
+
+    // Our implementation of `Subscription.request` sends a signal to the Subscription that more elements are in demand
+    @Override public void request(final long n) {
+      signal(new Request(n));
+    }
+    // Our implementation of `Subscription.cancel` sends a signal to the Subscription that the `Subscriber` is not interested in any more elements
+    @Override public void cancel() {
+      signal(Cancel.Instance);
+    }
+    // The reason for the `init` method is that we want to ensure the `SubscriptionImpl`
+    // is completely constructed before it is exposed to the thread pool, therefor this
+    // method is only intended to be invoked once, and immediately after the constructor has
+    // finished.
+    void init() {
+      signal(Subscribe.Instance);
+    }
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.example.unicast;
+
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * AsyncSubscriber is an implementation of Reactive Streams `Subscriber`,
+ * it runs asynchronously (on an Executor), requests one element
+ * at a time, and invokes a user-defined method to process each element.
+ *
+ * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden.
+ */
+public abstract class AsyncSubscriber<T> implements Subscriber<T>, Runnable {
+
+  // Signal represents the asynchronous protocol between the Publisher and Subscriber
+  private static interface Signal {}
+
+  private enum OnComplete implements Signal { Instance; }
+
+  private static class OnError implements Signal {
+    public final Throwable error;
+    public OnError(final Throwable error) { this.error = error; }
+  }
+
+  private static class OnNext<T> implements Signal {
+    public final T next;
+    public OnNext(final T next) { this.next = next; }
+  }
+
+  private static class OnSubscribe implements Signal {
+    public final Subscription subscription;
+    public OnSubscribe(final Subscription subscription) { this.subscription = subscription; }
+  }
+
+  private Subscription subscription; // Obeying rule 3.1, we make this private!
+  private boolean done; // It's useful to keep track of whether this Subscriber is done or not
+  private final Executor executor; // This is the Executor we'll use to be asynchronous, obeying rule 2.2
+
+  // Only one constructor, and it's only accessible for the subclasses
+  protected AsyncSubscriber(Executor executor) {
+    if (executor == null) throw null;
+    this.executor = executor;
+  }
+
+  // Showcases a convenience method to idempotently marking the Subscriber as "done", so we don't want to process more elements
+  // herefor we also need to cancel our `Subscription`.
+  private final void done() {
+    //On this line we could add a guard against `!done`, but since rule 3.7 says that `Subscription.cancel()` is idempotent, we don't need to.
+    done = true; // If `whenNext` throws an exception, let's consider ourselves done (not accepting more elements)
+    if (subscription != null) { // If we are bailing out before we got a `Subscription` there's little need for cancelling it.
+      try {
+        subscription.cancel(); // Cancel the subscription
+      } catch(final Throwable t) {
+        //Subscription.cancel is not allowed to throw an exception, according to rule 3.15
+        (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err);
+      }
+    }
+  }
+
+  // This method is invoked when the OnNext signals arrive
+  // Returns whether more elements are desired or not, and if no more elements are desired,
+  // for convenience.
+  protected abstract boolean whenNext(final T element);
+
+  // This method is invoked when the OnComplete signal arrives
+  // override this method to implement your own custom onComplete logic.
+  protected void whenComplete() { }
+
+  // This method is invoked if the OnError signal arrives
+  // override this method to implement your own custom onError logic.
+  protected void whenError(Throwable error) { }
+
+  private final void handleOnSubscribe(final Subscription s) {
+    if (s == null) {
+      // Getting a null `Subscription` here is not valid so lets just ignore it.
+    } else if (subscription != null) { // If someone has made a mistake and added this Subscriber multiple times, let's handle it gracefully
+      try {
+        s.cancel(); // Cancel the additional subscription to follow rule 2.5
+      } catch(final Throwable t) {
+        //Subscription.cancel is not allowed to throw an exception, according to rule 3.15
+        (new IllegalStateException(s + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err);
+      }
+    } else {
+      // We have to assign it locally before we use it, if we want to be a synchronous `Subscriber`
+      // Because according to rule 3.10, the Subscription is allowed to call `onNext` synchronously from within `request`
+      subscription = s;
+      try {
+        // If we want elements, according to rule 2.1 we need to call `request`
+        // And, according to rule 3.2 we are allowed to call this synchronously from within the `onSubscribe` method
+        s.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time
+      } catch(final Throwable t) {
+        // Subscription.request is not allowed to throw according to rule 3.16
+        (new IllegalStateException(s + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err);
+      }
+    }
+  }
+
+  private final void handleOnNext(final T element) {
+    if (!done) { // If we aren't already done
+      if(subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec
+        // Check for spec violation of 2.1 and 1.09
+        (new IllegalStateException("Someone violated the Reactive Streams rule 1.09 and 2.1 by signalling OnNext before `Subscription.request`. (no Subscription)")).printStackTrace(System.err);
+      } else {
+        try {
+          if (whenNext(element)) {
+            try {
+              subscription.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time
+            } catch(final Throwable t) {
+              // Subscription.request is not allowed to throw according to rule 3.16
+              (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err);
+            }
+          } else {
+            done(); // This is legal according to rule 2.6
+          }
+        } catch(final Throwable t) {
+          done();
+          try {
+            onError(t);
+          } catch(final Throwable t2) {
+            //Subscriber.onError is not allowed to throw an exception, according to rule 2.13
+            (new IllegalStateException(this + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err);
+          }
+        }
+      }
+    }
+  }
+
+  // Here it is important that we do not violate 2.2 and 2.3 by calling methods on the `Subscription` or `Publisher`
+  private void handleOnComplete() {
+    if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec
+      // Publisher is not allowed to signal onComplete before onSubscribe according to rule 1.09
+      (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onComplete prior to onSubscribe.")).printStackTrace(System.err);
+    } else {
+      done = true; // Obey rule 2.4
+      whenComplete();
+    }
+  }
+
+  // Here it is important that we do not violate 2.2 and 2.3 by calling methods on the `Subscription` or `Publisher`
+  private void handleOnError(final Throwable error) {
+    if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec
+      // Publisher is not allowed to signal onError before onSubscribe according to rule 1.09
+      (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onError prior to onSubscribe.")).printStackTrace(System.err);
+    } else {
+      done = true; // Obey rule 2.4
+      whenError(error);
+    }
+  }
+
+  // We implement the OnX methods on `Subscriber` to send Signals that we will process asycnhronously, but only one at a time
+
+  @Override public final void onSubscribe(final Subscription s) {
+    // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Subscription` is `null`
+    if (s == null) throw null;
+
+    signal(new OnSubscribe(s));
+  }
+
+  @Override public final void onNext(final T element) {
+    // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `element` is `null`
+    if (element == null) throw null;
+
+    signal(new OnNext<T>(element));
+  }
+
+  @Override public final void onError(final Throwable t) {
+    // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Throwable` is `null`
+    if (t == null) throw null;
+
+    signal(new OnError(t));
+  }
+
+  @Override public final void onComplete() {
+     signal(OnComplete.Instance);
+  }
+
+  // This `ConcurrentLinkedQueue` will track signals that are sent to this `Subscriber`, like `OnComplete` and `OnNext` ,
+  // and obeying rule 2.11
+  private final ConcurrentLinkedQueue<Signal> inboundSignals = new ConcurrentLinkedQueue<Signal>();
+
+  // We are using this `AtomicBoolean` to make sure that this `Subscriber` doesn't run concurrently with itself,
+  // obeying rule 2.7 and 2.11
+  private final AtomicBoolean on = new AtomicBoolean(false);
+
+   @SuppressWarnings("unchecked")
+   @Override public final void run() {
+    if(on.get()) { // establishes a happens-before relationship with the end of the previous run
+      try {
+        final Signal s = inboundSignals.poll(); // We take a signal off the queue
+        if (!done) { // If we're done, we shouldn't process any more signals, obeying rule 2.8
+          // Below we simply unpack the `Signal`s and invoke the corresponding methods
+          if (s instanceof OnNext<?>)
+            handleOnNext(((OnNext<T>)s).next);
+          else if (s instanceof OnSubscribe)
+            handleOnSubscribe(((OnSubscribe)s).subscription);
+          else if (s instanceof OnError) // We are always able to handle OnError, obeying rule 2.10
+            handleOnError(((OnError)s).error);
+          else if (s == OnComplete.Instance) // We are always able to handle OnComplete, obeying rule 2.9
+            handleOnComplete();
+        }
+      } finally {
+        on.set(false); // establishes a happens-before relationship with the beginning of the next run
+        if(!inboundSignals.isEmpty()) // If we still have signals to process
+          tryScheduleToExecute(); // Then we try to schedule ourselves to execute again
+      }
+    }
+  }
+
+  // What `signal` does is that it sends signals to the `Subscription` asynchronously
+  private void signal(final Signal signal) {
+    if (inboundSignals.offer(signal)) // No need to null-check here as ConcurrentLinkedQueue does this for us
+      tryScheduleToExecute(); // Then we try to schedule it for execution, if it isn't already
+  }
+
+  // This method makes sure that this `Subscriber` is only executing on one Thread at a time
+  private final void tryScheduleToExecute() {
+    if(on.compareAndSet(false, true)) {
+      try {
+        executor.execute(this);
+      } catch(Throwable t) { // If we can't run on the `Executor`, we need to fail gracefully and not violate rule 2.13
+        if (!done) {
+          try {
+            done(); // First of all, this failure is not recoverable, so we need to cancel our subscription
+          } finally {
+            inboundSignals.clear(); // We're not going to need these anymore
+            // This subscription is cancelled by now, but letting the Subscriber become schedulable again means
+            // that we can drain the inboundSignals queue if anything arrives after clearing
+            on.set(false);
+          }
+        }
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/InfiniteIncrementNumberPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.example.unicast;
+
+import java.util.Iterator;
+import java.util.concurrent.Executor;
+
+import org.reactivestreams.Subscription;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Publisher;
+
+public class InfiniteIncrementNumberPublisher extends AsyncIterablePublisher<Integer> {
+    public InfiniteIncrementNumberPublisher(final Executor executor) {
+        super(new Iterable<Integer>() {
+          @Override public Iterator<Integer> iterator() {
+            return new Iterator<Integer>() {
+              private int at = 0;
+              @Override public boolean hasNext() { return true; }
+              @Override public Integer next() { return at++; } // Wraps around on overflow
+              @Override public void remove() { throw new UnsupportedOperationException(); }
+            };
+          }
+        }, executor);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.example.unicast;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.Executor;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Publisher;
+
+public class NumberIterablePublisher extends AsyncIterablePublisher<Integer> {
+    public NumberIterablePublisher(final int from, final int to, final Executor executor) {
+        super(new Iterable<Integer>() {
+          { if(from > to) throw new IllegalArgumentException("from must be equal or greater than to!"); }
+          @Override public Iterator<Integer> iterator() {
+            return new Iterator<Integer>() {
+              private int at = from;
+              @Override public boolean hasNext() { return at < to; }
+              @Override public Integer next() {
+                if (!hasNext()) return Collections.<Integer>emptyList().iterator().next();
+                else return at++;
+              }
+              @Override public void remove() { throw new UnsupportedOperationException(); }
+            };
+          }
+        }, executor);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.example.unicast;
+
+import org.reactivestreams.*;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A synchronous implementation of the {@link Publisher} that can
+ * be subscribed to multiple times and each individual subscription
+ * will receive range of monotonically increasing integer values on demand.
+ */
+public final class RangePublisher implements Publisher<Integer> {
+
+    /** The starting value of the range. */
+    final int start;
+
+    /** The number of items to emit. */
+    final int count;
+
+    /**
+     * Constructs a RangePublisher instance with the given start and count values
+     * that yields a sequence of [start, start + count).
+     * @param start the starting value of the range
+     * @param count the number of items to emit
+     */
+    public RangePublisher(int start, int count) {
+        this.start = start;
+        this.count = count;
+    }
+
+    @Override
+    public void subscribe(Subscriber<? super Integer> subscriber) {
+        // As per rule 1.11, we have decided to support multiple subscribers
+        // in a unicast configuration for this `Publisher` implementation.
+
+        // As per rule 1.09, we need to throw a `java.lang.NullPointerException`
+        // if the `Subscriber` is `null`
+        if (subscriber == null) throw null;
+
+        // As per 2.13, this method must return normally (i.e. not throw).
+        try {
+            subscriber.onSubscribe(new RangeSubscription(subscriber, start, start + count));
+        } catch (Throwable ex) {
+            new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 " +
+                    "by throwing an exception from onSubscribe.", ex)
+                    // When onSubscribe fails this way, we don't know what state the
+                    // subscriber is thus calling onError may cause more crashes.
+                    .printStackTrace();
+        }
+    }
+
+    /**
+     * A Subscription implementation that holds the current downstream
+     * requested amount and responds to the downstream's request() and
+     * cancel() calls.
+     */
+    static final class RangeSubscription
+            // We are using this `AtomicLong` to make sure that this `Subscription`
+            // doesn't run concurrently with itself, which would violate rule 1.3
+            // among others (no concurrent notifications).
+            // The atomic transition from 0L to N > 0L will ensure this.
+            extends AtomicLong implements Subscription {
+
+        private static final long serialVersionUID = -9000845542177067735L;
+
+        /** The Subscriber we are emitting integer values to. */
+        final Subscriber<? super Integer> downstream;
+
+        /** The end index (exclusive). */
+        final int end;
+
+        /**
+         * The current index and within the [start, start + count) range that
+         * will be emitted as downstream.onNext().
+         */
+        int index;
+
+        /**
+         * Indicates the emission should stop.
+         */
+        volatile boolean cancelled;
+
+        /**
+         * Holds onto the IllegalArgumentException (containing the offending stacktrace)
+         * indicating there was a non-positive request() call from the downstream.
+         */
+        volatile Throwable invalidRequest;
+
+        /**
+         * Constructs a stateful RangeSubscription that emits signals to the given
+         * downstream from an integer range of [start, end).
+         * @param downstream the Subscriber receiving the integer values and the completion signal.
+         * @param start the first integer value emitted, start of the range
+         * @param end the end of the range, exclusive
+         */
+        RangeSubscription(Subscriber<? super Integer> downstream, int start, int end) {
+            this.downstream = downstream;
+            this.index = start;
+            this.end = end;
+        }
+
+        // This method will register inbound demand from our `Subscriber` and
+        // validate it against rule 3.9 and rule 3.17
+        @Override
+        public void request(long n) {
+            // Non-positive requests should be honored with IllegalArgumentException
+            if (n <= 0L) {
+                invalidRequest = new IllegalArgumentException("§3.9: non-positive requests are not allowed!");
+                n = 1;
+            }
+            // Downstream requests are cumulative and may come from any thread
+            for (;;) {
+                long requested = get();
+                long update = requested + n;
+                // As governed by rule 3.17, when demand overflows `Long.MAX_VALUE`
+                // we treat the signalled demand as "effectively unbounded"
+                if (update < 0L) {
+                    update = Long.MAX_VALUE;
+                }
+                // atomically update the current requested amount
+                if (compareAndSet(requested, update)) {
+                    // if there was no prior request amount, we start the emission loop
+                    if (requested == 0L) {
+                        emit(update);
+                    }
+                    break;
+                }
+            }
+        }
+
+        // This handles cancellation requests, and is idempotent, thread-safe and not
+        // synchronously performing heavy computations as specified in rule 3.5
+        @Override
+        public void cancel() {
+            // Indicate to the emission loop it should stop.
+            cancelled = true;
+        }
+
+        void emit(long currentRequested) {
+            // Load fields to avoid re-reading them from memory due to volatile accesses in the loop.
+            Subscriber<? super Integer> downstream = this.downstream;
+            int index = this.index;
+            int end = this.end;
+            int emitted = 0;
+
+            try {
+                for (; ; ) {
+                    // Check if there was an invalid request and then report its exception
+                    // as mandated by rule 3.9. The stacktrace in it should
+                    // help locate the faulty logic in the Subscriber.
+                    Throwable invalidRequest = this.invalidRequest;
+                    if (invalidRequest != null) {
+                        // When we signal onError, the subscription must be considered as cancelled, as per rule 1.6
+                        cancelled = true;
+
+                        downstream.onError(invalidRequest);
+                        return;
+                    }
+
+                    // Loop while the index hasn't reached the end and we haven't
+                    // emitted all that's been requested
+                    while (index != end && emitted != currentRequested) {
+                        // to make sure that we follow rule 1.8, 3.6 and 3.7
+                        // We stop if cancellation was requested.
+                        if (cancelled) {
+                            return;
+                        }
+
+                        downstream.onNext(index);
+
+                        // Increment the index for the next possible emission.
+                        index++;
+                        // Increment the emitted count to prevent overflowing the downstream.
+                        emitted++;
+                    }
+
+                    // If the index reached the end, we complete the downstream.
+                    if (index == end) {
+                        // to make sure that we follow rule 1.8, 3.6 and 3.7
+                        // Unless cancellation was requested by the last onNext.
+                        if (!cancelled) {
+                            // We need to consider this `Subscription` as cancelled as per rule 1.6
+                            // Note, however, that this state is not observable from the outside
+                            // world and since we leave the loop with requested > 0L, any
+                            // further request() will never trigger the loop.
+                            cancelled = true;
+
+                            downstream.onComplete();
+                        }
+                        return;
+                    }
+
+                    // Did the requested amount change while we were looping?
+                    long freshRequested = get();
+                    if (freshRequested == currentRequested) {
+                        // Save where the loop has left off: the next value to be emitted
+                        this.index = index;
+                        // Atomically subtract the previously requested (also emitted) amount
+                        currentRequested = addAndGet(-currentRequested);
+                        // If there was no new request in between get() and addAndGet(), we simply quit
+                        // The next 0 to N transition in request() will trigger the next emission loop.
+                        if (currentRequested == 0L) {
+                            break;
+                        }
+                        // Looks like there were more async requests, reset the emitted count and continue.
+                        emitted = 0;
+                    } else {
+                        // Yes, avoid the atomic subtraction and resume.
+                        // emitted != currentRequest in this case and index
+                        // still points to the next value to be emitted
+                        currentRequested = freshRequested;
+                    }
+                }
+            } catch (Throwable ex) {
+                // We can only get here if `onNext`, `onError` or `onComplete` threw, and they
+                // are not allowed to according to 2.13, so we can only cancel and log here.
+                // If `onError` throws an exception, this is a spec violation according to rule 1.9,
+                // and all we can do is to log it.
+
+                // Make sure that we are cancelled, since we cannot do anything else
+                // since the `Subscriber` is faulty.
+                cancelled = true;
+
+                // We can't report the failure to onError as the Subscriber is unreliable.
+                (new IllegalStateException(downstream + " violated the Reactive Streams rule 2.13 by " +
+                        "throwing an exception from onNext, onError or onComplete.", ex))
+                        .printStackTrace();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.example.unicast;
+
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+
+/**
+ * SyncSubscriber is an implementation of Reactive Streams `Subscriber`,
+ * it runs synchronously (on the Publisher's thread) and requests one element
+ * at a time and invokes a user-defined method to process each element.
+ *
+ * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden.
+ */
+public abstract class SyncSubscriber<T> implements Subscriber<T> {
+  private Subscription subscription; // Obeying rule 3.1, we make this private!
+  private boolean done = false;
+
+  @Override public void onSubscribe(final Subscription s) {
+    // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Subscription` is `null`
+    if (s == null) throw null;
+
+    if (subscription != null) { // If someone has made a mistake and added this Subscriber multiple times, let's handle it gracefully
+      try {
+        s.cancel(); // Cancel the additional subscription
+      } catch(final Throwable t) {
+        //Subscription.cancel is not allowed to throw an exception, according to rule 3.15
+        (new IllegalStateException(s + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err);
+      }
+    } else {
+      // We have to assign it locally before we use it, if we want to be a synchronous `Subscriber`
+      // Because according to rule 3.10, the Subscription is allowed to call `onNext` synchronously from within `request`
+      subscription = s;
+      try {
+        // If we want elements, according to rule 2.1 we need to call `request`
+        // And, according to rule 3.2 we are allowed to call this synchronously from within the `onSubscribe` method
+        s.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time
+      } catch(final Throwable t) {
+        // Subscription.request is not allowed to throw according to rule 3.16
+        (new IllegalStateException(s + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err);
+      }
+    }
+  }
+
+  @Override public void onNext(final T element) {
+    if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec
+      (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onNext prior to onSubscribe.")).printStackTrace(System.err);
+    } else {
+      // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `element` is `null`
+      if (element == null) throw null;
+
+      if (!done) { // If we aren't already done
+        try {
+          if (whenNext(element)) {
+            try {
+              subscription.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time
+            } catch (final Throwable t) {
+              // Subscription.request is not allowed to throw according to rule 3.16
+              (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err);
+            }
+          } else {
+            done();
+          }
+        } catch (final Throwable t) {
+          done();
+          try {
+            onError(t);
+          } catch (final Throwable t2) {
+            //Subscriber.onError is not allowed to throw an exception, according to rule 2.13
+            (new IllegalStateException(this + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err);
+          }
+        }
+      }
+    }
+  }
+
+  // Showcases a convenience method to idempotently marking the Subscriber as "done", so we don't want to process more elements
+  // herefor we also need to cancel our `Subscription`.
+  private void done() {
+    //On this line we could add a guard against `!done`, but since rule 3.7 says that `Subscription.cancel()` is idempotent, we don't need to.
+    done = true; // If we `whenNext` throws an exception, let's consider ourselves done (not accepting more elements)
+    try {
+      subscription.cancel(); // Cancel the subscription
+    } catch(final Throwable t) {
+      //Subscription.cancel is not allowed to throw an exception, according to rule 3.15
+      (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err);
+    }
+  }
+
+  // This method is left as an exercise to the reader/extension point
+  // Returns whether more elements are desired or not, and if no more elements are desired
+  protected abstract boolean whenNext(final T element);
+
+  @Override public void onError(final Throwable t) {
+    if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec
+      (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onError prior to onSubscribe.")).printStackTrace(System.err);
+    } else {
+      // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Throwable` is `null`
+      if (t == null) throw null;
+      // Here we are not allowed to call any methods on the `Subscription` or the `Publisher`, as per rule 2.3
+      // And anyway, the `Subscription` is considered to be cancelled if this method gets called, as per rule 2.4
+    }
+  }
+
+  @Override public void onComplete() {
+    if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec
+      (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onComplete prior to onSubscribe.")).printStackTrace(System.err);
+    } else {
+      // Here we are not allowed to call any methods on the `Subscription` or the `Publisher`, as per rule 2.3
+      // And anyway, the `Subscription` is considered to be cancelled if this method gets called, as per rule 2.4
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,896 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck;
+
+import org.reactivestreams.Processor;
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.tck.TestEnvironment.ManualPublisher;
+import org.reactivestreams.tck.TestEnvironment.ManualSubscriber;
+import org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport;
+import org.reactivestreams.tck.TestEnvironment.Promise;
+import org.reactivestreams.tck.flow.support.Function;
+import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules;
+import org.reactivestreams.tck.flow.support.PublisherVerificationRules;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class IdentityProcessorVerification<T> extends WithHelperPublisher<T>
+  implements SubscriberWhiteboxVerificationRules, PublisherVerificationRules {
+
+  private final TestEnvironment env;
+
+  ////////////////////// DELEGATED TO SPECS //////////////////////
+
+  // for delegating tests
+  private final SubscriberWhiteboxVerification<T> subscriberVerification;
+
+  // for delegating tests
+  private final PublisherVerification<T> publisherVerification;
+
+  ////////////////// END OF DELEGATED TO SPECS //////////////////
+
+  // number of elements the processor under test must be able ot buffer,
+  // without dropping elements. Defaults to `TestEnvironment.TEST_BUFFER_SIZE`.
+  private final int processorBufferSize;
+
+  /**
+   * Test class must specify the expected time it takes for the publisher to
+   * shut itself down when the the last downstream {@code Subscription} is cancelled.
+   *
+   * The processor will be required to be able to buffer {@code TestEnvironment.TEST_BUFFER_SIZE} elements.
+   */
+  @SuppressWarnings("unused")
+  public IdentityProcessorVerification(final TestEnvironment env) {
+    this(env, PublisherVerification.envPublisherReferenceGCTimeoutMillis(), TestEnvironment.TEST_BUFFER_SIZE);
+  }
+
+  /**
+   * Test class must specify the expected time it takes for the publisher to
+   * shut itself down when the the last downstream {@code Subscription} is cancelled.
+   *
+   * The processor will be required to be able to buffer {@code TestEnvironment.TEST_BUFFER_SIZE} elements.
+   *
+   * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher.
+   */
+  @SuppressWarnings("unused")
+  public IdentityProcessorVerification(final TestEnvironment env, long publisherReferenceGCTimeoutMillis) {
+    this(env, publisherReferenceGCTimeoutMillis, TestEnvironment.TEST_BUFFER_SIZE);
+  }
+
+  /**
+   * Test class must specify the expected time it takes for the publisher to
+   * shut itself down when the the last downstream {@code Subscription} is cancelled.
+   *
+   * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher.
+   * @param processorBufferSize            number of elements the processor is required to be able to buffer.
+   */
+  public IdentityProcessorVerification(final TestEnvironment env, long publisherReferenceGCTimeoutMillis, int processorBufferSize) {
+    this.env = env;
+    this.processorBufferSize = processorBufferSize;
+
+    this.subscriberVerification = new SubscriberWhiteboxVerification<T>(env) {
+      @Override
+      public Subscriber<T> createSubscriber(WhiteboxSubscriberProbe<T> probe) {
+        return IdentityProcessorVerification.this.createSubscriber(probe);
+      }
+
+      @Override public T createElement(int element) {
+        return IdentityProcessorVerification.this.createElement(element);
+      }
+
+      @Override
+      public Publisher<T> createHelperPublisher(long elements) {
+        return IdentityProcessorVerification.this.createHelperPublisher(elements);
+      }
+    };
+
+    publisherVerification = new PublisherVerification<T>(env, publisherReferenceGCTimeoutMillis) {
+      @Override
+      public Publisher<T> createPublisher(long elements) {
+        return IdentityProcessorVerification.this.createPublisher(elements);
+      }
+
+      @Override
+      public Publisher<T> createFailedPublisher() {
+        return IdentityProcessorVerification.this.createFailedPublisher();
+      }
+
+      @Override
+      public long maxElementsFromPublisher() {
+        return IdentityProcessorVerification.this.maxElementsFromPublisher();
+      }
+
+      @Override
+      public long boundedDepthOfOnNextAndRequestRecursion() {
+        return IdentityProcessorVerification.this.boundedDepthOfOnNextAndRequestRecursion();
+      }
+
+      @Override
+      public boolean skipStochasticTests() {
+        return IdentityProcessorVerification.this.skipStochasticTests();
+      }
+    };
+  }
+
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a {@link Processor}, which simply forwards all stream elements from its upstream
+   * to its downstream. It must be able to internally buffer the given number of elements.
+   *
+   * @param bufferSize number of elements the processor is required to be able to buffer.
+   */
+  public abstract Processor<T, T> createIdentityProcessor(int bufferSize);
+
+  /**
+   * By implementing this method, additional TCK tests concerning a "failed" publishers will be run.
+   *
+   * The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription,
+   * followed by signalling {@code onError} on it, as specified by Rule 1.9.
+   *
+   * If you want to ignore these additional tests, return {@code null} from this method.
+   */
+  public abstract Publisher<T> createFailedPublisher();
+
+  /**
+   * Override and return lower value if your Publisher is only able to produce a known number of elements.
+   * For example, if it is designed to return at-most-one element, return {@code 1} from this method.
+   *
+   * Defaults to {@code Long.MAX_VALUE - 1}, meaning that the Publisher can be produce a huge but NOT an unbounded number of elements.
+   *
+   * To mark your Publisher will *never* signal an {@code onComplete} override this method and return {@code Long.MAX_VALUE},
+   * which will result in *skipping all tests which require an onComplete to be triggered* (!).
+   */
+  public long maxElementsFromPublisher() {
+    return Long.MAX_VALUE - 1;
+  }
+
+  /**
+   * In order to verify rule 3.3 of the reactive streams spec, this number will be used to check if a
+   * {@code Subscription} actually solves the "unbounded recursion" problem by not allowing the number of
+   * recursive calls to exceed the number returned by this method.
+   *
+   * @see <a href="https://github.com/reactive-streams/reactive-streams-jvm#3.3">reactive streams spec, rule 3.3</a>
+   * @see PublisherVerification#required_spec303_mustNotAllowUnboundedRecursion()
+   */
+  public long boundedDepthOfOnNextAndRequestRecursion() {
+    return 1;
+  }
+
+  /**
+   * Override and return {@code true} in order to skip executing tests marked as {@code Stochastic}.
+   * Stochastic in this case means that the Rule is impossible or infeasible to deterministically verify—
+   * usually this means that this test case can yield false positives ("be green") even if for some case,
+   * the given implementation may violate the tested behaviour.
+   */
+  public boolean skipStochasticTests() {
+    return false;
+  }
+
+  /**
+   * Describes the tested implementation in terms of how many subscribers they can support.
+   * Some tests require the {@code Publisher} under test to support multiple Subscribers,
+   * yet the spec does not require all publishers to be able to do so, thus – if an implementation
+   * supports only a limited number of subscribers (e.g. only 1 subscriber, also known as "no fanout")
+   * you MUST return that number from this method by overriding it.
+   */
+  public long maxSupportedSubscribers() {
+      return Long.MAX_VALUE;
+  }
+
+  /**
+   * Override this method and return {@code true} if the {@link Processor} returned by the
+   * {@link #createIdentityProcessor(int)} coordinates its {@link Subscriber}s
+   * request amounts and only delivers onNext signals if all Subscribers have
+   * indicated (via their Subscription#request(long)) they are ready to receive elements.
+   */
+  public boolean doesCoordinatedEmission() {
+    return false;
+  }
+
+  ////////////////////// TEST ENV CLEANUP /////////////////////////////////////
+
+  @BeforeMethod
+  public void setUp() throws Exception {
+    publisherVerification.setUp();
+    subscriberVerification.setUp();
+  }
+
+  ////////////////////// PUBLISHER RULES VERIFICATION ///////////////////////////
+
+  // A Processor
+  //   must obey all Publisher rules on its publishing side
+  public Publisher<T> createPublisher(long elements) {
+    final Processor<T, T> processor = createIdentityProcessor(processorBufferSize);
+    final Publisher<T> pub = createHelperPublisher(elements);
+    pub.subscribe(processor);
+    return processor; // we run the PublisherVerification against this
+  }
+
+  @Override @Test
+  public void required_validate_maxElementsFromPublisher() throws Exception {
+    publisherVerification.required_validate_maxElementsFromPublisher();
+  }
+
+  @Override @Test
+  public void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception {
+    publisherVerification.required_validate_boundedDepthOfOnNextAndRequestRecursion();
+  }
+
+  /////////////////////// DELEGATED TESTS, A PROCESSOR "IS A" PUBLISHER //////////////////////
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1
+
+  @Test
+  public void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable {
+    publisherVerification.required_createPublisher1MustProduceAStreamOfExactly1Element();
+  }
+
+  @Test
+  public void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable {
+    publisherVerification.required_createPublisher3MustProduceAStreamOfExactly3Elements();
+  }
+
+  @Override @Test
+  public void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable {
+    publisherVerification.required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements();
+  }
+
+  @Override @Test
+  public void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable {
+    publisherVerification.required_spec102_maySignalLessThanRequestedAndTerminateSubscription();
+  }
+
+  @Override @Test
+  public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable {
+    publisherVerification.stochastic_spec103_mustSignalOnMethodsSequentially();
+  }
+
+  @Override @Test
+  public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable {
+    publisherVerification.optional_spec104_mustSignalOnErrorWhenFails();
+  }
+
+  @Override @Test
+  public void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable {
+    publisherVerification.required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates();
+  }
+
+  @Override @Test
+  public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable {
+    publisherVerification.optional_spec105_emptyStreamMustTerminateBySignallingOnComplete();
+  }
+
+  @Override @Test
+  public void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable {
+    publisherVerification.untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled();
+  }
+
+  @Override @Test
+  public void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable {
+    publisherVerification.required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled();
+  }
+
+  @Override @Test
+  public void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable {
+    publisherVerification.untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled();
+  }
+
+  @Override @Test
+  public void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable {
+    publisherVerification.untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals();
+  }
+
+  @Override @Test
+  public void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable {
+    publisherVerification.untested_spec109_subscribeShouldNotThrowNonFatalThrowable();
+  }
+
+  @Override @Test
+  public void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable {
+    publisherVerification.required_spec109_subscribeThrowNPEOnNullSubscriber();
+  }
+
+  @Override @Test
+  public void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable {
+    publisherVerification.required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe();
+  }
+
+  @Override @Test
+  public void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable {
+    publisherVerification.required_spec109_mustIssueOnSubscribeForNonNullSubscriber();
+  }
+
+  @Override @Test
+  public void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable {
+    publisherVerification.untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice();
+  }
+
+  @Override @Test
+  public void optional_spec111_maySupportMultiSubscribe() throws Throwable {
+    publisherVerification.optional_spec111_maySupportMultiSubscribe();
+  }
+
+  @Override @Test
+  public void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable {
+    publisherVerification.optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals();
+  }
+
+  @Override @Test
+  public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable {
+    publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne();
+  }
+
+  @Override @Test
+  public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable {
+    publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront();
+  }
+
+  @Override @Test
+  public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable {
+    publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected();
+  }
+
+  @Override @Test
+  public void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable {
+    publisherVerification.required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe();
+  }
+
+  @Override @Test
+  public void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable {
+    publisherVerification.required_spec303_mustNotAllowUnboundedRecursion();
+  }
+
+  @Override @Test
+  public void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception {
+    publisherVerification.untested_spec304_requestShouldNotPerformHeavyComputations();
+  }
+
+  @Override @Test
+  public void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception {
+    publisherVerification.untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation();
+  }
+
+  @Override @Test
+  public void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable {
+    publisherVerification.required_spec306_afterSubscriptionIsCancelledRequestMustBeNops();
+  }
+
+  @Override @Test
+  public void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable {
+    publisherVerification.required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops();
+  }
+
+  @Override @Test
+  public void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable {
+    publisherVerification.required_spec309_requestZeroMustSignalIllegalArgumentException();
+  }
+
+  @Override @Test
+  public void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable {
+    publisherVerification.required_spec309_requestNegativeNumberMustSignalIllegalArgumentException();
+  }
+
+  @Override @Test
+  public void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable {
+    publisherVerification.optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage();
+  }
+
+  @Override @Test
+  public void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable {
+    publisherVerification.required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling();
+  }
+
+  @Override @Test
+  public void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable {
+    publisherVerification.required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber();
+  }
+
+  @Override @Test
+  public void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable {
+    publisherVerification.required_spec317_mustSupportAPendingElementCountUpToLongMaxValue();
+  }
+
+  @Override @Test
+  public void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable {
+    publisherVerification.required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue();
+  }
+
+  @Override @Test
+  public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable {
+    publisherVerification.required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue();
+  }
+
+
+  /**
+   * Asks for a {@code Processor} that supports at least 2 {@code Subscriber}s at once and checks if two {@code Subscriber}s
+   * receive the same items and a terminal {@code Exception}.
+   * <p>
+   * If the {@code Processor} requests and/or emits items only when all of its {@code Subscriber}s have requested,
+   * override {@link #doesCoordinatedEmission()} and return {@code true} to indicate this property.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.4'>1.4</a> with multiple
+   * {@code Subscriber}s.
+   * <p>
+   * The test is not executed if {@link IdentityProcessorVerification#maxSupportedSubscribers()} is less than 2.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Processor} implementation:
+   * <ul>
+   * <li>The {@code TestEnvironment} has large enough timeout specified in case the {@code Processor} has some time-delay behavior.</li>
+   * <li>The {@code Processor} is able to fulfill requests of its {@code Subscriber}s independently of each other's requests or
+   * else override {@link #doesCoordinatedEmission()} and return {@code true} to indicate the test {@code Subscriber}s
+   * both have to request first.</li>
+   * </ul>
+   */
+  @Test
+  public void required_spec104_mustCallOnErrorOnAllItsSubscribersIfItEncountersANonRecoverableError() throws Throwable {
+    optionalMultipleSubscribersTest(2, new Function<Long,TestSetup>() {
+      @Override
+      public TestSetup apply(Long aLong) throws Throwable {
+        return new TestSetup(env, processorBufferSize) {{
+          final ManualSubscriberWithErrorCollection<T> sub1 = new ManualSubscriberWithErrorCollection<T>(env);
+          env.subscribe(processor, sub1);
+
+          final ManualSubscriberWithErrorCollection<T> sub2 = new ManualSubscriberWithErrorCollection<T>(env);
+          env.subscribe(processor, sub2);
+
+          final Exception ex = new RuntimeException("Test exception");
+
+          if (doesCoordinatedEmission()) {
+            sub1.request(1);
+            sub2.request(1);
+
+            expectRequest();
+
+            final T x = sendNextTFromUpstream();
+
+            expectNextElement(sub1, x);
+            expectNextElement(sub2, x);
+
+            sub1.request(1);
+            sub2.request(1);
+          } else {
+            sub1.request(1);
+
+            expectRequest(env.defaultTimeoutMillis(),
+                    "If the Processor coordinates requests/emissions when having multiple Subscribers"
+                    + " at once, please override doesCoordinatedEmission() to return true in this "
+                    + "IdentityProcessorVerification to allow this test to pass.");
+
+            final T x = sendNextTFromUpstream();
+            expectNextElement(sub1, x,
+                    "If the Processor coordinates requests/emissions when having multiple Subscribers"
+                            + " at once, please override doesCoordinatedEmission() to return true in this "
+                            + "IdentityProcessorVerification to allow this test to pass.");
+
+            sub1.request(1);
+
+            // sub1 has received one element, and has one demand pending
+            // sub2 has not yet requested anything
+          }
+          sendError(ex);
+
+          sub1.expectError(ex);
+          sub2.expectError(ex);
+
+          env.verifyNoAsyncErrorsNoDelay();
+        }};
+      }
+    });
+  }
+
+  ////////////////////// SUBSCRIBER RULES VERIFICATION ///////////////////////////
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1
+
+  // A Processor
+  //   must obey all Subscriber rules on its consuming side
+  public Subscriber<T> createSubscriber(final SubscriberWhiteboxVerification.WhiteboxSubscriberProbe<T> probe) {
+    final Processor<T, T> processor = createIdentityProcessor(processorBufferSize);
+    processor.subscribe(
+        new Subscriber<T>() {
+          private final Promise<Subscription> subs = new Promise<Subscription>(env);
+
+          @Override
+          public void onSubscribe(final Subscription subscription) {
+            if (env.debugEnabled()) {
+              env.debug(String.format("whiteboxSubscriber::onSubscribe(%s)", subscription));
+            }
+            if (subs.isCompleted()) subscription.cancel(); // the Probe must also pass subscriber verification
+
+            probe.registerOnSubscribe(new SubscriberWhiteboxVerification.SubscriberPuppet() {
+
+              @Override
+              public void triggerRequest(long elements) {
+                subscription.request(elements);
+              }
+
+              @Override
+              public void signalCancel() {
+                subscription.cancel();
+              }
+            });
+          }
+
+          @Override
+          public void onNext(T element) {
+            if (env.debugEnabled()) {
+              env.debug(String.format("whiteboxSubscriber::onNext(%s)", element));
+            }
+            probe.registerOnNext(element);
+          }
+
+          @Override
+          public void onComplete() {
+            if (env.debugEnabled()) {
+              env.debug("whiteboxSubscriber::onComplete()");
+            }
+            probe.registerOnComplete();
+          }
+
+          @Override
+          public void onError(Throwable cause) {
+            if (env.debugEnabled()) {
+              env.debug(String.format("whiteboxSubscriber::onError(%s)", cause));
+            }
+            probe.registerOnError(cause);
+          }
+        });
+
+    return processor; // we run the SubscriberVerification against this
+  }
+
+  ////////////////////// OTHER RULE VERIFICATION ///////////////////////////
+
+  // A Processor
+  //   must immediately pass on `onError` events received from its upstream to its downstream
+  @Test
+  public void mustImmediatelyPassOnOnErrorEventsReceivedFromItsUpstreamToItsDownstream() throws Exception {
+    new TestSetup(env, processorBufferSize) {{
+      final ManualSubscriberWithErrorCollection<T> sub = new ManualSubscriberWithErrorCollection<T>(env);
+      env.subscribe(processor, sub);
+
+      final Exception ex = new RuntimeException("Test exception");
+      sendError(ex);
+      sub.expectError(ex); // "immediately", i.e. without a preceding request
+
+      env.verifyNoAsyncErrorsNoDelay();
+    }};
+  }
+
+  /////////////////////// DELEGATED TESTS, A PROCESSOR "IS A" SUBSCRIBER //////////////////////
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1
+
+  @Test
+  public void required_exerciseWhiteboxHappyPath() throws Throwable {
+    subscriberVerification.required_exerciseWhiteboxHappyPath();
+  }
+
+  @Override @Test
+  public void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable {
+    subscriberVerification.required_spec201_mustSignalDemandViaSubscriptionRequest();
+  }
+
+  @Override @Test
+  public void untested_spec202_shouldAsynchronouslyDispatch() throws Exception {
+    subscriberVerification.untested_spec202_shouldAsynchronouslyDispatch();
+  }
+
+  @Override @Test
+  public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable {
+    subscriberVerification.required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete();
+  }
+
+  @Override @Test
+  public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable {
+    subscriberVerification.required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError();
+  }
+
+  @Override @Test
+  public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception {
+    subscriberVerification.untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError();
+  }
+
+  @Override @Test
+  public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable {
+    subscriberVerification.required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal();
+  }
+
+  @Override @Test
+  public void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception {
+    subscriberVerification.untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid();
+  }
+
+  @Override @Test
+  public void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception {
+    subscriberVerification.untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization();
+  }
+
+  @Override @Test
+  public void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable {
+    subscriberVerification.required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel();
+  }
+
+  @Override @Test
+  public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable {
+    subscriberVerification.required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall();
+  }
+
+  @Override @Test
+  public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable {
+    subscriberVerification.required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall();
+  }
+
+  @Override @Test
+  public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable {
+    subscriberVerification.required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall();
+  }
+
+  @Override @Test
+  public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable {
+    subscriberVerification.required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall();
+  }
+
+  @Override @Test
+  public void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception {
+    subscriberVerification.untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents();
+  }
+
+  @Override @Test
+  public void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable {
+    subscriberVerification.untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation();
+  }
+
+  @Override @Test
+  public void untested_spec213_failingOnSignalInvocation() throws Exception {
+    subscriberVerification.untested_spec213_failingOnSignalInvocation();
+  }
+
+  @Override @Test
+  public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    subscriberVerification.required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull();
+  }
+  @Override @Test
+  public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    subscriberVerification.required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull();
+  }
+  @Override @Test
+  public void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    subscriberVerification.required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull();
+  }
+
+  @Override @Test
+  public void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception {
+    subscriberVerification.untested_spec301_mustNotBeCalledOutsideSubscriberContext();
+  }
+
+  @Override @Test
+  public void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable {
+    subscriberVerification.required_spec308_requestMustRegisterGivenNumberElementsToBeProduced();
+  }
+
+  @Override @Test
+  public void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception {
+    subscriberVerification.untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber();
+  }
+
+  @Override @Test
+  public void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception {
+    subscriberVerification.untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError();
+  }
+
+  @Override @Test
+  public void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception {
+    subscriberVerification.untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists();
+  }
+
+  @Override @Test
+  public void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception {
+    subscriberVerification.untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError();
+  }
+
+  @Override @Test
+  public void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception {
+    subscriberVerification.untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber();
+  }
+
+  /////////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////
+
+  /**
+   * Asks for a {@code Processor} that supports at least 2 {@code Subscriber}s at once and checks requests
+   * from {@code Subscriber}s will eventually lead to requests towards the upstream of the {@code Processor}.
+   * <p>
+   * If the {@code Processor} requests and/or emits items only when all of its {@code Subscriber}s have requested,
+   * override {@link #doesCoordinatedEmission()} and return {@code true} to indicate this property.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.4'>2.1</a> with multiple
+   * {@code Subscriber}s.
+   * <p>
+   * The test is not executed if {@link IdentityProcessorVerification#maxSupportedSubscribers()} is less than 2.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Processor} implementation:
+   * <ul>
+   * <li>The {@code TestEnvironment} has large enough timeout specified in case the {@code Processor} has some time-delay behavior.</li>
+   * <li>The {@code Processor} is able to fulfill requests of its {@code Subscriber}s independently of each other's requests or
+   * else override {@link #doesCoordinatedEmission()} and return {@code true} to indicate the test {@code Subscriber}s
+   * both have to request first.</li>
+   * </ul>
+   */
+  @Test
+  public void required_mustRequestFromUpstreamForElementsThatHaveBeenRequestedLongAgo() throws Throwable {
+    optionalMultipleSubscribersTest(2, new Function<Long,TestSetup>() {
+      @Override
+      public TestSetup apply(Long subscribers) throws Throwable {
+        return new TestSetup(env, processorBufferSize) {{
+          ManualSubscriber<T> sub1 = newSubscriber();
+          sub1.request(20);
+
+          long totalRequests = expectRequest();
+          final T x = sendNextTFromUpstream();
+          expectNextElement(sub1, x);
+
+          if (totalRequests == 1) {
+            totalRequests += expectRequest();
+          }
+          final T y = sendNextTFromUpstream();
+          expectNextElement(sub1, y);
+
+          if (totalRequests == 2) {
+            totalRequests += expectRequest();
+          }
+
+          final ManualSubscriber<T> sub2 = newSubscriber();
+
+          // sub1 now has 18 pending
+          // sub2 has 0 pending
+
+          if (doesCoordinatedEmission()) {
+            sub2.expectNone(); // since sub2 hasn't requested anything yet
+
+            sub2.request(1);
+
+            final T z = sendNextTFromUpstream();
+            expectNextElement(sub1, z);
+            expectNextElement(sub2, z);
+          } else {
+            final T z = sendNextTFromUpstream();
+            expectNextElement(sub1, z,
+                    "If the Processor coordinates requests/emissions when having multiple Subscribers"
+                            + " at once, please override doesCoordinatedEmission() to return true in this "
+                            + "IdentityProcessorVerification to allow this test to pass.");
+            sub2.expectNone(); // since sub2 hasn't requested anything yet
+
+            sub2.request(1);
+            expectNextElement(sub2, z);
+          }
+          if (totalRequests == 3) {
+            expectRequest();
+          }
+
+          // to avoid error messages during test harness shutdown
+          sendCompletion();
+          sub1.expectCompletion(env.defaultTimeoutMillis());
+          sub2.expectCompletion(env.defaultTimeoutMillis());
+
+          env.verifyNoAsyncErrorsNoDelay();
+        }};
+      }
+    });
+  }
+
+  /////////////////////// TEST INFRASTRUCTURE //////////////////////
+
+  public void notVerified() {
+    publisherVerification.notVerified();
+  }
+
+  public void notVerified(String message) {
+    publisherVerification.notVerified(message);
+  }
+
+  /**
+   * Test for feature that REQUIRES multiple subscribers to be supported by Publisher.
+   */
+  public void optionalMultipleSubscribersTest(long requiredSubscribersSupport, Function<Long, TestSetup> body) throws Throwable {
+    if (requiredSubscribersSupport > maxSupportedSubscribers())
+      notVerified(String.format("The Publisher under test only supports %d subscribers, while this test requires at least %d to run.",
+                                maxSupportedSubscribers(), requiredSubscribersSupport));
+    else body.apply(requiredSubscribersSupport);
+  }
+
+  public abstract class TestSetup extends ManualPublisher<T> {
+    final private ManualSubscriber<T> tees; // gives us access to an infinite stream of T values
+    private Set<T> seenTees = new HashSet<T>();
+
+    final Processor<T, T> processor;
+
+    public TestSetup(TestEnvironment env, int testBufferSize) throws InterruptedException {
+      super(env);
+      tees = env.newManualSubscriber(createHelperPublisher(Long.MAX_VALUE));
+      processor = createIdentityProcessor(testBufferSize);
+      subscribe(processor);
+    }
+
+    public ManualSubscriber<T> newSubscriber() throws InterruptedException {
+      return env.newManualSubscriber(processor);
+    }
+
+    public T nextT() throws InterruptedException {
+      final T t = tees.requestNextElement();
+      if (seenTees.contains(t)) {
+        env.flop(String.format("Helper publisher illegally produced the same element %s twice", t));
+      }
+      seenTees.add(t);
+      return t;
+    }
+
+    public void expectNextElement(ManualSubscriber<T> sub, T expected) throws InterruptedException {
+      final T elem = sub.nextElement(String.format("timeout while awaiting %s", expected));
+      if (!elem.equals(expected)) {
+        env.flop(String.format("Received `onNext(%s)` on downstream but expected `onNext(%s)`", elem, expected));
+      }
+    }
+
+    public void expectNextElement(ManualSubscriber<T> sub, T expected, String errorMessageAddendum) throws InterruptedException {
+      final T elem = sub.nextElement(String.format("timeout while awaiting %s. %s", expected, errorMessageAddendum));
+      if (!elem.equals(expected)) {
+        env.flop(String.format("Received `onNext(%s)` on downstream but expected `onNext(%s)`", elem, expected));
+      }
+    }
+
+    public T sendNextTFromUpstream() throws InterruptedException {
+      final T x = nextT();
+      sendNext(x);
+      return x;
+    }
+  }
+
+  public class ManualSubscriberWithErrorCollection<A> extends ManualSubscriberWithSubscriptionSupport<A> {
+    Promise<Throwable> error;
+
+    public ManualSubscriberWithErrorCollection(TestEnvironment env) {
+      super(env);
+      error = new Promise<Throwable>(env);
+    }
+
+    @Override
+    public void onError(Throwable cause) {
+      error.complete(cause);
+    }
+
+    public void expectError(Throwable cause) throws InterruptedException {
+      expectError(cause, env.defaultTimeoutMillis());
+    }
+
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void expectError(Throwable cause, long timeoutMillis) throws InterruptedException {
+      error.expectCompletion(timeoutMillis, "Did not receive expected error on downstream");
+      if (!cause.equals(error.value())) {
+        env.flop(String.format("Expected error %s but got %s", cause, error.value()));
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,1245 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.tck.TestEnvironment.BlackholeSubscriberWithSubscriptionSupport;
+import org.reactivestreams.tck.TestEnvironment.Latch;
+import org.reactivestreams.tck.TestEnvironment.ManualSubscriber;
+import org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport;
+import org.reactivestreams.tck.flow.support.Function;
+import org.reactivestreams.tck.flow.support.Optional;
+import org.reactivestreams.tck.flow.support.PublisherVerificationRules;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.lang.Override;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Provides tests for verifying {@code Publisher} specification rules.
+ *
+ * @see org.reactivestreams.Publisher
+ */
+public abstract class PublisherVerification<T> implements PublisherVerificationRules {
+
+  private static final String PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV = "PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS";
+  private static final long DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS = 300L;
+
+  private final TestEnvironment env;
+
+  /**
+   * The amount of time after which a cancelled Subscriber reference should be dropped.
+   * See Rule 3.13 for details.
+   */
+  private final long publisherReferenceGCTimeoutMillis;
+
+  /**
+   * Constructs a new verification class using the given env and configuration.
+   *
+   * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher.
+   */
+  public PublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) {
+    this.env = env;
+    this.publisherReferenceGCTimeoutMillis = publisherReferenceGCTimeoutMillis;
+  }
+
+  /**
+   * Constructs a new verification class using the given env and configuration.
+   *
+   * The value for {@code publisherReferenceGCTimeoutMillis} will be obtained by using {@link PublisherVerification#envPublisherReferenceGCTimeoutMillis()}.
+   */
+  public PublisherVerification(TestEnvironment env) {
+    this.env = env;
+    this.publisherReferenceGCTimeoutMillis = envPublisherReferenceGCTimeoutMillis();
+  }
+
+  /**
+   * Tries to parse the env variable {@code PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS} as long and returns the value if present,
+   * OR its default value ({@link PublisherVerification#DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS}).
+   *
+   * This value is used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher.
+   *
+   * @throws java.lang.IllegalArgumentException when unable to parse the env variable
+   */
+  public static long envPublisherReferenceGCTimeoutMillis() {
+    final String envMillis = System.getenv(PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV);
+    if (envMillis == null) return DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS;
+    else try {
+      return Long.parseLong(envMillis);
+    } catch (NumberFormatException ex) {
+      throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV, envMillis), ex);
+    }
+  }
+
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a Publisher for a stream with exactly the given number of elements.
+   * If `elements` is `Long.MAX_VALUE` the produced stream must be infinite.
+   */
+  public abstract Publisher<T> createPublisher(long elements);
+
+  /**
+   * By implementing this method, additional TCK tests concerning a "failed" publishers will be run.
+   *
+   * The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription,
+   * followed by signalling {@code onError} on it, as specified by Rule 1.9.
+   *
+   * If you ignore these additional tests, return {@code null} from this method.
+   */
+  public abstract Publisher<T> createFailedPublisher();
+
+
+  /**
+   * Override and return lower value if your Publisher is only able to produce a known number of elements.
+   * For example, if it is designed to return at-most-one element, return {@code 1} from this method.
+   *
+   * Defaults to {@code Long.MAX_VALUE - 1}, meaning that the Publisher can be produce a huge but NOT an unbounded number of elements.
+   *
+   * To mark your Publisher will *never* signal an {@code onComplete} override this method and return {@code Long.MAX_VALUE},
+   * which will result in *skipping all tests which require an onComplete to be triggered* (!).
+   */
+  public long maxElementsFromPublisher() {
+    return Long.MAX_VALUE - 1;
+  }
+
+  /**
+   * Override and return {@code true} in order to skip executing tests marked as {@code Stochastic}.
+   * Stochastic in this case means that the Rule is impossible or infeasible to deterministically verify—
+   * usually this means that this test case can yield false positives ("be green") even if for some case,
+   * the given implementation may violate the tested behaviour.
+   */
+  public boolean skipStochasticTests() {
+    return false;
+  }
+
+  /**
+   * In order to verify rule 3.3 of the reactive streams spec, this number will be used to check if a
+   * {@code Subscription} actually solves the "unbounded recursion" problem by not allowing the number of
+   * recursive calls to exceed the number returned by this method.
+   *
+   * @see <a href="https://github.com/reactive-streams/reactive-streams-jvm#3.3">reactive streams spec, rule 3.3</a>
+   * @see PublisherVerification#required_spec303_mustNotAllowUnboundedRecursion()
+   */
+  public long boundedDepthOfOnNextAndRequestRecursion() {
+    return 1;
+  }
+
+  ////////////////////// TEST ENV CLEANUP /////////////////////////////////////
+
+  @BeforeMethod
+  public void setUp() throws Exception {
+    env.clearAsyncErrors();
+  }
+
+  ////////////////////// TEST SETUP VERIFICATION //////////////////////////////
+
+  @Override @Test
+  public void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable {
+    activePublisherTest(1, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws InterruptedException {
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced no elements", pub));
+        sub.requestEndOfStream();
+      }
+
+      Optional<T> requestNextElementOrEndOfStream(Publisher<T> pub, ManualSubscriber<T> sub) throws InterruptedException {
+        return sub.requestNextElementOrEndOfStream(String.format("Timeout while waiting for next element from Publisher %s", pub));
+      }
+
+    });
+  }
+
+  @Override @Test
+  public void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable {
+    activePublisherTest(3, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws InterruptedException {
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced no elements", pub));
+        assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced only 1 element", pub));
+        assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced only 2 elements", pub));
+        sub.requestEndOfStream();
+      }
+
+      Optional<T> requestNextElementOrEndOfStream(Publisher<T> pub, ManualSubscriber<T> sub) throws InterruptedException {
+        return sub.requestNextElementOrEndOfStream(String.format("Timeout while waiting for next element from Publisher %s", pub));
+      }
+
+    });
+  }
+
+  @Override @Test
+  public void required_validate_maxElementsFromPublisher() throws Exception {
+    assertTrue(maxElementsFromPublisher() >= 0, "maxElementsFromPublisher MUST return a number >= 0");
+  }
+
+  @Override @Test
+  public void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception {
+    assertTrue(boundedDepthOfOnNextAndRequestRecursion() >= 1, "boundedDepthOfOnNextAndRequestRecursion must return a number >= 1");
+  }
+
+
+  ////////////////////// SPEC RULE VERIFICATION ///////////////////////////////
+
+  @Override @Test
+  public void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable {
+    activePublisherTest(5, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws InterruptedException {
+
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        try {
+            sub.expectNone(String.format("Publisher %s produced value before the first `request`: ", pub));
+            sub.request(1);
+            sub.nextElement(String.format("Publisher %s produced no element after first `request`", pub));
+            sub.expectNone(String.format("Publisher %s produced unrequested: ", pub));
+
+            sub.request(1);
+            sub.request(2);
+            sub.nextElements(3, env.defaultTimeoutMillis(), String.format("Publisher %s produced less than 3 elements after two respective `request` calls", pub));
+
+            sub.expectNone(String.format("Publisher %sproduced unrequested ", pub));
+        } finally {
+            sub.cancel();
+        }
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable {
+    final int elements = 3;
+    final int requested = 10;
+
+    activePublisherTest(elements, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.request(requested);
+        sub.nextElements(elements);
+        sub.expectCompletion();
+      }
+    });
+  }
+
+  @Override @Test
+  public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable {
+    final int iterations = 100;
+    final int elements = 10;
+
+    stochasticTest(iterations, new Function<Integer, Void>() {
+      @Override
+      public Void apply(final Integer runNumber) throws Throwable {
+        activePublisherTest(elements, true, new PublisherTestRun<T>() {
+          @Override
+          public void run(Publisher<T> pub) throws Throwable {
+            final Latch completionLatch = new Latch(env);
+
+            final AtomicInteger gotElements = new AtomicInteger(0);
+            pub.subscribe(new Subscriber<T>() {
+              private Subscription subs;
+
+              private ConcurrentAccessBarrier concurrentAccessBarrier = new ConcurrentAccessBarrier();
+
+              /**
+               * Concept wise very similar to a {@link org.reactivestreams.tck.TestEnvironment.Latch}, serves to protect
+               * a critical section from concurrent access, with the added benefit of Thread tracking and same-thread-access awareness.
+               *
+               * Since a <i>Synchronous</i> Publisher may choose to synchronously (using the same {@link Thread}) call
+               * {@code onNext} directly from either {@code subscribe} or {@code request} a plain Latch is not enough
+               * to verify concurrent access safety - one needs to track if the caller is not still using the calling thread
+               * to enter subsequent critical sections ("nesting" them effectively).
+               */
+              final class ConcurrentAccessBarrier {
+                private AtomicReference<Thread> currentlySignallingThread = new AtomicReference<Thread>(null);
+                private volatile String previousSignal = null;
+
+                public void enterSignal(String signalName) {
+                  if((!currentlySignallingThread.compareAndSet(null, Thread.currentThread())) && !isSynchronousSignal()) {
+                    env.flop(String.format(
+                      "Illegal concurrent access detected (entering critical section)! " +
+                        "%s emited %s signal, before %s finished its %s signal.",
+                        Thread.currentThread(), signalName, currentlySignallingThread.get(), previousSignal));
+                  }
+                  this.previousSignal = signalName;
+                }
+
+                public void leaveSignal(String signalName) {
+                  currentlySignallingThread.set(null);
+                  this.previousSignal = signalName;
+                }
+
+                private boolean isSynchronousSignal() {
+                  return (previousSignal != null) && Thread.currentThread().equals(currentlySignallingThread.get());
+                }
+
+              }
+
+              @Override
+              public void onSubscribe(Subscription s) {
+                final String signal = "onSubscribe()";
+                concurrentAccessBarrier.enterSignal(signal);
+
+                subs = s;
+                subs.request(1);
+
+                concurrentAccessBarrier.leaveSignal(signal);
+              }
+
+              @Override
+              public void onNext(T ignore) {
+                final String signal = String.format("onNext(%s)", ignore);
+                concurrentAccessBarrier.enterSignal(signal);
+
+                if (gotElements.incrementAndGet() <= elements) // requesting one more than we know are in the stream (some Publishers need this)
+                  subs.request(1);
+
+                concurrentAccessBarrier.leaveSignal(signal);
+              }
+
+              @Override
+              public void onError(Throwable t) {
+                final String signal = String.format("onError(%s)", t.getMessage());
+                concurrentAccessBarrier.enterSignal(signal);
+
+                // ignore value
+
+                concurrentAccessBarrier.leaveSignal(signal);
+              }
+
+              @Override
+              public void onComplete() {
+                final String signal = "onComplete()";
+                concurrentAccessBarrier.enterSignal(signal);
+
+                // entering for completeness
+
+                concurrentAccessBarrier.leaveSignal(signal);
+                completionLatch.close();
+              }
+            });
+
+            completionLatch.expectClose(
+              elements * env.defaultTimeoutMillis(),
+              String.format("Failed in iteration %d of %d. Expected completion signal after signalling %d elements (signalled %d), yet did not receive it",
+                            runNumber, iterations, elements, gotElements.get()));
+          }
+        });
+        return null;
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable {
+    try {
+      whenHasErrorPublisherTest(new PublisherTestRun<T>() {
+        @Override
+        public void run(final Publisher<T> pub) throws InterruptedException {
+          final Latch onErrorlatch = new Latch(env);
+          final Latch onSubscribeLatch = new Latch(env);
+          pub.subscribe(new TestEnvironment.TestSubscriber<T>(env) {
+            @Override
+            public void onSubscribe(Subscription subs) {
+              onSubscribeLatch.assertOpen("Only one onSubscribe call expected");
+              onSubscribeLatch.close();
+            }
+            @Override
+            public void onError(Throwable cause) {
+              onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always");
+              onErrorlatch.assertOpen(String.format("Error-state Publisher %s called `onError` twice on new Subscriber", pub));
+              onErrorlatch.close();
+            }
+          });
+
+          onSubscribeLatch.expectClose("Should have received onSubscribe");
+          onErrorlatch.expectClose(String.format("Error-state Publisher %s did not call `onError` on new Subscriber", pub));
+
+          env.verifyNoAsyncErrors();
+          }
+      });
+    } catch (SkipException se) {
+      throw se;
+    } catch (Throwable ex) {
+      // we also want to catch AssertionErrors and anything the publisher may have thrown inside subscribe
+      // which was wrong of him - he should have signalled on error using onError
+      throw new RuntimeException(String.format("Publisher threw exception (%s) instead of signalling error via onError!", ex.getMessage()), ex);
+    }
+  }
+
+  @Override @Test
+  public void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable {
+    activePublisherTest(3, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.requestNextElement();
+        sub.requestNextElement();
+        sub.requestNextElement();
+        sub.requestEndOfStream();
+        sub.expectNone();
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable {
+    optionalActivePublisherTest(0, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.request(1);
+        sub.expectCompletion();
+        sub.expectNone();
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable {
+    notVerified(); // not really testable without more control over the Publisher
+  }
+
+  @Override @Test
+  public void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable {
+    activePublisherTest(1, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.request(10);
+        sub.nextElement();
+        sub.expectCompletion();
+
+        sub.request(10);
+        sub.expectNone();
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable {
+    notVerified(); // can we meaningfully test this, without more control over the publisher?
+  }
+
+  @Override @Test
+  public void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable {
+    notVerified(); // can we meaningfully test this?
+  }
+
+  @Override @Test
+  public void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable {
+    notVerified(); // can we meaningfully test this?
+  }
+
+  @Override @Test
+  public void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable {
+    activePublisherTest(0, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        try {
+            pub.subscribe(null);
+            env.flop("Publisher did not throw a NullPointerException when given a null Subscribe in subscribe");
+        } catch (NullPointerException ignored) {
+          // valid behaviour
+        }
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable {
+    activePublisherTest(0, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final Latch onSubscribeLatch = new Latch(env);
+        final AtomicReference<Subscription> cancel = new AtomicReference<Subscription>();
+        try {
+          pub.subscribe(new Subscriber<T>() {
+            @Override
+            public void onError(Throwable cause) {
+              onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always");
+            }
+
+            @Override
+            public void onSubscribe(Subscription subs) {
+              cancel.set(subs);
+              onSubscribeLatch.assertOpen("Only one onSubscribe call expected");
+              onSubscribeLatch.close();
+            }
+
+            @Override
+            public void onNext(T elem) {
+              onSubscribeLatch.assertClosed("onSubscribe should be called prior to onNext always");
+            }
+
+            @Override
+            public void onComplete() {
+              onSubscribeLatch.assertClosed("onSubscribe should be called prior to onComplete always");
+            }
+          });
+          onSubscribeLatch.expectClose("Should have received onSubscribe");
+          env.verifyNoAsyncErrorsNoDelay();
+        } finally {
+          Subscription s = cancel.getAndSet(null);
+          if (s != null) {
+            s.cancel();
+          }
+        }
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable {
+    whenHasErrorPublisherTest(new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final Latch onErrorLatch = new Latch(env);
+        final Latch onSubscribeLatch = new Latch(env);
+        ManualSubscriberWithSubscriptionSupport<T> sub = new ManualSubscriberWithSubscriptionSupport<T>(env) {
+          @Override
+          public void onError(Throwable cause) {
+            onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always");
+            onErrorLatch.assertOpen("Only one onError call expected");
+            onErrorLatch.close();
+          }
+
+          @Override
+          public void onSubscribe(Subscription subs) {
+            onSubscribeLatch.assertOpen("Only one onSubscribe call expected");
+            onSubscribeLatch.close();
+          }
+        };
+        pub.subscribe(sub);
+        onSubscribeLatch.expectClose("Should have received onSubscribe");
+        onErrorLatch.expectClose("Should have received onError");
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable {
+    notVerified(); // can we meaningfully test this?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#1.11
+  @Override @Test
+  public void optional_spec111_maySupportMultiSubscribe() throws Throwable {
+    optionalActivePublisherTest(1, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub1 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub2 = env.newManualSubscriber(pub);
+
+        try {
+          env.verifyNoAsyncErrors();
+        } finally {
+          try {
+            sub1.cancel();
+          } finally {
+            sub2.cancel();
+          }
+        }
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable {
+    optionalActivePublisherTest(1, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub1 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub2 = env.newManualSubscriber(pub);
+        // Since we're testing the case when the Publisher DOES support the optional multi-subscribers scenario,
+        // and decides if it handles them uni-cast or multi-cast, we don't know which subscriber will receive an
+        // onNext (and optional onComplete) signal(s) and which just onComplete signal.
+        // Plus, even if subscription assumed to be unicast, it's implementation choice, which one will be signalled
+        // with onNext.
+        sub1.requestNextElementOrEndOfStream();
+        sub2.requestNextElementOrEndOfStream();
+        try {
+            env.verifyNoAsyncErrors();
+        } finally {
+            try {
+                sub1.cancel();
+            } finally {
+                sub2.cancel();
+            }
+        }
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable {
+    optionalActivePublisherTest(5, true, new PublisherTestRun<T>() { // This test is skipped if the publisher is unbounded (never sends onComplete)
+      @Override
+      public void run(Publisher<T> pub) throws InterruptedException {
+        ManualSubscriber<T> sub1 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub2 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub3 = env.newManualSubscriber(pub);
+
+        sub1.request(1);
+        T x1 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub));
+        sub2.request(2);
+        List<T> y1 = sub2.nextElements(2, String.format("Publisher %s did not produce the requested 2 elements on 2nd subscriber", pub));
+        sub1.request(1);
+        T x2 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub));
+        sub3.request(3);
+        List<T> z1 = sub3.nextElements(3, String.format("Publisher %s did not produce the requested 3 elements on 3rd subscriber", pub));
+        sub3.request(1);
+        T z2 = sub3.nextElement(String.format("Publisher %s did not produce the requested 1 element on 3rd subscriber", pub));
+        sub3.request(1);
+        T z3 = sub3.nextElement(String.format("Publisher %s did not produce the requested 1 element on 3rd subscriber", pub));
+        sub3.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 3rd subscriber", pub));
+        sub2.request(3);
+        List<T> y2 = sub2.nextElements(3, String.format("Publisher %s did not produce the requested 3 elements on 2nd subscriber", pub));
+        sub2.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 2nd subscriber", pub));
+        sub1.request(2);
+        List<T> x3 = sub1.nextElements(2, String.format("Publisher %s did not produce the requested 2 elements on 1st subscriber", pub));
+        sub1.request(1);
+        T x4 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub));
+        sub1.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 1st subscriber", pub));
+
+        @SuppressWarnings("unchecked")
+        List<T> r = new ArrayList<T>(Arrays.asList(x1, x2));
+        r.addAll(x3);
+        r.addAll(Collections.singleton(x4));
+
+        List<T> check1 = new ArrayList<T>(y1);
+        check1.addAll(y2);
+
+        //noinspection unchecked
+        List<T> check2 = new ArrayList<T>(z1);
+        check2.add(z2);
+        check2.add(z3);
+
+        assertEquals(r, check1, String.format("Publisher %s did not produce the same element sequence for subscribers 1 and 2", pub));
+        assertEquals(r, check2, String.format("Publisher %s did not produce the same element sequence for subscribers 1 and 3", pub));
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable {
+    optionalActivePublisherTest(3, false, new PublisherTestRun<T>() { // This test is skipped if the publisher cannot produce enough elements
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub1 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub2 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub3 = env.newManualSubscriber(pub);
+
+        List<T> received1 = new ArrayList<T>();
+        List<T> received2 = new ArrayList<T>();
+        List<T> received3 = new ArrayList<T>();
+
+        // if the publisher must touch it's source to notice it's been drained, the OnComplete won't come until we ask for more than it actually contains...
+        // edgy edge case?
+        sub1.request(4);
+        sub2.request(4);
+        sub3.request(4);
+
+        received1.addAll(sub1.nextElements(3));
+        received2.addAll(sub2.nextElements(3));
+        received3.addAll(sub3.nextElements(3));
+
+        // NOTE: can't check completion, the Publisher may not be able to signal it
+        //       a similar test *with* completion checking is implemented
+
+        assertEquals(received1, received2, String.format("Expected elements to be signaled in the same sequence to 1st and 2nd subscribers"));
+        assertEquals(received2, received3, String.format("Expected elements to be signaled in the same sequence to 2nd and 3rd subscribers"));
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable {
+    optionalActivePublisherTest(3, true, new PublisherTestRun<T>() { // This test is skipped if the publisher is unbounded (never sends onComplete)
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub1 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub2 = env.newManualSubscriber(pub);
+        ManualSubscriber<T> sub3 = env.newManualSubscriber(pub);
+
+        List<T> received1 = new ArrayList<T>();
+        List<T> received2 = new ArrayList<T>();
+        List<T> received3 = new ArrayList<T>();
+
+        // if the publisher must touch it's source to notice it's been drained, the OnComplete won't come until we ask for more than it actually contains...
+        // edgy edge case?
+        sub1.request(4);
+        sub2.request(4);
+        sub3.request(4);
+
+        received1.addAll(sub1.nextElements(3));
+        received2.addAll(sub2.nextElements(3));
+        received3.addAll(sub3.nextElements(3));
+
+        sub1.expectCompletion();
+        sub2.expectCompletion();
+        sub3.expectCompletion();
+
+        assertEquals(received1, received2, String.format("Expected elements to be signaled in the same sequence to 1st and 2nd subscribers"));
+        assertEquals(received2, received3, String.format("Expected elements to be signaled in the same sequence to 2nd and 3rd subscribers"));
+      }
+    });
+  }
+
+  ///////////////////// SUBSCRIPTION TESTS //////////////////////////////////
+
+  @Override @Test
+  public void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable {
+    activePublisherTest(6, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub = new ManualSubscriber<T>(env) {
+          @Override
+          public void onSubscribe(Subscription subs) {
+            this.subscription.completeImmediatly(subs);
+
+            subs.request(1);
+            subs.request(1);
+            subs.request(1);
+          }
+
+          @Override
+          public void onNext(T element) {
+            Subscription subs = this.subscription.value();
+            subs.request(1);
+          }
+        };
+
+        env.subscribe(pub, sub);
+
+        env.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable {
+    final long oneMoreThanBoundedLimit = boundedDepthOfOnNextAndRequestRecursion() + 1;
+
+    activePublisherTest(oneMoreThanBoundedLimit, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final ThreadLocal<Long> stackDepthCounter = new ThreadLocal<Long>() {
+          @Override
+          protected Long initialValue() {
+            return 0L;
+          }
+        };
+
+        final Latch runCompleted = new Latch(env);
+
+        final ManualSubscriber<T> sub = new ManualSubscriberWithSubscriptionSupport<T>(env) {
+          // counts the number of signals received, used to break out from possibly infinite request/onNext loops
+          long signalsReceived = 0L;
+
+          @Override
+          public void onNext(T element) {
+            // NOT calling super.onNext as this test only cares about stack depths, not the actual values of elements
+            // which also simplifies this test as we do not have to drain the test buffer, which would otherwise be in danger of overflowing
+
+            signalsReceived += 1;
+            stackDepthCounter.set(stackDepthCounter.get() + 1);
+            if (env.debugEnabled()) {
+              env.debug(String.format("%s(recursion depth: %d)::onNext(%s)", this, stackDepthCounter.get(), element));
+            }
+
+            final long callsUntilNow = stackDepthCounter.get();
+            if (callsUntilNow > boundedDepthOfOnNextAndRequestRecursion()) {
+              env.flop(String.format("Got %d onNext calls within thread: %s, yet expected recursive bound was %d",
+                                     callsUntilNow, Thread.currentThread(), boundedDepthOfOnNextAndRequestRecursion()));
+
+              // stop the recursive call chain
+              runCompleted.close();
+              return;
+            } else if (signalsReceived >= oneMoreThanBoundedLimit) {
+              // since max number of signals reached, and recursion depth not exceeded, we judge this as a success and
+              // stop the recursive call chain
+              runCompleted.close();
+              return;
+            }
+
+            // request more right away, the Publisher must break the recursion
+            subscription.value().request(1);
+
+            stackDepthCounter.set(stackDepthCounter.get() - 1);
+          }
+
+          @Override
+          public void onComplete() {
+            super.onComplete();
+            runCompleted.close();
+          }
+
+          @Override
+          public void onError(Throwable cause) {
+            super.onError(cause);
+            runCompleted.close();
+          }
+        };
+
+        try {
+          env.subscribe(pub, sub);
+
+          sub.request(1); // kick-off the `request -> onNext -> request -> onNext -> ...`
+
+          final String msg = String.format("Unable to validate call stack depth safety, " +
+                                               "awaited at-most %s signals (`maxOnNextSignalsInRecursionTest()`) or completion",
+                                           oneMoreThanBoundedLimit);
+          runCompleted.expectClose(env.defaultTimeoutMillis(), msg);
+          env.verifyNoAsyncErrorsNoDelay();
+        } finally {
+          // since the request/onNext recursive calls may keep the publisher running "forever",
+          // we MUST cancel it manually before exiting this test case
+          sub.cancel();
+        }
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable {
+    activePublisherTest(3, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+
+        // override ManualSubscriberWithSubscriptionSupport#cancel because by default a ManualSubscriber will drop the
+        // subscription once it's cancelled (as expected).
+        // In this test however it must keep the cancelled Subscription and keep issuing `request(long)` to it.
+        ManualSubscriber<T> sub = new ManualSubscriberWithSubscriptionSupport<T>(env) {
+          @Override
+          public void cancel() {
+            if (subscription.isCompleted()) {
+              subscription.value().cancel();
+            } else {
+              env.flop("Cannot cancel a subscription before having received it");
+            }
+          }
+        };
+
+        env.subscribe(pub, sub);
+
+        sub.cancel();
+        sub.request(1);
+        sub.request(1);
+        sub.request(1);
+
+        sub.expectNone();
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable {
+    activePublisherTest(1, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+
+        // leak the Subscription
+        final Subscription subs = sub.subscription.value();
+
+        subs.cancel();
+        subs.cancel();
+        subs.cancel();
+
+        sub.expectNone();
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable {
+    activePublisherTest(10, false, new PublisherTestRun<T>() {
+      @Override public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.request(0);
+        sub.expectError(IllegalArgumentException.class);
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable {
+    activePublisherTest(10, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        final Random r = new Random();
+        sub.request(-r.nextInt(Integer.MAX_VALUE) - 1);
+        // we do require implementations to mention the rule number at the very least, or mentioning that the non-negative request is the problem
+        sub.expectError(IllegalArgumentException.class);
+      }
+    });
+  }
+
+  @Override @Test
+  public void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable {
+    optionalActivePublisherTest(10, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        final Random r = new Random();
+        sub.request(-r.nextInt(Integer.MAX_VALUE) - 1);
+        // we do require implementations to mention the rule number at the very least, or mentioning that the non-negative request is the problem
+        sub.expectErrorWithMessage(IllegalArgumentException.class, Arrays.asList("3.9", "non-positive subscription request", "negative subscription request"));
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable {
+    // the publisher is able to signal more elements than the subscriber will be requesting in total
+    final int publisherElements = 20;
+
+    final int demand1 = 10;
+    final int demand2 = 5;
+    final int totalDemand = demand1 + demand2;
+
+    activePublisherTest(publisherElements, false, new PublisherTestRun<T>() {
+      @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+      public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+
+        sub.request(demand1);
+        sub.request(demand2);
+
+        /*
+          NOTE: The order of the nextElement/cancel calls below is very important (!)
+
+          If this ordering was reversed, given an asynchronous publisher,
+          the following scenario would be *legal* and would break this test:
+
+          > AsyncPublisher receives request(10) - it does not emit data right away, it's asynchronous
+          > AsyncPublisher receives request(5) - demand is now 15
+          ! AsyncPublisher didn't emit any onNext yet (!)
+          > AsyncPublisher receives cancel() - handles it right away, by "stopping itself" for example
+          ! cancel was handled hefore the AsyncPublisher ever got the chance to emit data
+          ! the subscriber ends up never receiving even one element - the test is stuck (and fails, even on valid Publisher)
+
+          Which is why we must first expect an element, and then cancel, once the producing is "running".
+         */
+        sub.nextElement();
+        sub.cancel();
+
+        int onNextsSignalled = 1;
+
+        boolean stillBeingSignalled;
+        do {
+          // put asyncError if onNext signal received
+          sub.expectNone();
+          Throwable error = env.dropAsyncError();
+
+          if (error == null) {
+            stillBeingSignalled = false;
+          } else {
+            onNextsSignalled += 1;
+            stillBeingSignalled = true;
+          }
+
+          // if the Publisher tries to emit more elements than was requested (and/or ignores cancellation) this will throw
+          assertTrue(onNextsSignalled <= totalDemand,
+                     String.format("Publisher signalled [%d] elements, which is more than the signalled demand: %d",
+                                   onNextsSignalled, totalDemand));
+
+        } while (stillBeingSignalled);
+      }
+    });
+
+    env.verifyNoAsyncErrorsNoDelay();
+  }
+
+  @Override @Test
+  public void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable {
+    final ReferenceQueue<ManualSubscriber<T>> queue = new ReferenceQueue<ManualSubscriber<T>>();
+
+    final Function<Publisher<T>, WeakReference<ManualSubscriber<T>>> run = new Function<Publisher<T>, WeakReference<ManualSubscriber<T>>>() {
+      @Override
+      public WeakReference<ManualSubscriber<T>> apply(Publisher<T> pub) throws Exception {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        final WeakReference<ManualSubscriber<T>> ref = new WeakReference<ManualSubscriber<T>>(sub, queue);
+
+        sub.request(1);
+        sub.nextElement();
+        sub.cancel();
+
+        return ref;
+      }
+    };
+
+    activePublisherTest(3, false, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final WeakReference<ManualSubscriber<T>> ref = run.apply(pub);
+
+        // cancel may be run asynchronously so we add a sleep before running the GC
+        // to "resolve" the race
+        Thread.sleep(publisherReferenceGCTimeoutMillis);
+        System.gc();
+
+        if (!ref.equals(queue.remove(100))) {
+          env.flop(String.format("Publisher %s did not drop reference to test subscriber after subscription cancellation", pub));
+        }
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable {
+    final int totalElements = 3;
+
+    activePublisherTest(totalElements, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.request(Long.MAX_VALUE);
+
+        sub.nextElements(totalElements);
+        sub.expectCompletion();
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable {
+    final int totalElements = 3;
+
+    activePublisherTest(totalElements, true, new PublisherTestRun<T>() {
+      @Override
+      public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriber<T> sub = env.newManualSubscriber(pub);
+        sub.request(Long.MAX_VALUE / 2); // pending = Long.MAX_VALUE / 2
+        sub.request(Long.MAX_VALUE / 2); // pending = Long.MAX_VALUE - 1
+        sub.request(1); // pending = Long.MAX_VALUE
+
+        sub.nextElements(totalElements);
+        sub.expectCompletion();
+
+        try {
+          env.verifyNoAsyncErrorsNoDelay();
+        } finally {
+          sub.cancel();
+        }
+
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable {
+    activePublisherTest(Integer.MAX_VALUE, false, new PublisherTestRun<T>() {
+      @Override public void run(Publisher<T> pub) throws Throwable {
+        final ManualSubscriberWithSubscriptionSupport<T> sub = new BlackholeSubscriberWithSubscriptionSupport<T>(env) {
+           // arbitrarily set limit on nuber of request calls signalled, we expect overflow after already 2 calls,
+           // so 10 is relatively high and safe even if arbitrarily chosen
+          int callsCounter = 10;
+
+          @Override
+          public void onNext(T element) {
+            if (env.debugEnabled()) {
+              env.debug(String.format("%s::onNext(%s)", this, element));
+            }
+            if (subscription.isCompleted()) {
+              if (callsCounter > 0) {
+                subscription.value().request(Long.MAX_VALUE - 1);
+                callsCounter--;
+              } else {
+                  subscription.value().cancel();
+              }
+            } else {
+              env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element));
+            }
+          }
+        };
+        env.subscribe(pub, sub, env.defaultTimeoutMillis());
+
+        // eventually triggers `onNext`, which will then trigger up to `callsCounter` times `request(Long.MAX_VALUE - 1)`
+        // we're pretty sure to overflow from those
+        sub.request(1);
+
+        // no onError should be signalled
+        try {
+          env.verifyNoAsyncErrors();
+        } finally {
+          sub.cancel();
+        }
+      }
+    });
+  }
+
+  ///////////////////// ADDITIONAL "COROLLARY" TESTS ////////////////////////
+
+  ///////////////////// TEST INFRASTRUCTURE /////////////////////////////////
+
+  public interface PublisherTestRun<T> {
+    public void run(Publisher<T> pub) throws Throwable;
+  }
+
+  /**
+   * Test for feature that SHOULD/MUST be implemented, using a live publisher.
+   *
+   * @param elements the number of elements the Publisher under test  must be able to emit to run this test
+   * @param completionSignalRequired true if an {@code onComplete} signal is required by this test to run.
+   *                                 If the tested Publisher is unable to signal completion, tests requireing onComplete signals will be skipped.
+   *                                 To signal if your Publisher is able to signal completion see {@link PublisherVerification#maxElementsFromPublisher()}.
+   */
+  public void activePublisherTest(long elements, boolean completionSignalRequired, PublisherTestRun<T> body) throws Throwable {
+    if (elements > maxElementsFromPublisher()) {
+      throw new SkipException(String.format("Unable to run this test, as required elements nr: %d is higher than supported by given producer: %d", elements, maxElementsFromPublisher()));
+    } else if (completionSignalRequired && maxElementsFromPublisher() == Long.MAX_VALUE) {
+      throw new SkipException("Unable to run this test, as it requires an onComplete signal, " +
+                                "which this Publisher is unable to provide (as signalled by returning Long.MAX_VALUE from `maxElementsFromPublisher()`)");
+    } else {
+      Publisher<T> pub = createPublisher(elements);
+      body.run(pub);
+      env.verifyNoAsyncErrorsNoDelay();
+    }
+  }
+
+  /**
+   * Test for feature that MAY be implemented. This test will be marked as SKIPPED if it fails.
+   *
+   * @param elements the number of elements the Publisher under test  must be able to emit to run this test
+   * @param completionSignalRequired true if an {@code onComplete} signal is required by this test to run.
+   *                                 If the tested Publisher is unable to signal completion, tests requireing onComplete signals will be skipped.
+   *                                 To signal if your Publisher is able to signal completion see {@link PublisherVerification#maxElementsFromPublisher()}.
+   */
+  public void optionalActivePublisherTest(long elements, boolean completionSignalRequired, PublisherTestRun<T> body) throws Throwable {
+    if (elements > maxElementsFromPublisher()) {
+      throw new SkipException(String.format("Unable to run this test, as required elements nr: %d is higher than supported by given producer: %d", elements, maxElementsFromPublisher()));
+    } else if (completionSignalRequired && maxElementsFromPublisher() == Long.MAX_VALUE) {
+      throw new SkipException("Unable to run this test, as it requires an onComplete signal, " +
+                                "which this Publisher is unable to provide (as signalled by returning Long.MAX_VALUE from `maxElementsFromPublisher()`)");
+    } else {
+
+      final Publisher<T> pub = createPublisher(elements);
+      final String skipMessage = "Skipped because tested publisher does NOT implement this OPTIONAL requirement.";
+
+      try {
+        potentiallyPendingTest(pub, body);
+      } catch (Exception ex) {
+        notVerified(skipMessage);
+      } catch (AssertionError ex) {
+        notVerified(skipMessage + " Reason for skipping was: " + ex.getMessage());
+      }
+    }
+  }
+
+  public static final String SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE =
+    "Skipping because no error state Publisher provided, and the test requires it. " +
+          "Please implement PublisherVerification#createFailedPublisher to run this test.";
+
+  public static final String SKIPPING_OPTIONAL_TEST_FAILED =
+    "Skipping, because provided Publisher does not pass this *additional* verification.";
+  /**
+   * Additional test for Publisher in error state
+   */
+  public void whenHasErrorPublisherTest(PublisherTestRun<T> body) throws Throwable {
+    potentiallyPendingTest(createFailedPublisher(), body, SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE);
+  }
+
+  public void potentiallyPendingTest(Publisher<T> pub, PublisherTestRun<T> body) throws Throwable {
+    potentiallyPendingTest(pub, body, SKIPPING_OPTIONAL_TEST_FAILED);
+  }
+
+  public void potentiallyPendingTest(Publisher<T> pub, PublisherTestRun<T> body, String message) throws Throwable {
+    if (pub != null) {
+      body.run(pub);
+    } else {
+      throw new SkipException(message);
+    }
+  }
+
+  /**
+   * Executes a given test body {@code n} times.
+   * All the test runs must pass in order for the stochastic test to pass.
+   */
+  public void stochasticTest(int n, Function<Integer, Void> body) throws Throwable {
+    if (skipStochasticTests()) {
+      notVerified("Skipping @Stochastic test because `skipStochasticTests()` returned `true`!");
+    }
+
+    for (int i = 0; i < n; i++) {
+      body.apply(i);
+    }
+  }
+
+  public void notVerified() {
+    throw new SkipException("Not verified by this TCK.");
+  }
+
+  /**
+   * Return this value from {@link PublisherVerification#maxElementsFromPublisher()} to mark that the given {@link org.reactivestreams.Publisher},
+   * is not able to signal completion. For example it is strictly a time-bound or unbounded source of data.
+   *
+   * <b>Returning this value from {@link PublisherVerification#maxElementsFromPublisher()} will result in skipping all TCK tests which require onComplete signals!</b>
+   */
+  public long publisherUnableToSignalOnComplete() {
+    return Long.MAX_VALUE;
+  }
+
+  public void notVerified(String message) {
+    throw new SkipException(message);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.tck.TestEnvironment.ManualPublisher;
+import org.reactivestreams.tck.TestEnvironment.ManualSubscriber;
+import org.reactivestreams.tck.flow.support.Optional;
+import org.reactivestreams.tck.flow.support.SubscriberBlackboxVerificationRules;
+import org.reactivestreams.tck.flow.support.TestException;
+import org.testng.SkipException;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.reactivestreams.tck.SubscriberWhiteboxVerification.BlackboxSubscriberProxy;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Provides tests for verifying {@link org.reactivestreams.Subscriber} and {@link org.reactivestreams.Subscription}
+ * specification rules, without any modifications to the tested implementation (also known as "Black Box" testing).
+ *
+ * This verification is NOT able to check many of the rules of the spec, and if you want more
+ * verification of your implementation you'll have to implement {@code org.reactivestreams.tck.SubscriberWhiteboxVerification}
+ * instead.
+ *
+ * @see org.reactivestreams.Subscriber
+ * @see org.reactivestreams.Subscription
+ */
+public abstract class SubscriberBlackboxVerification<T> extends WithHelperPublisher<T>
+  implements SubscriberBlackboxVerificationRules {
+
+  protected final TestEnvironment env;
+
+  protected SubscriberBlackboxVerification(TestEnvironment env) {
+    this.env = env;
+  }
+
+  // USER API
+
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic.
+   */
+  public abstract Subscriber<T> createSubscriber();
+
+  /**
+   * Override this method if the Subscriber implementation you are verifying
+   * needs an external signal before it signals demand to its Publisher.
+   *
+   * By default this method does nothing.
+   */
+  public void triggerRequest(final Subscriber<? super T> subscriber) {
+    // this method is intentionally left blank
+  }
+
+  // ENV SETUP
+
+  /**
+   * Executor service used by the default provided asynchronous Publisher.
+   * @see #createHelperPublisher(long)
+   */
+  private ExecutorService publisherExecutor;
+  @BeforeClass public void startPublisherExecutorService() { publisherExecutor = Executors.newFixedThreadPool(4); }
+  @AfterClass public void shutdownPublisherExecutorService() { if (publisherExecutor != null) publisherExecutor.shutdown(); }
+  @Override public ExecutorService publisherExecutorService() { return publisherExecutor; }
+
+  ////////////////////// TEST ENV CLEANUP /////////////////////////////////////
+
+  @BeforeMethod
+  public void setUp() throws Exception {
+    env.clearAsyncErrors();
+  }
+
+  ////////////////////// SPEC RULE VERIFICATION ///////////////////////////////
+
+  @Override @Test
+  public void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable {
+    blackboxSubscriberTest(new BlackboxTestStageTestRun() {
+      @Override
+      public void run(BlackboxTestStage stage) throws InterruptedException {
+        triggerRequest(stage.subProxy().sub());
+        final long requested = stage.expectRequest();// assuming subscriber wants to consume elements...
+        final long signalsToEmit = Math.min(requested, 512); // protecting against Subscriber which sends ridiculous large demand
+
+        // should cope with up to requested number of elements
+        for (int i = 0; i < signalsToEmit && sampleIsCancelled(stage, i, 10); i++)
+          stage.signalNext();
+
+        // we complete after `signalsToEmit` (which can be less than `requested`),
+        // which is legal under https://github.com/reactive-streams/reactive-streams-jvm#1.2
+        stage.sendCompletion();
+      }
+
+      /**
+       * In order to allow some "skid" and not check state on each iteration,
+       * only check {@code stage.isCancelled} every {@code checkInterval}'th iteration.
+       */
+      private boolean sampleIsCancelled(BlackboxTestStage stage, int i, int checkInterval) throws InterruptedException {
+        if (i % checkInterval == 0) return stage.isCancelled();
+        else return false;
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable {
+    blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() {
+      @Override
+      public void run(BlackboxTestStage stage) throws Throwable {
+        final Subscription subs = new Subscription() {
+          @Override
+          public void request(long n) {
+            final Optional<StackTraceElement> onCompleteStackTraceElement = env.findCallerMethodInStackTrace("onComplete");
+            if (onCompleteStackTraceElement.isDefined()) {
+              final StackTraceElement stackElem = onCompleteStackTraceElement.get();
+              env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)",
+                                     stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+            }
+          }
+
+          @Override
+          public void cancel() {
+            final Optional<StackTraceElement> onCompleteStackElement = env.findCallerMethodInStackTrace("onComplete");
+            if (onCompleteStackElement.isDefined()) {
+              final StackTraceElement stackElem = onCompleteStackElement.get();
+              env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)",
+                                     stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+            }
+          }
+        };
+
+        final Subscriber<T> sub = createSubscriber();
+        sub.onSubscribe(subs);
+        sub.onComplete();
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable {
+    blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() {
+      @Override
+      public void run(BlackboxTestStage stage) throws Throwable {
+        final Subscription subs = new Subscription() {
+          @Override
+          public void request(long n) {
+            Throwable thr = new Throwable();
+            for (StackTraceElement stackElem : thr.getStackTrace()) {
+              if (stackElem.getMethodName().equals("onError")) {
+                env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)",
+                                       stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+              }
+            }
+          }
+
+          @Override
+          public void cancel() {
+            Throwable thr = new Throwable();
+            for (StackTraceElement stackElem : thr.getStackTrace()) {
+              if (stackElem.getMethodName().equals("onError")) {
+                env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)",
+                                       stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+              }
+            }
+          }
+        };
+
+        final Subscriber<T> sub = createSubscriber();
+        sub.onSubscribe(subs);
+        sub.onError(new TestException());
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception {
+    new BlackboxTestStage(env) {{
+      // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail
+      final TestEnvironment.Latch secondSubscriptionCancelled = new TestEnvironment.Latch(env);
+      sub().onSubscribe(
+          new Subscription() {
+            @Override
+            public void request(long elements) {
+              env.flop(String.format("Subscriber %s illegally called `subscription.request(%s)`!", sub(), elements));
+            }
+
+            @Override
+            public void cancel() {
+              secondSubscriptionCancelled.close();
+            }
+
+            @Override
+            public String toString() {
+              return "SecondSubscription(should get cancelled)";
+            }
+          });
+
+      secondSubscriptionCancelled.expectClose("Expected SecondSubscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called.");
+      env.verifyNoAsyncErrorsNoDelay();
+      sendCompletion(); // we're done, complete the subscriber under test
+    }};
+  }
+
+  @Override @Test
+  public void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+    // the same thread part of the clause can be verified but that is not very useful, or is it?
+  }
+
+  @Override @Test
+  public void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable {
+    notVerified(); // cannot be meaningfully tested as black box, or can it?
+  }
+
+  @Override @Test
+  public void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable {
+    blackboxSubscriberTest(new BlackboxTestStageTestRun() {
+      @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+      public void run(BlackboxTestStage stage) throws Throwable {
+        triggerRequest(stage.subProxy().sub());
+        final long notUsed = stage.expectRequest(); // received request signal
+        stage.sub().onComplete();
+        stage.subProxy().expectCompletion();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable {
+    blackboxSubscriberTest(new BlackboxTestStageTestRun() {
+      @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+      public void run(BlackboxTestStage stage) throws Throwable {
+        final Subscriber<? super T> sub = stage.sub();
+        sub.onComplete();
+        stage.subProxy().expectCompletion();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable {
+    blackboxSubscriberTest(new BlackboxTestStageTestRun() {
+      @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+      public void run(BlackboxTestStage stage) throws Throwable {
+        triggerRequest(stage.subProxy().sub());
+        final long notUsed = stage.expectRequest(); // received request signal
+        stage.sub().onError(new TestException()); // in response to that, we fail
+        stage.subProxy().expectError(Throwable.class);
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10
+  @Override @Test
+  public void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable {
+    blackboxSubscriberTest(new BlackboxTestStageTestRun() {
+      @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+      public void run(BlackboxTestStage stage) throws Throwable {
+
+        stage.sub().onError(new TestException());
+        stage.subProxy().expectError(Throwable.class);
+      }
+    });
+  }
+
+  @Override @Test
+  public void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable {
+    notVerified(); // cannot be meaningfully tested as black box, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() {
+      @Override
+      public void run(BlackboxTestStage stage) throws Throwable {
+
+        {
+          final Subscriber<T> sub = createSubscriber();
+          boolean gotNPE = false;
+          try {
+            sub.onSubscribe(null);
+          } catch(final NullPointerException expected) {
+            gotNPE = true;
+          }
+          assertTrue(gotNPE, "onSubscribe(null) did not throw NullPointerException");
+        }
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() {
+      @Override
+      public void run(BlackboxTestStage stage) throws Throwable {
+        final Subscription subscription = new Subscription() {
+          @Override public void request(final long elements) {}
+          @Override public void cancel() {}
+        };
+
+        {
+          final Subscriber<T> sub = createSubscriber();
+          boolean gotNPE = false;
+          sub.onSubscribe(subscription);
+          try {
+            sub.onNext(null);
+          } catch(final NullPointerException expected) {
+            gotNPE = true;
+          }
+          assertTrue(gotNPE, "onNext(null) did not throw NullPointerException");
+        }
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  @Override @Test
+  public void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() {
+      @Override
+      public void run(BlackboxTestStage stage) throws Throwable {
+        final Subscription subscription = new Subscription() {
+          @Override public void request(final long elements) {}
+          @Override public void cancel() {}
+        };
+
+        {
+          final Subscriber<T> sub = createSubscriber();
+          boolean gotNPE = false;
+          sub.onSubscribe(subscription);
+          try {
+            sub.onError(null);
+          } catch(final NullPointerException expected) {
+            gotNPE = true;
+          }
+          assertTrue(gotNPE, "onError(null) did not throw NullPointerException");
+        }
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  ////////////////////// SUBSCRIPTION SPEC RULE VERIFICATION //////////////////
+
+  @Override @Test
+  public void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable {
+    notVerified(); // cannot be meaningfully tested as black box, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  @Override @Test
+  public void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  /////////////////////// ADDITIONAL "COROLLARY" TESTS ////////////////////////
+
+  /////////////////////// TEST INFRASTRUCTURE /////////////////////////////////
+
+  abstract class BlackboxTestStageTestRun {
+    public abstract void run(BlackboxTestStage stage) throws Throwable;
+  }
+
+  public void blackboxSubscriberTest(BlackboxTestStageTestRun body) throws Throwable {
+    BlackboxTestStage stage = new BlackboxTestStage(env, true);
+    body.run(stage);
+  }
+
+  public void blackboxSubscriberWithoutSetupTest(BlackboxTestStageTestRun body) throws Throwable {
+    BlackboxTestStage stage = new BlackboxTestStage(env, false);
+    body.run(stage);
+  }
+
+  public class BlackboxTestStage extends ManualPublisher<T> {
+    public Publisher<T> pub;
+    public ManualSubscriber<T> tees; // gives us access to an infinite stream of T values
+
+    public T lastT = null;
+    private Optional<BlackboxSubscriberProxy<T>> subProxy = Optional.empty();
+
+    public BlackboxTestStage(TestEnvironment env) throws InterruptedException {
+      this(env, true);
+    }
+
+    public BlackboxTestStage(TestEnvironment env, boolean runDefaultInit) throws InterruptedException {
+      super(env);
+      if (runDefaultInit) {
+        pub = this.createHelperPublisher(Long.MAX_VALUE);
+        tees = env.newManualSubscriber(pub);
+        Subscriber<T> sub = createSubscriber();
+        subProxy = Optional.of(createBlackboxSubscriberProxy(env, sub));
+        subscribe(subProxy.get());
+      }
+    }
+
+    public Subscriber<? super T> sub() {
+      return subscriber.value();
+    }
+
+    /**
+     * Proxy for the {@link #sub()} {@code Subscriber}, providing certain assertions on methods being called on the Subscriber.
+     */
+    public BlackboxSubscriberProxy<T> subProxy() {
+      return subProxy.get();
+    }
+
+    public Publisher<T> createHelperPublisher(long elements) {
+      return SubscriberBlackboxVerification.this.createHelperPublisher(elements);
+    }
+
+    public BlackboxSubscriberProxy<T> createBlackboxSubscriberProxy(TestEnvironment env, Subscriber<T> sub) {
+      return new BlackboxSubscriberProxy<T>(env, sub);
+    }
+
+    public T signalNext() throws InterruptedException {
+      T element = nextT();
+      sendNext(element);
+      return element;
+    }
+
+    public T nextT() throws InterruptedException {
+      lastT = tees.requestNextElement();
+      return lastT;
+    }
+
+  }
+
+  public void notVerified() {
+    throw new SkipException("Not verified using this TCK.");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.tck.TestEnvironment.*;
+import org.reactivestreams.tck.flow.support.Optional;
+import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules;
+import org.reactivestreams.tck.flow.support.TestException;
+import org.testng.SkipException;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Provides whitebox style tests for verifying {@link org.reactivestreams.Subscriber}
+ * and {@link org.reactivestreams.Subscription} specification rules.
+ *
+ * @see org.reactivestreams.Subscriber
+ * @see org.reactivestreams.Subscription
+ */
+public abstract class SubscriberWhiteboxVerification<T> extends WithHelperPublisher<T>
+  implements SubscriberWhiteboxVerificationRules {
+
+  private final TestEnvironment env;
+
+  protected SubscriberWhiteboxVerification(TestEnvironment env) {
+    this.env = env;
+  }
+
+  // USER API
+
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic.
+   *
+   * In order to be meaningfully testable your Subscriber must inform the given
+   * `WhiteboxSubscriberProbe` of the respective events having been received.
+   */
+  public abstract Subscriber<T> createSubscriber(WhiteboxSubscriberProbe<T> probe);
+
+  // ENV SETUP
+
+  /**
+   * Executor service used by the default provided asynchronous Publisher.
+   * @see #createHelperPublisher(long)
+   */
+  private ExecutorService publisherExecutor;
+  @BeforeClass public void startPublisherExecutorService() { publisherExecutor = Executors.newFixedThreadPool(4); }
+  @AfterClass public void shutdownPublisherExecutorService() { if (publisherExecutor != null) publisherExecutor.shutdown(); }
+  @Override public ExecutorService publisherExecutorService() { return publisherExecutor; }
+
+  ////////////////////// TEST ENV CLEANUP /////////////////////////////////////
+
+  @BeforeMethod
+  public void setUp() throws Exception {
+    env.clearAsyncErrors();
+  }
+
+  ////////////////////// TEST SETUP VERIFICATION //////////////////////////////
+
+  @Test
+  public void required_exerciseWhiteboxHappyPath() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.puppet().triggerRequest(1);
+        stage.puppet().triggerRequest(1);
+
+        long receivedRequests = stage.expectRequest();
+
+        stage.signalNext();
+        stage.probe.expectNext(stage.lastT);
+
+        stage.puppet().triggerRequest(1);
+        if (receivedRequests == 1) {
+          stage.expectRequest();
+        }
+
+        stage.signalNext();
+        stage.probe.expectNext(stage.lastT);
+
+        stage.puppet().signalCancel();
+        stage.expectCancelling();
+
+        stage.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  ////////////////////// SPEC RULE VERIFICATION ///////////////////////////////
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.1
+  @Override @Test
+  public void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.puppet().triggerRequest(1);
+        stage.expectRequest();
+
+        stage.signalNext();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.2
+  @Override @Test
+  public void untested_spec202_shouldAsynchronouslyDispatch() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.3
+  @Override @Test
+  public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable {
+    subscriberTestWithoutSetup(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws Throwable {
+        final Subscription subs = new Subscription() {
+          @Override
+          public void request(long n) {
+            final Optional<StackTraceElement> onCompleteStackTraceElement = env.findCallerMethodInStackTrace("onComplete");
+            if (onCompleteStackTraceElement.isDefined()) {
+              final StackTraceElement stackElem = onCompleteStackTraceElement.get();
+              env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)",
+                                     stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+            }
+          }
+
+          @Override
+          public void cancel() {
+            final Optional<StackTraceElement> onCompleteStackElement = env.findCallerMethodInStackTrace("onComplete");
+            if (onCompleteStackElement.isDefined()) {
+              final StackTraceElement stackElem = onCompleteStackElement.get();
+              env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)",
+                                     stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+            }
+          }
+        };
+
+        stage.probe = stage.createWhiteboxSubscriberProbe(env);
+        final Subscriber<T> sub = createSubscriber(stage.probe);
+
+        sub.onSubscribe(subs);
+        sub.onComplete();
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.3
+  @Override @Test
+  public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable {
+    subscriberTestWithoutSetup(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws Throwable {
+        final Subscription subs = new Subscription() {
+          @Override
+          public void request(long n) {
+            Throwable thr = new Throwable();
+            for (StackTraceElement stackElem : thr.getStackTrace()) {
+              if (stackElem.getMethodName().equals("onError")) {
+                env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)",
+                                       stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+              }
+            }
+          }
+
+          @Override
+          public void cancel() {
+            Throwable thr = new Throwable();
+            for (StackTraceElement stackElem : thr.getStackTrace()) {
+              if (stackElem.getMethodName().equals("onError")) {
+                env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)",
+                                       stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber()));
+              }
+            }
+          }
+        };
+
+        stage.probe = stage.createWhiteboxSubscriberProbe(env);
+        final Subscriber<T> sub = createSubscriber(stage.probe);
+
+        sub.onSubscribe(subs);
+        sub.onError(new TestException());
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.4
+  @Override @Test
+  public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.5
+  @Override @Test
+  public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws Throwable {
+        // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail
+        final Latch secondSubscriptionCancelled = new Latch(env);
+        final Subscriber<? super T> sub = stage.sub();
+        final Subscription subscription = new Subscription() {
+          @Override
+          public void request(long elements) {
+            // ignore...
+          }
+
+          @Override
+          public void cancel() {
+            secondSubscriptionCancelled.close();
+          }
+
+          @Override
+          public String toString() {
+            return "SecondSubscription(should get cancelled)";
+          }
+        };
+        sub.onSubscribe(subscription);
+
+        secondSubscriptionCancelled.expectClose("Expected 2nd Subscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called");
+        env.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.6
+  @Override @Test
+  public void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.7
+  @Override @Test
+  public void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+    // the same thread part of the clause can be verified but that is not very useful, or is it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.8
+  @Override @Test
+  public void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.puppet().triggerRequest(1);
+        stage.puppet().signalCancel();
+        stage.expectRequest();
+        stage.signalNext();
+
+        stage.puppet().triggerRequest(1);
+        stage.puppet().triggerRequest(1);
+
+        stage.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.9
+  @Override @Test
+  public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.puppet().triggerRequest(1);
+        stage.sendCompletion();
+        stage.probe.expectCompletion();
+
+        stage.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.9
+  @Override @Test
+  public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.sendCompletion();
+        stage.probe.expectCompletion();
+
+        stage.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10
+  @Override @Test
+  public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.puppet().triggerRequest(1);
+        stage.puppet().triggerRequest(1);
+
+        Exception ex = new TestException();
+        stage.sendError(ex);
+        stage.probe.expectError(ex);
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10
+  @Override @Test
+  public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        Exception ex = new TestException();
+        stage.sendError(ex);
+        stage.probe.expectError(ex);
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.11
+  @Override @Test
+  public void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.12
+  @Override @Test
+  public void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13
+  @Override @Test
+  public void untested_spec213_failingOnSignalInvocation() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13
+  @Override @Test
+  public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws Throwable {
+
+        final Subscriber<? super T> sub = stage.sub();
+        boolean gotNPE = false;
+        try {
+          sub.onSubscribe(null);
+        } catch (final NullPointerException expected) {
+          gotNPE = true;
+        }
+
+        assertTrue(gotNPE, "onSubscribe(null) did not throw NullPointerException");
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13
+  @Override @Test
+  public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws Throwable {
+
+        final Subscriber<? super T> sub = stage.sub();
+        boolean gotNPE = false;
+        try {
+          sub.onNext(null);
+        } catch (final NullPointerException expected) {
+          gotNPE = true;
+        }
+
+        assertTrue(gotNPE, "onNext(null) did not throw NullPointerException");
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13
+  @Override @Test
+  public void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws Throwable {
+
+          final Subscriber<? super T> sub = stage.sub();
+          boolean gotNPE = false;
+          try {
+            sub.onError(null);
+          } catch (final NullPointerException expected) {
+            gotNPE = true;
+          } finally {
+            assertTrue(gotNPE, "onError(null) did not throw NullPointerException");
+          }
+
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    });
+  }
+
+
+  ////////////////////// SUBSCRIPTION SPEC RULE VERIFICATION //////////////////
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.1
+  @Override @Test
+  public void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.8
+  @Override @Test
+  public void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable {
+    subscriberTest(new TestStageTestRun() {
+      @Override
+      public void run(WhiteboxTestStage stage) throws InterruptedException {
+        stage.puppet().triggerRequest(2);
+        long requestedElements = stage.expectRequest();
+        stage.probe.expectNext(stage.signalNext());
+        // Some subscribers may only request one element at a time.
+        if (requestedElements < 2) {
+          stage.expectRequest();
+        }
+        stage.probe.expectNext(stage.signalNext());
+
+        stage.probe.expectNone();
+        stage.puppet().triggerRequest(3);
+
+        stage.verifyNoAsyncErrors();
+      }
+    });
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.10
+  @Override @Test
+  public void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.11
+  @Override @Test
+  public void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.14
+  @Override @Test
+  public void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.15
+  @Override @Test
+  public void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.16
+  @Override @Test
+  public void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception {
+    notVerified(); // cannot be meaningfully tested, or can it?
+  }
+
+  /////////////////////// ADDITIONAL "COROLLARY" TESTS ////////////////////////
+
+  /////////////////////// TEST INFRASTRUCTURE /////////////////////////////////
+
+  abstract class TestStageTestRun {
+    public abstract void run(WhiteboxTestStage stage) throws Throwable;
+  }
+
+  /**
+   * Prepares subscriber and publisher pair (by subscribing the first to the latter),
+   * and then hands over the tests {@link WhiteboxTestStage} over to the test.
+   *
+   * The test stage is, like in a puppet show, used to orchestrate what each participant should do.
+   * Since this is a whitebox test, this allows the stage to completely control when and how to signal / expect signals.
+   */
+  public void subscriberTest(TestStageTestRun body) throws Throwable {
+    WhiteboxTestStage stage = new WhiteboxTestStage(env, true);
+    body.run(stage);
+  }
+
+  /**
+   * Provides a {@link WhiteboxTestStage} without performing any additional setup,
+   * like the {@link #subscriberTest(SubscriberWhiteboxVerification.TestStageTestRun)} would.
+   *
+   * Use this method to write tests in which you need full control over when and how the initial {@code subscribe} is signalled.
+   */
+  public void subscriberTestWithoutSetup(TestStageTestRun body) throws Throwable {
+    WhiteboxTestStage stage = new WhiteboxTestStage(env, false);
+    body.run(stage);
+  }
+
+  /**
+   * Test for feature that MAY be implemented. This test will be marked as SKIPPED if it fails.
+   */
+  public void optionalSubscriberTestWithoutSetup(TestStageTestRun body) throws Throwable {
+    try {
+      subscriberTestWithoutSetup(body);
+    } catch (Exception ex) {
+      notVerified("Skipped because tested publisher does NOT implement this OPTIONAL requirement.");
+    }
+  }
+
+  public class WhiteboxTestStage extends ManualPublisher<T> {
+    public Publisher<T> pub;
+    public ManualSubscriber<T> tees; // gives us access to a stream T values
+    public WhiteboxSubscriberProbe<T> probe;
+
+    public T lastT = null;
+
+    public WhiteboxTestStage(TestEnvironment env) throws InterruptedException {
+      this(env, true);
+    }
+
+    public WhiteboxTestStage(TestEnvironment env, boolean runDefaultInit) throws InterruptedException {
+      super(env);
+      if (runDefaultInit) {
+        pub = this.createHelperPublisher(Long.MAX_VALUE);
+        tees = env.newManualSubscriber(pub);
+        probe = new WhiteboxSubscriberProbe<T>(env, subscriber);
+        subscribe(createSubscriber(probe));
+        probe.puppet.expectCompletion(env.defaultTimeoutMillis(), String.format("Subscriber %s did not `registerOnSubscribe`", sub()));
+        env.verifyNoAsyncErrorsNoDelay();
+      }
+    }
+
+    public Subscriber<? super T> sub() {
+      return subscriber.value();
+    }
+
+    public SubscriberPuppet puppet() {
+      return probe.puppet();
+    }
+
+    public WhiteboxSubscriberProbe<T> probe() {
+      return probe;
+    }
+
+    public Publisher<T> createHelperPublisher(long elements) {
+      return SubscriberWhiteboxVerification.this.createHelperPublisher(elements);
+    }
+
+    public WhiteboxSubscriberProbe<T> createWhiteboxSubscriberProbe(TestEnvironment env) {
+      return new WhiteboxSubscriberProbe<T>(env, subscriber);
+    }
+
+    public T signalNext() throws InterruptedException {
+      return signalNext(nextT());
+    }
+
+    private T signalNext(T element) throws InterruptedException {
+      sendNext(element);
+      return element;
+    }
+
+    public T nextT() throws InterruptedException {
+      lastT = tees.requestNextElement();
+      return lastT;
+    }
+
+    public void verifyNoAsyncErrors() {
+      env.verifyNoAsyncErrors();
+    }
+  }
+
+  /**
+   * This class is intented to be used as {@code Subscriber} decorator and should be used in {@code pub.subscriber(...)} calls,
+   * in order to allow intercepting calls on the underlying {@code Subscriber}.
+   * This delegation allows the proxy to implement {@link BlackboxProbe} assertions.
+   */
+  public static class BlackboxSubscriberProxy<T> extends BlackboxProbe<T> implements Subscriber<T> {
+
+    public BlackboxSubscriberProxy(TestEnvironment env, Subscriber<T> subscriber) {
+      super(env, Promise.<Subscriber<? super T>>completed(env, subscriber));
+    }
+
+    @Override
+    public void onSubscribe(Subscription s) {
+      sub().onSubscribe(s);
+    }
+
+    @Override
+    public void onNext(T t) {
+      registerOnNext(t);
+      sub().onNext(t);
+    }
+
+    @Override
+    public void onError(Throwable cause) {
+      registerOnError(cause);
+      sub().onError(cause);
+    }
+
+    @Override
+    public void onComplete() {
+      registerOnComplete();
+      sub().onComplete();
+    }
+  }
+
+  public static class BlackboxProbe<T> implements SubscriberProbe<T> {
+    protected final TestEnvironment env;
+    protected final Promise<Subscriber<? super T>> subscriber;
+
+    protected final Receptacle<T> elements;
+    protected final Promise<Throwable> error;
+
+    public BlackboxProbe(TestEnvironment env, Promise<Subscriber<? super T>> subscriber) {
+      this.env = env;
+      this.subscriber = subscriber;
+      elements = new Receptacle<T>(env);
+      error = new Promise<Throwable>(env);
+    }
+
+    @Override
+    public void registerOnNext(T element) {
+      elements.add(element);
+    }
+
+    @Override
+    public void registerOnComplete() {
+      try {
+        elements.complete();
+      } catch (IllegalStateException ex) {
+        // "Queue full", onComplete was already called
+        env.flop("subscriber::onComplete was called a second time, which is illegal according to Rule 1.7");
+      }
+    }
+
+    @Override
+    public void registerOnError(Throwable cause) {
+      try {
+        error.complete(cause);
+      } catch (IllegalStateException ex) {
+        // "Queue full", onError was already called
+        env.flop("subscriber::onError was called a second time, which is illegal according to Rule 1.7");
+      }
+    }
+
+    public T expectNext() throws InterruptedException {
+      return elements.next(env.defaultTimeoutMillis(), String.format("Subscriber %s did not call `registerOnNext(_)`", sub()));
+    }
+
+    public void expectNext(T expected) throws InterruptedException {
+      expectNext(expected, env.defaultTimeoutMillis());
+    }
+
+    public void expectNext(T expected, long timeoutMillis) throws InterruptedException {
+      T received = elements.next(timeoutMillis, String.format("Subscriber %s did not call `registerOnNext(%s)`", sub(), expected));
+      if (!received.equals(expected)) {
+        env.flop(String.format("Subscriber %s called `registerOnNext(%s)` rather than `registerOnNext(%s)`", sub(), received, expected));
+      }
+    }
+
+    public Subscriber<? super T> sub() {
+      return subscriber.value();
+    }
+
+    public void expectCompletion() throws InterruptedException {
+      expectCompletion(env.defaultTimeoutMillis());
+    }
+
+    public void expectCompletion(long timeoutMillis) throws InterruptedException {
+      expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnComplete()`", sub()));
+    }
+
+    public void expectCompletion(long timeoutMillis, String msg) throws InterruptedException {
+      elements.expectCompletion(timeoutMillis, msg);
+    }
+
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public <E extends Throwable> void expectErrorWithMessage(Class<E> expected, String requiredMessagePart) throws InterruptedException {
+      final E err = expectError(expected);
+      String message = err.getMessage();
+      assertTrue(message.contains(requiredMessagePart),
+        String.format("Got expected exception %s but missing message [%s], was: %s", err.getClass(), requiredMessagePart, expected));
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected) throws InterruptedException {
+      return expectError(expected, env.defaultTimeoutMillis());
+    }
+
+    @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"})
+    public <E extends Throwable> E expectError(Class<E> expected, long timeoutMillis) throws InterruptedException {
+      error.expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected));
+      if (error.value() == null) {
+        return env.flopAndFail(String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected));
+      } else if (expected.isInstance(error.value())) {
+        return (E) error.value();
+      } else {
+        return env.flopAndFail(String.format("Subscriber %s called `registerOnError(%s)` rather than `registerOnError(%s)`", sub(), error.value(), expected));
+      }
+    }
+
+    public void expectError(Throwable expected) throws InterruptedException {
+      expectError(expected, env.defaultTimeoutMillis());
+    }
+
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void expectError(Throwable expected, long timeoutMillis) throws InterruptedException {
+      error.expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected));
+      if (error.value() != expected) {
+        env.flop(String.format("Subscriber %s called `registerOnError(%s)` rather than `registerOnError(%s)`", sub(), error.value(), expected));
+      }
+    }
+
+    public void expectNone() throws InterruptedException {
+      expectNone(env.defaultNoSignalsTimeoutMillis());
+    }
+
+    public void expectNone(long withinMillis) throws InterruptedException {
+      elements.expectNone(withinMillis, "Expected nothing");
+    }
+
+  }
+
+  public static class WhiteboxSubscriberProbe<T> extends BlackboxProbe<T> implements SubscriberPuppeteer {
+    protected Promise<SubscriberPuppet> puppet;
+
+    public WhiteboxSubscriberProbe(TestEnvironment env, Promise<Subscriber<? super T>> subscriber) {
+      super(env, subscriber);
+      puppet = new Promise<SubscriberPuppet>(env);
+    }
+
+    private SubscriberPuppet puppet() {
+      return puppet.value();
+    }
+
+    @Override
+    public void registerOnSubscribe(SubscriberPuppet p) {
+      if (!puppet.isCompleted()) {
+        puppet.complete(p);
+      }
+    }
+
+  }
+
+  public interface SubscriberPuppeteer {
+
+    /**
+     * Must be called by the test subscriber when it has successfully registered a subscription
+     * inside the `onSubscribe` method.
+     */
+    void registerOnSubscribe(SubscriberPuppet puppet);
+  }
+
+  public interface SubscriberProbe<T> {
+
+    /**
+     * Must be called by the test subscriber when it has received an`onNext` event.
+     */
+    void registerOnNext(T element);
+
+    /**
+     * Must be called by the test subscriber when it has received an `onComplete` event.
+     */
+    void registerOnComplete();
+
+    /**
+     * Must be called by the test subscriber when it has received an `onError` event.
+     */
+    void registerOnError(Throwable cause);
+
+  }
+
+  /**
+   * Implement this puppet in your Whitebox style tests.
+   * The test suite will invoke the specific trigger/signal methods requesting you to execute the specific action.
+   * Since this is a whitebox style test, you're allowed and expected to use knowladge about your implementation to
+   * make implement these calls.
+   */
+  public interface SubscriberPuppet {
+
+    /**
+     * Ensure that at least {@code elements} are eventually requested by your {@link Subscriber}, if it hasn't already
+     * requested that many elements.
+     * <p>
+     * This does not necessarily have to correlate 1:1 with a {@code Subscription.request(elements)} call, but the sum
+     * of the elements requested by your {@code Subscriber} must eventually be at least the the sum of the elements
+     * triggered to be requested by all the invocations of this method.
+     * <p>
+     * Additionally, subscribers are permitted to delay requesting elements until previous requests for elements have
+     * been fulfilled. For example, a subscriber that only requests one element at a time may fulfill the request made
+     * by this method by requesting one element {@code elements} times, waiting for each element to arrive before the
+     * next request is made.
+     * <p>
+     * Before sending any element to the subscriber, the TCK must wait for the subscriber to request that element, and
+     * must be prepared for the subscriber to only request one element at a time, it is not enough for the TCK to
+     * simply invoke this method before sending elements.
+     */
+    void triggerRequest(long elements);
+
+    /**
+     * Trigger {@code cancel()} on your {@link Subscriber}
+     */
+    void signalCancel();
+  }
+
+  public void notVerified() {
+    throw new SkipException("Not verified using this TCK.");
+  }
+
+  public void notVerified(String msg) {
+    throw new SkipException(msg);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,1168 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.tck.flow.support.Optional;
+import org.reactivestreams.tck.flow.support.SubscriberBufferOverflowException;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+public class TestEnvironment {
+  public static final int TEST_BUFFER_SIZE = 16;
+
+  private static final String DEFAULT_TIMEOUT_MILLIS_ENV = "DEFAULT_TIMEOUT_MILLIS";
+  private static final long DEFAULT_TIMEOUT_MILLIS = 100;
+
+  private static final String DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV = "DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS";
+  private static final String DEFAULT_POLL_TIMEOUT_MILLIS_ENV = "DEFAULT_POLL_TIMEOUT_MILLIS_ENV";
+
+  private final long defaultTimeoutMillis;
+  private final long defaultPollTimeoutMillis;
+  private final long defaultNoSignalsTimeoutMillis;
+  private final boolean printlnDebug;
+
+  private CopyOnWriteArrayList<Throwable> asyncErrors = new CopyOnWriteArrayList<Throwable>();
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   * @param defaultTimeoutMillis default timeout to be used in all expect* methods
+   * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore
+   * @param defaultPollTimeoutMillis default amount of time to poll for events if {@code defaultTimeoutMillis} isn't
+    *                                preempted by an asynchronous event.
+   * @param printlnDebug         if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output,
+   */
+  public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, long defaultPollTimeoutMillis,
+                         boolean printlnDebug) {
+    this.defaultTimeoutMillis = defaultTimeoutMillis;
+    this.defaultPollTimeoutMillis = defaultPollTimeoutMillis;
+    this.defaultNoSignalsTimeoutMillis = defaultNoSignalsTimeoutMillis;
+    this.printlnDebug = printlnDebug;
+  }
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   * @param defaultTimeoutMillis default timeout to be used in all expect* methods
+   * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore
+   * @param printlnDebug         if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output,
+   */
+  public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, boolean printlnDebug) {
+    this(defaultTimeoutMillis, defaultNoSignalsTimeoutMillis, defaultTimeoutMillis, printlnDebug);
+  }
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   *
+   * @param defaultTimeoutMillis default timeout to be used in all expect* methods
+   * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore
+   * @param defaultPollTimeoutMillis default amount of time to poll for events if {@code defaultTimeoutMillis} isn't
+   *                                 preempted by an asynchronous event.
+   */
+  public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, long defaultPollTimeoutMillis) {
+      this(defaultTimeoutMillis, defaultNoSignalsTimeoutMillis, defaultPollTimeoutMillis, false);
+  }
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   *
+   * @param defaultTimeoutMillis default timeout to be used in all expect* methods
+   * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore
+   */
+  public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis) {
+    this(defaultTimeoutMillis, defaultTimeoutMillis, defaultNoSignalsTimeoutMillis);
+  }
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   *
+   * @param defaultTimeoutMillis default timeout to be used in all expect* methods
+   */
+  public TestEnvironment(long defaultTimeoutMillis) {
+    this(defaultTimeoutMillis, defaultTimeoutMillis, defaultTimeoutMillis);
+  }
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   *
+   * The default timeout for all expect* methods will be obtained by either the env variable {@code DEFAULT_TIMEOUT_MILLIS}
+   * or the default value ({@link TestEnvironment#DEFAULT_TIMEOUT_MILLIS}) will be used.
+   *
+   * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output,
+   *                     often helpful to pinpoint simple race conditions etc.
+   */
+  public TestEnvironment(boolean printlnDebug) {
+    this(envDefaultTimeoutMillis(), envDefaultNoSignalsTimeoutMillis(), envDefaultPollTimeoutMillis(), printlnDebug);
+  }
+
+  /**
+   * Tests must specify the timeout for expected outcome of asynchronous
+   * interactions. Longer timeout does not invalidate the correctness of
+   * the implementation, but can in some cases result in longer time to
+   * run the tests.
+   *
+   * The default timeout for all expect* methods will be obtained by either the env variable {@code DEFAULT_TIMEOUT_MILLIS}
+   * or the default value ({@link TestEnvironment#DEFAULT_TIMEOUT_MILLIS}) will be used.
+   */
+  public TestEnvironment() {
+    this(envDefaultTimeoutMillis(), envDefaultNoSignalsTimeoutMillis());
+  }
+
+  /** This timeout is used when waiting for a signal to arrive. */
+  public long defaultTimeoutMillis() {
+    return defaultTimeoutMillis;
+  }
+
+  /**
+   * This timeout is used when asserting that no further signals are emitted.
+   * Note that this timeout default
+   */
+  public long defaultNoSignalsTimeoutMillis() {
+    return defaultNoSignalsTimeoutMillis;
+  }
+
+  /**
+   * The default amount of time to poll for events if {@code defaultTimeoutMillis} isn't preempted by an asynchronous
+   * event.
+   */
+  public long defaultPollTimeoutMillis() {
+    return defaultPollTimeoutMillis;
+  }
+
+  /**
+   * Tries to parse the env variable {@code DEFAULT_TIMEOUT_MILLIS} as long and returns the value if present OR its default value.
+   *
+   * @throws java.lang.IllegalArgumentException when unable to parse the env variable
+   */
+  public static long envDefaultTimeoutMillis() {
+    final String envMillis = System.getenv(DEFAULT_TIMEOUT_MILLIS_ENV);
+    if (envMillis == null) return DEFAULT_TIMEOUT_MILLIS;
+    else try {
+      return Long.parseLong(envMillis);
+    } catch (NumberFormatException ex) {
+      throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_TIMEOUT_MILLIS_ENV, envMillis), ex);
+    }
+  }
+
+  /**
+   * Tries to parse the env variable {@code DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS} as long and returns the value if present OR its default value.
+   *
+   * @throws java.lang.IllegalArgumentException when unable to parse the env variable
+   */
+  public static long envDefaultNoSignalsTimeoutMillis() {
+    final String envMillis = System.getenv(DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV);
+    if (envMillis == null) return envDefaultTimeoutMillis();
+    else try {
+      return Long.parseLong(envMillis);
+    } catch (NumberFormatException ex) {
+      throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV, envMillis), ex);
+    }
+  }
+
+  /**
+   * Tries to parse the env variable {@code DEFAULT_POLL_TIMEOUT_MILLIS_ENV} as long and returns the value if present OR its default value.
+   *
+   * @throws java.lang.IllegalArgumentException when unable to parse the env variable
+   */
+  public static long envDefaultPollTimeoutMillis() {
+    final String envMillis = System.getenv(DEFAULT_POLL_TIMEOUT_MILLIS_ENV);
+    if (envMillis == null) return envDefaultTimeoutMillis();
+    else try {
+      return Long.parseLong(envMillis);
+    } catch (NumberFormatException ex) {
+      throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_POLL_TIMEOUT_MILLIS_ENV, envMillis), ex);
+    }
+  }
+
+  /**
+   * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously.
+   * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required.
+   *
+   * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution.
+   * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly
+   * from the environment using {@code env.dropAsyncError()}.
+   *
+   * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()}
+   */
+  public void flop(String msg) {
+    try {
+      fail(msg);
+    } catch (Throwable t) {
+      asyncErrors.add(t);
+    }
+  }
+
+  /**
+   * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously.
+   * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required.
+   *
+   * This overload keeps the passed in throwable as the asyncError, instead of creating an AssertionError for this.
+   *
+   * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution.
+   * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly
+   * from the environment using {@code env.dropAsyncError()}.
+   *
+   * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()}
+   */
+  public void flop(Throwable thr, String msg) {
+    try {
+      fail(msg, thr);
+    } catch (Throwable t) {
+      asyncErrors.add(thr);
+    }
+  }
+
+  /**
+   * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously.
+   * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required.
+   *
+   * This overload keeps the passed in throwable as the asyncError, instead of creating an AssertionError for this.
+   *
+   * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution.
+   * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly
+   * from the environment using {@code env.dropAsyncError()}.
+   *
+   * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()}
+   */
+  public void flop(Throwable thr) {
+    try {
+      fail(thr.getMessage(), thr);
+    } catch (Throwable t) {
+      asyncErrors.add(thr);
+    }
+  }
+
+  /**
+   * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously.
+   *
+   * This method DOES fail the test right away (it tries to, by throwing an AssertionException),
+   * in such it is different from {@link org.reactivestreams.tck.TestEnvironment#flop} which only records the error.
+   *
+   * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution.
+   * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly
+   * from the environment using {@code env.dropAsyncError()}.
+   *
+   * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()}
+   */
+  public <T> T flopAndFail(String msg) {
+    try {
+      fail(msg);
+    } catch (Throwable t) {
+      asyncErrors.add(t);
+      fail(msg, t);
+    }
+    return null; // unreachable, the previous block will always exit by throwing
+  }
+
+
+
+  public <T> void subscribe(Publisher<T> pub, TestSubscriber<T> sub) throws InterruptedException {
+    subscribe(pub, sub, defaultTimeoutMillis);
+  }
+
+  public <T> void subscribe(Publisher<T> pub, TestSubscriber<T> sub, long timeoutMillis) throws InterruptedException {
+    pub.subscribe(sub);
+    sub.subscription.expectCompletion(timeoutMillis, String.format("Could not subscribe %s to Publisher %s", sub, pub));
+    verifyNoAsyncErrorsNoDelay();
+  }
+
+  public <T> ManualSubscriber<T> newBlackholeSubscriber(Publisher<T> pub) throws InterruptedException {
+    ManualSubscriberWithSubscriptionSupport<T> sub = new BlackholeSubscriberWithSubscriptionSupport<T>(this);
+    subscribe(pub, sub, defaultTimeoutMillis());
+    return sub;
+  }
+
+  public <T> ManualSubscriber<T> newManualSubscriber(Publisher<T> pub) throws InterruptedException {
+    return newManualSubscriber(pub, defaultTimeoutMillis());
+  }
+
+  public <T> ManualSubscriber<T> newManualSubscriber(Publisher<T> pub, long timeoutMillis) throws InterruptedException {
+    ManualSubscriberWithSubscriptionSupport<T> sub = new ManualSubscriberWithSubscriptionSupport<T>(this);
+    subscribe(pub, sub, timeoutMillis);
+    return sub;
+  }
+
+  public void clearAsyncErrors() {
+    asyncErrors.clear();
+  }
+
+  public Throwable dropAsyncError() {
+    try {
+      return asyncErrors.remove(0);
+    } catch (IndexOutOfBoundsException ex) {
+      return null;
+    }
+  }
+
+  /**
+   * Waits for {@link TestEnvironment#defaultNoSignalsTimeoutMillis()} and then verifies that no asynchronous errors
+   * were signalled pior to, or during that time (by calling {@code flop()}).
+   */
+  public void verifyNoAsyncErrors() {
+    verifyNoAsyncErrors(defaultNoSignalsTimeoutMillis());
+  }
+
+  /**
+   * This version of {@code verifyNoAsyncErrors} should be used when errors still could be signalled
+   * asynchronously during {@link TestEnvironment#defaultTimeoutMillis()} time.
+   * <p></p>
+   * It will immediatly check if any async errors were signaled (using {@link TestEnvironment#flop(String)},
+   * and if no errors encountered wait for another default timeout as the errors may yet be signalled.
+   * The initial check is performed in order to fail-fast in case of an already failed test.
+   */
+  public void verifyNoAsyncErrors(long delay) {
+    try {
+      verifyNoAsyncErrorsNoDelay();
+
+      Thread.sleep(delay);
+      verifyNoAsyncErrorsNoDelay();
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Verifies that no asynchronous errors were signalled pior to calling this method (by calling {@code flop()}).
+   * This version of verifyNoAsyncError <b>does not wait before checking for asynchronous errors</b>, and is to be used
+   * for example in tight loops etc.
+   */
+  public void verifyNoAsyncErrorsNoDelay() {
+    for (Throwable e : asyncErrors) {
+      if (e instanceof AssertionError) {
+        throw (AssertionError) e;
+      } else {
+        fail(String.format("Async error during test execution: %s", e.getMessage()), e);
+      }
+    }
+  }
+
+  /** If {@code TestEnvironment#printlnDebug} is true, print debug message to std out. */
+  public void debug(String msg) {
+    if (debugEnabled()) {
+      System.out.printf("[TCK-DEBUG] %s%n", msg);
+    }
+  }
+
+  public final boolean debugEnabled() {
+    return printlnDebug;
+  }
+
+  /**
+   * Looks for given {@code method} method in stack trace.
+   * Can be used to answer questions like "was this method called from onComplete?".
+   *
+   * @return the caller's StackTraceElement at which he the looked for method was found in the call stack, EMPTY otherwise
+   */
+  public Optional<StackTraceElement> findCallerMethodInStackTrace(String method) {
+    final Throwable thr = new Throwable(); // gets the stacktrace
+
+    for (StackTraceElement stackElement : thr.getStackTrace()) {
+      if (stackElement.getMethodName().equals(method)) {
+        return Optional.of(stackElement);
+      }
+    }
+    return Optional.empty();
+  }
+
+  // ---- classes ----
+
+  /**
+   * {@link Subscriber} implementation which can be steered by test code and asserted on.
+   */
+  public static class ManualSubscriber<T> extends TestSubscriber<T> {
+    Receptacle<T> received;
+
+    public ManualSubscriber(TestEnvironment env) {
+      super(env);
+      received = new Receptacle<T>(this.env);
+    }
+
+    @Override
+    public void onNext(T element) {
+      try {
+        received.add(element);
+      } catch (IllegalStateException ex) {
+          // error message refinement
+          throw new SubscriberBufferOverflowException(
+            String.format("Received more than bufferSize (%d) onNext signals. " +
+                            "The Publisher probably emited more signals than expected!",
+                          received.QUEUE_SIZE), ex);
+      }
+    }
+
+    @Override
+    public void onComplete() {
+      received.complete();
+    }
+
+    public void request(long elements) {
+      subscription.value().request(elements);
+    }
+
+    public T requestNextElement() throws InterruptedException {
+      return requestNextElement(env.defaultTimeoutMillis());
+    }
+
+    public T requestNextElement(long timeoutMillis) throws InterruptedException {
+      return requestNextElement(timeoutMillis, "Did not receive expected element");
+    }
+
+    public T requestNextElement(String errorMsg) throws InterruptedException {
+      return requestNextElement(env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public T requestNextElement(long timeoutMillis, String errorMsg) throws InterruptedException {
+      request(1);
+      return nextElement(timeoutMillis, errorMsg);
+    }
+
+    public Optional<T> requestNextElementOrEndOfStream() throws InterruptedException {
+      return requestNextElementOrEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion");
+    }
+
+    public Optional<T> requestNextElementOrEndOfStream(String errorMsg) throws InterruptedException {
+      return requestNextElementOrEndOfStream(env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public Optional<T> requestNextElementOrEndOfStream(long timeoutMillis) throws InterruptedException {
+      return requestNextElementOrEndOfStream(timeoutMillis, "Did not receive expected stream completion");
+    }
+
+    public Optional<T> requestNextElementOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException {
+      request(1);
+      return nextElementOrEndOfStream(timeoutMillis, errorMsg);
+    }
+
+    public void requestEndOfStream() throws InterruptedException {
+      requestEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion");
+    }
+
+    public void requestEndOfStream(long timeoutMillis) throws InterruptedException {
+      requestEndOfStream(timeoutMillis, "Did not receive expected stream completion");
+    }
+
+    public void requestEndOfStream(String errorMsg) throws InterruptedException {
+      requestEndOfStream(env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public void requestEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException {
+      request(1);
+      expectCompletion(timeoutMillis, errorMsg);
+    }
+
+    public List<T> requestNextElements(long elements) throws InterruptedException {
+      request(elements);
+      return nextElements(elements, env.defaultTimeoutMillis());
+    }
+
+    public List<T> requestNextElements(long elements, long timeoutMillis) throws InterruptedException {
+      request(elements);
+      return nextElements(elements, timeoutMillis, String.format("Did not receive %d expected elements", elements));
+    }
+
+    public List<T> requestNextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException {
+      request(elements);
+      return nextElements(elements, timeoutMillis, errorMsg);
+    }
+
+    public T nextElement() throws InterruptedException {
+      return nextElement(env.defaultTimeoutMillis());
+    }
+
+    public T nextElement(long timeoutMillis) throws InterruptedException {
+      return nextElement(timeoutMillis, "Did not receive expected element");
+    }
+
+    public T nextElement(String errorMsg) throws InterruptedException {
+      return nextElement(env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public T nextElement(long timeoutMillis, String errorMsg) throws InterruptedException {
+      return received.next(timeoutMillis, errorMsg);
+    }
+
+    public Optional<T> nextElementOrEndOfStream() throws InterruptedException {
+      return nextElementOrEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion");
+    }
+
+    public Optional<T> nextElementOrEndOfStream(long timeoutMillis) throws InterruptedException {
+      return nextElementOrEndOfStream(timeoutMillis, "Did not receive expected stream completion");
+    }
+
+    public Optional<T> nextElementOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException {
+      return received.nextOrEndOfStream(timeoutMillis, errorMsg);
+    }
+
+    public List<T> nextElements(long elements) throws InterruptedException {
+      return nextElements(elements, env.defaultTimeoutMillis(), "Did not receive expected element or completion");
+    }
+
+    public List<T> nextElements(long elements, String errorMsg) throws InterruptedException {
+      return nextElements(elements, env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public List<T> nextElements(long elements, long timeoutMillis) throws InterruptedException {
+      return nextElements(elements, timeoutMillis, "Did not receive expected element or completion");
+    }
+
+    public List<T> nextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException {
+      return received.nextN(elements, timeoutMillis, errorMsg);
+    }
+
+    public void expectNext(T expected) throws InterruptedException {
+      expectNext(expected, env.defaultTimeoutMillis());
+    }
+
+    public void expectNext(T expected, long timeoutMillis) throws InterruptedException {
+      T received = nextElement(timeoutMillis, "Did not receive expected element on downstream");
+      if (!received.equals(expected)) {
+        env.flop(String.format("Expected element %s on downstream but received %s", expected, received));
+      }
+    }
+
+    public void expectCompletion() throws InterruptedException {
+      expectCompletion(env.defaultTimeoutMillis(), "Did not receive expected stream completion");
+    }
+
+    public void expectCompletion(long timeoutMillis) throws InterruptedException {
+      expectCompletion(timeoutMillis, "Did not receive expected stream completion");
+    }
+
+    public void expectCompletion(String errorMsg) throws InterruptedException {
+      expectCompletion(env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException {
+      received.expectCompletion(timeoutMillis, errorMsg);
+    }
+
+    public <E extends Throwable> void expectErrorWithMessage(Class<E> expected, String requiredMessagePart) throws Exception {
+      expectErrorWithMessage(expected, Collections.singletonList(requiredMessagePart), env.defaultTimeoutMillis(), env.defaultPollTimeoutMillis());
+    }
+    public <E extends Throwable> void expectErrorWithMessage(Class<E> expected, List<String> requiredMessagePartAlternatives) throws Exception {
+      expectErrorWithMessage(expected, requiredMessagePartAlternatives, env.defaultTimeoutMillis(), env.defaultPollTimeoutMillis());
+    }
+
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public <E extends Throwable> void expectErrorWithMessage(Class<E> expected, String requiredMessagePart, long timeoutMillis) throws Exception {
+      expectErrorWithMessage(expected, Collections.singletonList(requiredMessagePart), timeoutMillis);
+    }
+
+    public <E extends Throwable> void expectErrorWithMessage(Class<E> expected, List<String> requiredMessagePartAlternatives, long timeoutMillis) throws Exception {
+      expectErrorWithMessage(expected, requiredMessagePartAlternatives, timeoutMillis, timeoutMillis);
+    }
+
+    public <E extends Throwable> void expectErrorWithMessage(Class<E> expected, List<String> requiredMessagePartAlternatives,
+                                                             long totalTimeoutMillis, long pollTimeoutMillis) throws Exception {
+      final E err = expectError(expected, totalTimeoutMillis, pollTimeoutMillis);
+      final String message = err.getMessage();
+
+      boolean contains = false;
+      for (String requiredMessagePart : requiredMessagePartAlternatives)
+        if (message.contains(requiredMessagePart)) contains = true; // not short-circuting loop, it is expected to
+      assertTrue(contains,
+              String.format("Got expected exception [%s] but missing message part [%s], was: %s",
+                      err.getClass(), "anyOf: " + requiredMessagePartAlternatives, err.getMessage()));
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected) throws Exception {
+      return expectError(expected, env.defaultTimeoutMillis());
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected, long timeoutMillis) throws Exception {
+      return expectError(expected, timeoutMillis, env.defaultPollTimeoutMillis());
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected, String errorMsg) throws Exception {
+      return expectError(expected, env.defaultTimeoutMillis(), errorMsg);
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected, long timeoutMillis, String errorMsg) throws Exception {
+      return expectError(expected, timeoutMillis, env.defaultPollTimeoutMillis(), errorMsg);
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected, long totalTimeoutMillis, long pollTimeoutMillis) throws Exception {
+      return expectError(expected, totalTimeoutMillis, pollTimeoutMillis, String.format("Expected onError(%s)", expected.getName()));
+    }
+
+    public <E extends Throwable> E expectError(Class<E> expected, long totalTimeoutMillis, long pollTimeoutMillis,
+                                               String errorMsg) throws Exception {
+      return received.expectError(expected, totalTimeoutMillis, pollTimeoutMillis, errorMsg);
+    }
+
+    public void expectNone() throws InterruptedException {
+      expectNone(env.defaultNoSignalsTimeoutMillis());
+    }
+
+    public void expectNone(String errMsgPrefix) throws InterruptedException {
+      expectNone(env.defaultNoSignalsTimeoutMillis(), errMsgPrefix);
+    }
+
+    public void expectNone(long withinMillis) throws InterruptedException {
+      expectNone(withinMillis, "Did not expect an element but got element");
+    }
+
+    public void expectNone(long withinMillis, String errMsgPrefix) throws InterruptedException {
+      received.expectNone(withinMillis, errMsgPrefix);
+    }
+
+  }
+
+  public static class ManualSubscriberWithSubscriptionSupport<T> extends ManualSubscriber<T> {
+
+    public ManualSubscriberWithSubscriptionSupport(TestEnvironment env) {
+      super(env);
+    }
+
+    @Override
+    public void onNext(T element) {
+      if (env.debugEnabled()) {
+        env.debug(String.format("%s::onNext(%s)", this, element));
+      }
+      if (subscription.isCompleted()) {
+        super.onNext(element);
+      } else {
+        env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element));
+      }
+    }
+
+    @Override
+    public void onComplete() {
+      if (env.debugEnabled()) {
+        env.debug(this + "::onComplete()");
+      }
+      if (subscription.isCompleted()) {
+        super.onComplete();
+      } else {
+        env.flop("Subscriber::onComplete() called before Subscriber::onSubscribe");
+      }
+    }
+
+    @Override
+    public void onSubscribe(Subscription s) {
+      if (env.debugEnabled()) {
+        env.debug(String.format("%s::onSubscribe(%s)", this, s));
+      }
+      if (!subscription.isCompleted()) {
+        subscription.complete(s);
+      } else {
+        env.flop("Subscriber::onSubscribe called on an already-subscribed Subscriber");
+      }
+    }
+
+    @Override
+    public void onError(Throwable cause) {
+      if (env.debugEnabled()) {
+        env.debug(String.format("%s::onError(%s)", this, cause));
+      }
+      if (subscription.isCompleted()) {
+        super.onError(cause);
+      } else {
+        env.flop(cause, String.format("Subscriber::onError(%s) called before Subscriber::onSubscribe", cause));
+      }
+    }
+  }
+
+  /**
+   * Similar to {@link org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport}
+   * but does not accumulate values signalled via <code>onNext</code>, thus it can not be used to assert
+   * values signalled to this subscriber. Instead it may be used to quickly drain a given publisher.
+   */
+  public static class BlackholeSubscriberWithSubscriptionSupport<T>
+    extends ManualSubscriberWithSubscriptionSupport<T> {
+
+    public BlackholeSubscriberWithSubscriptionSupport(TestEnvironment env) {
+      super(env);
+    }
+
+    @Override
+    public void onNext(T element) {
+      if (env.debugEnabled()) {
+        env.debug(String.format("%s::onNext(%s)", this, element));
+      }
+      if (!subscription.isCompleted()) {
+        env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element));
+      }
+    }
+
+    @Override
+    public T nextElement(long timeoutMillis, String errorMsg) throws InterruptedException {
+      throw new RuntimeException("Can not expect elements from BlackholeSubscriber, use ManualSubscriber instead!");
+    }
+
+    @Override
+    public List<T> nextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException {
+      throw new RuntimeException("Can not expect elements from BlackholeSubscriber, use ManualSubscriber instead!");
+    }
+  }
+
+  public static class TestSubscriber<T> implements Subscriber<T> {
+    final Promise<Subscription> subscription;
+
+    protected final TestEnvironment env;
+
+    public TestSubscriber(TestEnvironment env) {
+      this.env = env;
+      subscription = new Promise<Subscription>(env);
+    }
+
+    @Override
+    public void onError(Throwable cause) {
+      env.flop(cause, String.format("Unexpected Subscriber::onError(%s)", cause));
+    }
+
+    @Override
+    public void onComplete() {
+      env.flop("Unexpected Subscriber::onComplete()");
+    }
+
+    @Override
+    public void onNext(T element) {
+      env.flop(String.format("Unexpected Subscriber::onNext(%s)", element));
+    }
+
+    @Override
+    public void onSubscribe(Subscription subscription) {
+      env.flop(String.format("Unexpected Subscriber::onSubscribe(%s)", subscription));
+    }
+
+    public void cancel() {
+      if (subscription.isCompleted()) {
+        subscription.value().cancel();
+      } else {
+        env.flop("Cannot cancel a subscription before having received it");
+      }
+    }
+  }
+
+  public static class ManualPublisher<T> implements Publisher<T> {
+    protected final TestEnvironment env;
+
+    protected long pendingDemand = 0L;
+    protected Promise<Subscriber<? super T>> subscriber;
+
+    protected final Receptacle<Long> requests;
+
+    protected final Latch cancelled;
+
+    public ManualPublisher(TestEnvironment env) {
+      this.env = env;
+      requests = new Receptacle<Long>(env);
+      cancelled = new Latch(env);
+      subscriber = new Promise<Subscriber<? super T>>(this.env);
+    }
+
+    @Override
+    public void subscribe(Subscriber<? super T> s) {
+      if (!subscriber.isCompleted()) {
+        subscriber.completeImmediatly(s);
+
+        Subscription subs = new Subscription() {
+          @Override
+          public void request(long elements) {
+            requests.add(elements);
+          }
+
+          @Override
+          public void cancel() {
+            cancelled.close();
+          }
+        };
+        s.onSubscribe(subs);
+
+      } else {
+        env.flop("TestPublisher doesn't support more than one Subscriber");
+      }
+    }
+
+    public void sendNext(T element) {
+      if (subscriber.isCompleted()) {
+        subscriber.value().onNext(element);
+      } else {
+        env.flop("Cannot sendNext before having a Subscriber");
+      }
+    }
+
+    public void sendCompletion() {
+      if (subscriber.isCompleted()) {
+        subscriber.value().onComplete();
+      } else {
+        env.flop("Cannot sendCompletion before having a Subscriber");
+      }
+    }
+
+    public void sendError(Throwable cause) {
+      if (subscriber.isCompleted()) {
+        subscriber.value().onError(cause);
+      } else {
+        env.flop("Cannot sendError before having a Subscriber");
+      }
+    }
+
+    public long expectRequest() throws InterruptedException {
+      return expectRequest(env.defaultTimeoutMillis());
+    }
+
+    public long expectRequest(long timeoutMillis) throws InterruptedException {
+      long requested = requests.next(timeoutMillis, "Did not receive expected `request` call");
+      if (requested <= 0) {
+        return env.<Long>flopAndFail(String.format("Requests cannot be zero or negative but received request(%s)", requested));
+      } else {
+        pendingDemand += requested;
+        return requested;
+      }
+    }
+
+
+    public long expectRequest(long timeoutMillis, String errorMessageAddendum) throws InterruptedException {
+      long requested = requests.next(timeoutMillis, String.format("Did not receive expected `request` call. %s", errorMessageAddendum));
+      if (requested <= 0) {
+        return env.<Long>flopAndFail(String.format("Requests cannot be zero or negative but received request(%s)", requested));
+      } else {
+        pendingDemand += requested;
+        return requested;
+      }
+    }
+
+    public void expectExactRequest(long expected) throws InterruptedException {
+      expectExactRequest(expected, env.defaultTimeoutMillis());
+    }
+
+    public void expectExactRequest(long expected, long timeoutMillis) throws InterruptedException {
+      long requested = expectRequest(timeoutMillis);
+      if (requested != expected) {
+        env.flop(String.format("Received `request(%d)` on upstream but expected `request(%d)`", requested, expected));
+      }
+      pendingDemand += requested;
+    }
+
+    public void expectNoRequest() throws InterruptedException {
+      expectNoRequest(env.defaultTimeoutMillis());
+    }
+
+    public void expectNoRequest(long timeoutMillis) throws InterruptedException {
+      requests.expectNone(timeoutMillis, "Received an unexpected call to: request: ");
+    }
+
+    public void expectCancelling() throws InterruptedException {
+      expectCancelling(env.defaultTimeoutMillis());
+    }
+
+    public void expectCancelling(long timeoutMillis) throws InterruptedException {
+      cancelled.expectClose(timeoutMillis, "Did not receive expected cancelling of upstream subscription");
+    }
+
+    public boolean isCancelled() throws InterruptedException {
+      return cancelled.isClosed();
+    }
+  }
+
+  /**
+   * Like a CountDownLatch, but resettable and with some convenience methods
+   */
+  public static class Latch {
+    private final TestEnvironment env;
+    volatile private CountDownLatch countDownLatch = new CountDownLatch(1);
+
+    public Latch(TestEnvironment env) {
+      this.env = env;
+    }
+
+    public void reOpen() {
+      countDownLatch = new CountDownLatch(1);
+    }
+
+    public boolean isClosed() {
+      return countDownLatch.getCount() == 0;
+    }
+
+    public void close() {
+      countDownLatch.countDown();
+    }
+
+    public void assertClosed(String openErrorMsg) {
+      if (!isClosed()) {
+        env.flop(new ExpectedClosedLatchException(openErrorMsg));
+      }
+    }
+
+    public void assertOpen(String closedErrorMsg) {
+      if (isClosed()) {
+        env.flop(new ExpectedOpenLatchException(closedErrorMsg));
+      }
+    }
+
+    public void expectClose(String notClosedErrorMsg) throws InterruptedException {
+      expectClose(env.defaultTimeoutMillis(), notClosedErrorMsg);
+    }
+
+    public void expectClose(long timeoutMillis, String notClosedErrorMsg) throws InterruptedException {
+      countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+      if (countDownLatch.getCount() > 0) {
+        env.flop(String.format("%s within %d ms", notClosedErrorMsg, timeoutMillis));
+      }
+    }
+
+    static final class ExpectedOpenLatchException extends RuntimeException {
+      public ExpectedOpenLatchException(String message) {
+        super(message);
+      }
+    }
+
+    static final class ExpectedClosedLatchException extends RuntimeException {
+      public ExpectedClosedLatchException(String message) {
+        super(message);
+      }
+    }
+
+  }
+
+  // simple promise for *one* value, which cannot be reset
+  public static class Promise<T> {
+    private final TestEnvironment env;
+
+    public static <T> Promise<T> completed(TestEnvironment env, T value) {
+      Promise<T> promise = new Promise<T>(env);
+      promise.completeImmediatly(value);
+      return promise;
+    }
+
+    public Promise(TestEnvironment env) {
+      this.env = env;
+    }
+
+    private ArrayBlockingQueue<T> abq = new ArrayBlockingQueue<T>(1);
+    private AtomicReference<T> _value = new AtomicReference<T>();
+
+    public T value() {
+      final T value = _value.get();
+      if (value != null) {
+        return value;
+      } else {
+        env.flop("Cannot access promise value before completion");
+        return null;
+      }
+    }
+
+    public boolean isCompleted() {
+      return _value.get() != null;
+    }
+
+    /**
+     * Allows using expectCompletion to await for completion of the value and complete it _then_
+     */
+    public void complete(T value) {
+      if (_value.compareAndSet(null, value)) {
+        // we add the value to the queue such to wake up any expectCompletion which was triggered before complete() was called
+        abq.add(value);
+      } else {
+        env.flop(String.format("Cannot complete a promise more than once! Present value: %s, attempted to set: %s", _value.get(), value));
+      }
+    }
+
+    /**
+     * Same as complete.
+     *
+     * Keeping this method for binary compatibility.
+     */
+    public void completeImmediatly(T value) {
+      complete(value);
+    }
+
+    public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException {
+      if (!isCompleted()) {
+        T val = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS);
+
+        if (val == null) {
+          env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis));
+        }
+      }
+    }
+  }
+
+  // a "Promise" for multiple values, which also supports "end-of-stream reached"
+  public static class Receptacle<T> {
+    final int QUEUE_SIZE = 2 * TEST_BUFFER_SIZE;
+    private final TestEnvironment env;
+
+    private final ArrayBlockingQueue<Optional<T>> abq = new ArrayBlockingQueue<Optional<T>>(QUEUE_SIZE);
+
+    private final Latch completedLatch;
+
+    Receptacle(TestEnvironment env) {
+      this.env = env;
+      this.completedLatch = new Latch(env);
+    }
+
+    public void add(T value) {
+      completedLatch.assertOpen(String.format("Unexpected element %s received after stream completed", value));
+
+      abq.add(Optional.of(value));
+    }
+
+    public void complete() {
+      completedLatch.assertOpen("Unexpected additional complete signal received!");
+      completedLatch.close();
+
+      abq.add(Optional.<T>empty());
+    }
+
+    public T next(long timeoutMillis, String errorMsg) throws InterruptedException {
+      Optional<T> value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS);
+
+      if (value == null) {
+        return env.flopAndFail(String.format("%s within %d ms", errorMsg, timeoutMillis));
+      } else if (value.isDefined()) {
+        return value.get();
+      } else {
+        return env.flopAndFail("Expected element but got end-of-stream");
+      }
+    }
+
+    public Optional<T> nextOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException {
+      Optional<T> value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS);
+
+      if (value == null) {
+        env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis));
+        return Optional.empty();
+      }
+
+      return value;
+    }
+
+    /**
+     * @param timeoutMillis total timeout time for awaiting all {@code elements} number of elements
+     */
+    public List<T> nextN(long elements, long timeoutMillis, String errorMsg) throws InterruptedException {
+      List<T> result = new LinkedList<T>();
+      long remaining = elements;
+      long deadline = System.currentTimeMillis() + timeoutMillis;
+      while (remaining > 0) {
+        long remainingMillis = deadline - System.currentTimeMillis();
+
+        result.add(next(remainingMillis, errorMsg));
+        remaining--;
+      }
+
+      return result;
+    }
+
+
+    public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException {
+      Optional<T> value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS);
+
+      if (value == null) {
+        env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis));
+      } else if (value.isDefined()) {
+        env.flop(String.format("Expected end-of-stream but got element [%s]", value.get()));
+      } // else, ok
+    }
+
+    /**
+     * @deprecated Deprecated in favor of {@link #expectError(Class, long, long, String)}.
+     */
+    @Deprecated
+    public <E extends Throwable> E expectError(Class<E> clazz, long timeoutMillis, String errorMsg) throws Exception {
+      return expectError(clazz, timeoutMillis, timeoutMillis, errorMsg);
+    }
+
+    @SuppressWarnings("unchecked")
+    final <E extends Throwable> E expectError(Class<E> clazz, final long totalTimeoutMillis,
+                                              long pollTimeoutMillis,
+                                              String errorMsg) throws Exception {
+      long totalTimeoutRemainingNs = MILLISECONDS.toNanos(totalTimeoutMillis);
+      long timeStampANs = System.nanoTime();
+      long timeStampBNs;
+
+      for (;;) {
+        Thread.sleep(Math.min(pollTimeoutMillis, NANOSECONDS.toMillis(totalTimeoutRemainingNs)));
+
+        if (env.asyncErrors.isEmpty()) {
+          timeStampBNs = System.nanoTime();
+          totalTimeoutRemainingNs =- timeStampBNs - timeStampANs;
+          timeStampANs = timeStampBNs;
+
+          if (totalTimeoutRemainingNs <= 0) {
+            return env.flopAndFail(String.format("%s within %d ms", errorMsg, totalTimeoutMillis));
+          }
+        } else {
+          // ok, there was an expected error
+          Throwable thrown = env.asyncErrors.remove(0);
+
+          if (clazz.isInstance(thrown)) {
+            return (E) thrown;
+          } else {
+
+            return env.flopAndFail(String.format("%s within %d ms; Got %s but expected %s",
+                    errorMsg, totalTimeoutMillis, thrown.getClass().getCanonicalName(), clazz.getCanonicalName()));
+          }
+        }
+      }
+    }
+
+    public void expectNone(long withinMillis, String errorMsgPrefix) throws InterruptedException {
+      Thread.sleep(withinMillis);
+      Optional<T> value = abq.poll();
+
+      if (value == null) {
+        // ok
+      } else if (value.isDefined()) {
+        env.flop(String.format("%s [%s]", errorMsgPrefix, value.get()));
+      } else {
+        env.flop("Expected no element but got end-of-stream");
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.tck.flow.support.Function;
+import org.reactivestreams.tck.flow.support.HelperPublisher;
+import org.reactivestreams.tck.flow.support.InfiniteHelperPublisher;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Type which is able to create elements based on a seed {@code id} value.
+ * <p>
+ * Simplest implementations will simply return the incoming id as the element.
+ *
+ * @param <T> type of element to be delivered to the Subscriber
+ */
+public abstract class WithHelperPublisher<T> {
+
+  /** ExecutorService to be used by the provided helper {@link org.reactivestreams.Publisher} */
+  public abstract ExecutorService publisherExecutorService();
+
+  /**
+   * Implement this method to match your expected element type.
+   * In case of implementing a simple Subscriber which is able to consume any kind of element simply return the
+   * incoming {@code element} element.
+   * <p>
+   * Sometimes the Subscriber may be limited in what type of element it is able to consume, this you may have to implement
+   * this method such that the emitted element matches the Subscribers requirements. Simplest implementations would be
+   * to simply pass in the {@code element} as payload of your custom element, such as appending it to a String or other identifier.
+   * <p>
+   * <b>Warning:</b> This method may be called concurrently by the helper publisher, thus it should be implemented in a
+   * thread-safe manner.
+   *
+   * @return element of the matching type {@code T} that will be delivered to the tested Subscriber
+   */
+  public abstract T createElement(int element);
+
+  /**
+   * Helper method required for creating the Publisher to which the tested Subscriber will be subscribed and tested against.
+   * <p>
+   * By default an <b>asynchronously signalling Publisher</b> is provided, which will use {@link #createElement(int)}
+   * to generate elements type your Subscriber is able to consume.
+   * <p>
+   * Sometimes you may want to implement your own custom custom helper Publisher - to validate behaviour of a Subscriber
+   * when facing a synchronous Publisher for example. If you do, it MUST emit the exact number of elements asked for
+   * (via the {@code elements} parameter) and MUST also must treat the following numbers of elements in these specific ways:
+   * <ul>
+   *   <li>
+   *     If {@code elements} is {@code Long.MAX_VALUE} the produced stream must be infinite.
+   *   </li>
+   *   <li>
+   *     If {@code elements} is {@code 0} the {@code Publisher} should signal {@code onComplete} immediatly.
+   *     In other words, it should represent a "completed stream".
+   *   </li>
+   * </ul>
+   */
+  @SuppressWarnings("unchecked")
+  public Publisher<T> createHelperPublisher(long elements) {
+    final Function<Integer, T> mkElement = new Function<Integer, T>() {
+      @Override public T apply(Integer id) throws Throwable {
+        return createElement(id);
+      }
+    };
+
+    if (elements > Integer.MAX_VALUE) return new InfiniteHelperPublisher(mkElement, publisherExecutorService());
+    else return new HelperPublisher(0, (int) elements, mkElement, publisherExecutorService());
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.FlowAdapters;
+import org.reactivestreams.tck.PublisherVerification;
+import org.reactivestreams.tck.TestEnvironment;
+
+import java.util.concurrent.Flow;
+
+/**
+ * Provides tests for verifying a Java 9+ {@link java.util.concurrent.Flow.Publisher} specification rules.
+ *
+ * @see java.util.concurrent.Flow.Publisher
+ */
+public abstract class FlowPublisherVerification<T> extends PublisherVerification<T> {
+
+  public FlowPublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) {
+    super(env, publisherReferenceGCTimeoutMillis);
+  }
+
+  public FlowPublisherVerification(TestEnvironment env) {
+    super(env);
+  }
+
+  @Override
+  final public Publisher<T> createPublisher(long elements) {
+    final Flow.Publisher<T> flowPublisher = createFlowPublisher(elements);
+    return FlowAdapters.toPublisher(flowPublisher);
+  }
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a Publisher for a stream with exactly the given number of elements.
+   * If `elements` is `Long.MAX_VALUE` the produced stream must be infinite.
+   */
+  public abstract Flow.Publisher<T> createFlowPublisher(long elements);
+
+  @Override
+  final public Publisher<T> createFailedPublisher() {
+    final Flow.Publisher<T> failed = createFailedFlowPublisher();
+    if (failed == null) return null; // because `null` means "SKIP" in createFailedPublisher
+    else return FlowAdapters.toPublisher(failed);
+  }
+  /**
+   * By implementing this method, additional TCK tests concerning a "failed" publishers will be run.
+   *
+   * The expected behaviour of the {@link Flow.Publisher} returned by this method is hand out a subscription,
+   * followed by signalling {@code onError} on it, as specified by Rule 1.9.
+   *
+   * If you ignore these additional tests, return {@code null} from this method.
+   */
+  public abstract Flow.Publisher<T> createFailedFlowPublisher();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow;
+
+import org.reactivestreams.FlowAdapters;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.Subscription;
+import org.reactivestreams.tck.SubscriberBlackboxVerification;
+import org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.support.SubscriberBlackboxVerificationRules;
+
+import java.util.concurrent.Flow;
+
+/**
+ * Provides tests for verifying {@link java.util.concurrent.Flow.Subscriber} and {@link java.util.concurrent.Flow.Subscription}
+ * specification rules, without any modifications to the tested implementation (also known as "Black Box" testing).
+ *
+ * This verification is NOT able to check many of the rules of the spec, and if you want more
+ * verification of your implementation you'll have to implement {@code org.reactivestreams.tck.SubscriberWhiteboxVerification}
+ * instead.
+ *
+ * @see java.util.concurrent.Flow.Subscriber
+ * @see java.util.concurrent.Flow.Subscription
+ */
+public abstract class FlowSubscriberBlackboxVerification<T> extends SubscriberBlackboxVerification<T>
+  implements SubscriberBlackboxVerificationRules {
+
+  protected FlowSubscriberBlackboxVerification(TestEnvironment env) {
+    super(env);
+  }
+
+  @Override
+  public final void triggerRequest(Subscriber<? super T> subscriber) {
+    triggerFlowRequest(FlowAdapters.toFlowSubscriber(subscriber));
+  }
+  /**
+   * Override this method if the {@link java.util.concurrent.Flow.Subscriber} implementation you are verifying
+   * needs an external signal before it signals demand to its Publisher.
+   *
+   * By default this method does nothing.
+   */
+  public void triggerFlowRequest(Flow.Subscriber<? super T> subscriber) {
+    // this method is intentionally left blank
+  }
+
+  @Override
+  public final Subscriber<T> createSubscriber() {
+    return FlowAdapters.<T>toSubscriber(createFlowSubscriber());
+  }
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a new {@link Flow.Subscriber} instance to be subjected to the testing logic.
+   */
+  abstract public Flow.Subscriber<T> createFlowSubscriber();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow;
+
+import org.reactivestreams.FlowAdapters;
+import org.reactivestreams.Subscriber;
+import org.reactivestreams.tck.SubscriberWhiteboxVerification;
+import org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules;
+
+import java.util.concurrent.Flow;
+
+/**
+ * Provides whitebox style tests for verifying {@link java.util.concurrent.Flow.Subscriber}
+ * and {@link java.util.concurrent.Flow.Subscription} specification rules.
+ *
+ * @see java.util.concurrent.Flow.Subscriber
+ * @see java.util.concurrent.Flow.Subscription
+ */
+public abstract class FlowSubscriberWhiteboxVerification<T> extends SubscriberWhiteboxVerification<T>
+  implements SubscriberWhiteboxVerificationRules {
+
+  protected FlowSubscriberWhiteboxVerification(TestEnvironment env) {
+    super(env);
+  }
+
+  @Override
+  final public Subscriber<T> createSubscriber(WhiteboxSubscriberProbe<T> probe) {
+    return FlowAdapters.toSubscriber(createFlowSubscriber(probe));
+  }
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic.
+   *
+   * In order to be meaningfully testable your Subscriber must inform the given
+   * `WhiteboxSubscriberProbe` of the respective events having been received.
+   */
+  protected abstract Flow.Subscriber<T> createFlowSubscriber(WhiteboxSubscriberProbe<T> probe);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow;
+
+import org.reactivestreams.*;
+import org.reactivestreams.tck.IdentityProcessorVerification;
+import org.reactivestreams.tck.TestEnvironment;
+import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules;
+import org.reactivestreams.tck.flow.support.PublisherVerificationRules;
+
+import java.util.concurrent.Flow;
+
+public abstract class IdentityFlowProcessorVerification<T> extends IdentityProcessorVerification<T>
+  implements SubscriberWhiteboxVerificationRules, PublisherVerificationRules {
+
+  public IdentityFlowProcessorVerification(TestEnvironment env) {
+    super(env);
+  }
+
+  public IdentityFlowProcessorVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) {
+    super(env, publisherReferenceGCTimeoutMillis);
+  }
+
+  public IdentityFlowProcessorVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis, int processorBufferSize) {
+    super(env, publisherReferenceGCTimeoutMillis, processorBufferSize);
+  }
+
+  /**
+   * By implementing this method, additional TCK tests concerning a "failed" Flow publishers will be run.
+   *
+   * The expected behaviour of the {@link Flow.Publisher} returned by this method is hand out a subscription,
+   * followed by signalling {@code onError} on it, as specified by Rule 1.9.
+   *
+   * If you want to ignore these additional tests, return {@code null} from this method.
+   */
+  protected abstract Flow.Publisher<T> createFailedFlowPublisher();
+
+  /**
+   * This is the main method you must implement in your test incarnation.
+   * It must create a {@link Flow.Processor}, which simply forwards all stream elements from its upstream
+   * to its downstream. It must be able to internally buffer the given number of elements.
+   *
+   * @param bufferSize number of elements the processor is required to be able to buffer.
+   */
+  protected abstract Flow.Processor<T,T> createIdentityFlowProcessor(int bufferSize);
+
+  @Override
+  public final Processor<T, T> createIdentityProcessor(int bufferSize) {
+    return FlowAdapters.toProcessor(createIdentityFlowProcessor(bufferSize));
+  }
+
+  @Override
+  public final Publisher<T> createFailedPublisher() {
+    Flow.Publisher<T> failed = createFailedFlowPublisher();
+    if (failed == null) return null; // because `null` means "SKIP" in createFailedPublisher
+    else return FlowAdapters.toPublisher(failed);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+public interface Function<In, Out> {
+  public Out apply(In in) throws Throwable;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.Executor;
+
+import org.reactivestreams.example.unicast.AsyncIterablePublisher;
+
+public class HelperPublisher<T> extends AsyncIterablePublisher<T> {
+
+    public HelperPublisher(final int from, final int to, final Function<Integer, T> create, final Executor executor) {
+        super(new Iterable<T>() {
+          { if(from > to) throw new IllegalArgumentException("from must be equal or greater than to!"); }
+          @Override public Iterator<T> iterator() {
+            return new Iterator<T>() {
+              private int at = from;
+              @Override public boolean hasNext() { return at < to; }
+              @Override public T next() {
+                if (!hasNext()) return Collections.<T>emptyList().iterator().next();
+                else try {
+                  return create.apply(at++);
+                } catch (Throwable t) {
+                  throw new IllegalStateException(String.format("Failed to create element for id %d!", at - 1), t);
+                }
+              }
+              @Override public void remove() { throw new UnsupportedOperationException(); }
+            };
+          }
+        }, executor);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+import org.reactivestreams.example.unicast.AsyncIterablePublisher;
+
+import java.util.Iterator;
+import java.util.concurrent.Executor;
+
+public class InfiniteHelperPublisher<T> extends AsyncIterablePublisher<T> {
+
+    public InfiniteHelperPublisher(final Function<Integer, T> create, final Executor executor) {
+        super(new Iterable<T>() {
+          @Override public Iterator<T> iterator() {
+            return new Iterator<T>() {
+              private int at = 0;
+
+              @Override public boolean hasNext() { return true; }
+              @Override public T next() {
+                try {
+                  return create.apply(at++); // Wraps around on overflow
+                } catch (Throwable t) {
+                  throw new IllegalStateException(
+                    String.format("Failed to create element in %s for id %s!", getClass().getSimpleName(), at - 1), t);
+                }
+              }
+              @Override public void remove() { throw new UnsupportedOperationException(); }
+            };
+          }
+        }, executor);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+
+/**
+ * Copy of scala.control.util.NonFatal in order to not depend on scala-library
+ */
+public class NonFatal {
+  private NonFatal() {
+    // no instances, please.
+  }
+
+  /**
+   * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal
+   *
+   * @param t throwable to be matched for fatal-ness
+   * @return true if is a non-fatal throwable, false otherwise
+   */
+  public static boolean isNonFatal(Throwable t) {
+    if (t instanceof StackOverflowError) {
+      // StackOverflowError ok even though it is a VirtualMachineError
+      return true;
+    } else if (t instanceof VirtualMachineError ||
+        t instanceof ThreadDeath ||
+        t instanceof InterruptedException ||
+        t instanceof LinkageError) {
+      // VirtualMachineError includes OutOfMemoryError and other fatal errors
+      return false;
+    } else {
+      return true;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+import java.util.NoSuchElementException;
+
+// simplest possible version of Scala's Option type
+public abstract class Optional<T> {
+
+  private static final Optional<Object> NONE = new Optional<Object>() {
+    @Override
+    public Object get() {
+      throw new NoSuchElementException(".get call on None!");
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return true;
+    }
+  };
+
+  private Optional() {
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> Optional<T> empty() {
+    return (Optional<T>) NONE;
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> Optional<T> of(T it) {
+    if (it == null) return (Optional<T>) Optional.NONE;
+    else return new Some(it);
+  }
+
+  public abstract T get();
+
+  public abstract boolean isEmpty();
+
+  public boolean isDefined() {
+    return !isEmpty();
+  }
+
+  public static class Some<T> extends Optional<T> {
+    private final T value;
+
+    Some(T value) {
+      this.value = value;
+    }
+
+    @Override
+    public T get() {
+      return value;
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return false;
+    }
+
+    @Override
+    public String toString() {
+      return String.format("Some(%s)", value);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "None";
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+/**
+ * Internal TCK use only.
+ * Add / Remove tests for PublisherVerification here to make sure that they arre added/removed in the other places.
+ */
+public interface PublisherVerificationRules {
+  /**
+   * Validates that the override of {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()}
+   * returns a non-negative value.
+   */
+  void required_validate_maxElementsFromPublisher() throws Exception;
+  /**
+   * Validates that the override of {@link org.reactivestreams.tck.PublisherVerification#boundedDepthOfOnNextAndRequestRecursion()}
+   * returns a positive value.
+   */
+  void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception;
+  /**
+   * Asks for a {@code Publisher} that should emit exactly one item and complete (both within a
+   * timeout specified by {@link org.reactivestreams.tck.TestEnvironment#defaultTimeoutMillis()})
+   * in response to a request(1).
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} returns zero.
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code Publisher.subscribe(Subscriber)} method has actual implementation,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher},
+   * that {@code Publisher} is actually subscribed to,</li>
+   * <li>if the {@code Publisher} is part of a chain, all elements actually issue a {@code request()} call
+   * in response to the test subscriber or by default to their upstream,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called
+   * as part of the preparation process (usually before subscribing to other {@code Publisher}s),</li>
+   * <li>if the {@code Publisher} implementation works for a consumer that calls {@code request(1)},</li>
+   * <li>if the {@code Publisher} implementation is able to emit an {@code onComplete} without requests,</li>
+   * <li>that the {@code Publisher} implementation does not emit more than the allowed elements (exactly one).</li>
+   * </ul>
+   */
+  void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable;
+  /**
+   * Asks for a {@code Publisher} that should emit exactly three items and complete (all within a
+   * timeout specified by {@link org.reactivestreams.tck.TestEnvironment#defaultTimeoutMillis()}).
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * The tests requests one-by-one and verifies each single response item arrives in time.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code Publisher.subscribe(Subscriber)} method has actual implementation,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher},
+   * that {@code Publisher} is actually subscribed to,</li>
+   * <li>if the {@code Publisher} is part of a chain, all elements actually issue a {@code request()} call
+   * in response to the test subscriber or by default to their upstream,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called
+   * as part of the preparation process (usually before subscribing to other {@code Publisher}s),</li>
+   * <li>if the {@code Publisher} implementation works for a subscriber that calls {@code request(1)} after consuming an item,</li>
+   * <li>if the {@code Publisher} implementation is able to emit an {@code onComplete} without requests.</li>
+   * </ul>
+   */
+  void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable;
+  /**
+   * Asks for a {@code Publisher} that responds to a request pattern of 0 (not requesting upfront), 1, 1 and 2
+   * in a timely manner.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.1'>1.1</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 5.
+   * <p>
+   * This test ensures that the {@code Publisher} implementation correctly responds to {@code request()} calls that in
+   * total are less than the number of elements this {@code Publisher} could emit (thus the completion event won't be emitted).
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} and verifies that requesting once and with more than the length (but bounded) results in the
+   * correct number of items to be emitted (i.e., length 3 and request 10) followed by an {@code onComplete} signal.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.2'>1.2</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * This test ensures that the {@code Publisher} implementation can deal with larger requests than the number of items it can produce.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass.</li>
+   * </ul>
+   */
+  void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (i.e., length 10), repeatedly subscribes to this {@code Publisher}, requests items
+   * one by one and verifies the {@code Publisher} calls the {@code onXXX} methods non-overlappingly.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.3'>1.3</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10.
+   * <p>
+   * Note that this test is probabilistic, that is, may not capture any concurrent invocation in a {code Publisher} implementation.
+   * Note also that this test is sensitive to cases when a {@code request()} call in {@code onSubscribe()} triggers an asynchronous
+   * call to the other {@code onXXX} methods. In contrast, the test allows synchronous call chain of
+   * {@code onSubscribe -> request -> onNext}.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if a {@code request()} call from {@code onSubscribe()} could trigger an asynchronous call to {@code onNext()} and if so, make sure
+   * such {@code request()} calls are deferred until the call to {@code onSubscribe()} returns normally.</li>
+   * </ul>
+   */
+  void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable;
+  /**
+   * Asks for an error {@code Publisher} that should call {@code onSubscribe} exactly once
+   * followed by a single call to {@code onError()} without receiving any requests and otherwise
+   * not throwing any exception.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.4'>1.4</a>
+   * <p>
+   * The test is not executed if {@code PublisherVerification.createErrorPublisher()} returns null.
+   * <p>
+   * If this test fails, the following could be checked within the error {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code Publisher.subscribe(Subscriber)} method has actual implementation,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher},
+   * that {@code Publisher} is actually subscribed to,</li>
+   * <li>if the {@code Publisher} implementation does signal an {@code onSubscribe} before signalling {@code onError},</li>
+   * <li>if the {@code Publisher} implementation is able to emit an {@code onError} without requests,</li>
+   * <li>if the {@code Publisher} is non-empty as this test requires a {@code Publisher} to signal an
+   * {@code onError} eagerly.</li>
+   * </ul>
+   */
+  void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (i.e., length 3) and verifies, after requesting one by one, the sequence
+   * completes normally.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.5'>1.5</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * Note that the tests requests 1 after the items have been received and before expecting an {@code onComplete} signal.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * </ul>
+   */
+  void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable;
+  /**
+   * Asks for an empty {@code Publisher} (i.e., length 0) and verifies it completes in a timely manner.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.5'>1.5</a>
+   * <p>
+   * Note that the tests requests 1 before expecting an {@code onComplete} signal.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>if the {@code Publisher} is non-empty as this test requires a {@code Publisher} without items.</li>
+   * </ul>
+   */
+  void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable;
+  /**
+   * Currently, this test is skipped because it is unclear this rule can be effectively checked
+   * on a {@code Publisher} instance without looking into or hooking into the implementation of it.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.6'>1.6</a>
+   */
+  void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable;
+  /**
+   * Asks for a single-element {@code Publisher} and checks if requesting after the terminal event doesn't
+   * lead to more items or terminal signals to be emitted.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.7'>1.7</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1.
+   * <p>
+   * The tests requests more items than the expected {@code Publisher} length upfront and some more items after its completion.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>the indication for the terminal state is properly persisted and a request call can't trigger emission of more items or another
+   * terminal signal.</li>
+   * </ul>
+   */
+  void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable;
+  /**
+   * Currently, this test is skipped, although it is possible to validate an error {@code Publisher} along
+   * the same lines as {@link #required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled()}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.7'>1.7</a>
+   */
+  void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable;
+  /**
+   * Currently, this test is skipped because there was no agreement on how to verify its "eventually" requirement.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.8'>1.8</a>
+   */
+  void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable;
+  /**
+   * Asks for an empty {@code Publisher} and verifies if {@code onSubscribe} signal was emitted before
+   * any other {@code onNext}, {@code onError} or {@code onComplete} signal.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.9'>1.9</a>
+   * <p>
+   * Note that this test doesn't request anything, however, an {@code onNext} is not considered as a failure.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>the {@code Publisher.subscribe(Subscriber)} method has actual implementation,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher},
+   * that {@code Publisher} is actually subscribed to,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called
+   * as part of the preparation process (usually before subscribing to other {@code Publisher}s).</li>
+   * </ul>
+   */
+  void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable;
+  /**
+   * Currently, this test is skipped because there is no common agreement on what is to be considered a fatal exception and
+   * besides, {@code Publisher.subscribe} is only allowed throw a {@code NullPointerException} and any other
+   * exception would require looking into or hooking into the implementation of the {@code Publisher}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.9'>1.9</a>
+   */
+  void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable;
+  /**
+   * Asks for an empty {@code Publisher} and calls {@code subscribe} on it with {@code null} that should result in
+   * a {@code NullPointerException} to be thrown.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.9'>1.9</a>
+   * <p>
+   * If this test fails, check if the {@code subscribe()} implementation has an explicit null check (or a method dereference
+   * on the {@code Subscriber}), especially if the incoming {@code Subscriber} is wrapped or stored to be used later.
+   */
+  void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable;
+  /**
+   * Asks for an error {@code Publisher} that should call {@code onSubscribe} exactly once
+   * followed by a single call to {@code onError()} without receiving any requests.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.9'>1.9</a>
+   * <p>
+   * The test is not executed if {@code PublisherVerification.createErrorPublisher()} returns null.
+   * <p>
+   * The difference between this test and {@link #optional_spec104_mustSignalOnErrorWhenFails()} is that there is
+   * no explicit verification if exceptions were thrown in addition to the regular {@code onSubscribe+onError} signal pair.
+   * <p>
+   * If this test fails, the following could be checked within the error {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code Publisher.subscribe(Subscriber)} method has actual implementation,</li>
+   * <li>in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher},
+   * that {@code Publisher} is actually subscribed to,</li>
+   * <li>if the {@code Publisher} implementation is able to emit an {@code onError} without requests,</li>
+   * <li>if the {@code Publisher} is non-empty as this test expects a {@code Publisher} without items.</li>
+   * </ul>
+   */
+  void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable;
+  /**
+   * Currently, this test is skipped because enforcing rule §1.10 requires unlimited retention and reference-equal checks on
+   * all incoming {@code Subscriber} which is generally infeasible, plus reusing the same {@code Subscriber} instance is
+   * better detected (or ignored) inside {@code Subscriber.onSubscribe} when the method is called multiple times.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.10'>1.10</a>
+   */
+  void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable;
+  /**
+   * Asks for a single-element {@code Publisher} and subscribes to it twice, without consuming with either
+   * {@code Subscriber} instance
+   * (i.e., no requests are issued).
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.11'>1.11</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1.
+   * <p>
+   * Note that this test ignores what signals the {@code Publisher} emits. Any exception thrown through non-regular
+   * means will indicate a skipped test.
+   */
+  void optional_spec111_maySupportMultiSubscribe() throws Throwable;
+  /**
+   * Asks for a single-element {@code Publisher} and subscribes to it twice.
+   * Each {@code Subscriber} requests for 1 element and checks if onNext or onComplete signals was received.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.11'>1.11</a>,
+   * and depends on valid implementation of rule <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.5'>1.5</a>
+   * in order to verify this.
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1.
+   * <p>
+   * Any exception thrown through non-regular means will indicate a skipped test.
+   */
+  void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 5), subscribes 3 {@code Subscriber}s to it, requests with different
+   * patterns and checks if all 3 received the same events in the same order.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.11'>1.11</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 5.
+   * <p>
+   * The request pattern for the first {@code Subscriber} is (1, 1, 2, 1); for the second is (2, 3) and for the third is (3, 1, 1).
+   * <p>
+   * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of
+   * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test.
+   * <p>
+   * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher},
+   * see the skip message for an indication of this.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 3), subscribes 3 {@code Subscriber}s to it, requests more than the length items
+   * upfront with each and verifies they all received the same items in the same order (but does not verify they all complete).
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.11'>1.11</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of
+   * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test.
+   * <p>
+   * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher},
+   * see the skip message for an indication of this.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 3), subscribes 3 {@code Subscriber}s to it, requests more than the length items
+   * upfront with each and verifies they all received the same items in the same order followed by an {@code onComplete} signal.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#1.11'>1.11</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of
+   * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test.
+   * <p>
+   * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher},
+   * see the skip message for an indication of this.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 6), requests several times from within {@code onSubscribe} and then requests
+   * one-by-one from {@code onNext}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.2'>3.2</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 6.
+   * <p>
+   * The request pattern is 3 x 1 from within {@code onSubscribe} and one from within each {@code onNext} invocation.
+   * <p>
+   * The test consumes the {@code Publisher} but otherwise doesn't verify the {@code Publisher} completes (however, it checks
+   * for errors).
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable;
+  /**
+   * Asks for a {@code Publisher} with length equal to the value returned by {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()} plus 1,
+   * calls {@code request(1)} externally and then from within {@code onNext} and checks if the stack depth did not increase beyond the
+   * amount permitted by {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.3'>3.3</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than
+   * {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()} plus 1.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the implementation doesn't allow unbounded recursion when {@code request()} is called from within {@code onNext}, i.e., the lack of
+   * reentrant-safe state machine around the request amount (such as a for loop with a bound on the parameter {@code n} that calls {@code onNext}).
+   * </ul>
+   */
+  void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable;
+  /**
+   * Currently, this test is skipped because a {@code request} could enter into a synchronous computation via {@code onNext}
+   * legally and otherwise there is no common agreement how to detect such heavy computation reliably.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.4'>3.4</a>
+   */
+  void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception;
+  /**
+   * Currently, this test is skipped because there is no reliable agreed upon way to detect a heavy computation.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.5'>3.5</a>
+   */
+  void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception;
+  /**
+   * Asks for a short {@code Publisher} (length 3) and verifies that cancelling without requesting anything, then requesting
+   * items should result in no signals to be emitted.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.6'>3.6</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * The post-cancellation request pattern is (1, 1, 1).
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.</li>
+   * </ul>
+   */
+  void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable;
+  /**
+   * Asks for a single-element {@code Publisher} and verifies that without requesting anything, cancelling the sequence
+   * multiple times should result in no signals to be emitted and should result in an thrown exception.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.7'>3.7</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.</li>
+   * </ul>
+   */
+  void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 10) and issues a {@code request(0)} which should trigger an {@code onError} call
+   * with an {@code IllegalArgumentException}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.9'>3.9</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10.
+   * <p>
+   * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by
+   * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the
+   * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example).
+   * <p>
+   * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within
+   * the {@code Publisher}.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal
+   * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError}
+   * in general.
+   * </ul>
+   */
+  void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 10) and issues a random, negative {@code request()} call which should
+   * trigger an {@code onError} call with an {@code IllegalArgumentException}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.9'>3.9</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10.
+   * <p>
+   * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by
+   * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the
+   * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example).
+   * <p>
+   * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within
+   * the {@code Publisher}.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal
+   * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError}
+   * in general.
+   * </ul>
+   */
+  void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 10) and issues a random, negative {@code request()} call which should
+   * trigger an {@code onError} call with an {@code IllegalArgumentException}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.9'>3.9</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10.
+   * <p>
+   * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by
+   * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the
+   * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example).
+   * <p>
+   * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within
+   * the {@code Publisher}.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal
+   * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError}
+   * in general.
+   * </ul>
+   */
+  void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 20), requests some items (less than the length), consumes one item then
+   * cancels the sequence and verifies the publisher emitted at most the requested amount and stopped emitting (or terminated).
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.12'>3.12</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 20.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.</li>
+   * </ul>
+   */
+  void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 3) requests and consumes one element from it, cancels the {@code Subscription}
+   * , calls {@code System.gc()} and then checks if all references to the test {@code Subscriber} has been dropped (by checking
+   * the {@code WeakReference} has been emptied).
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.13'>3.13</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.</li>
+   * <li>the {@code Publisher} stores the {@code Subscriber} reference somewhere which is then not cleaned up when the {@code Subscriber} is cancelled.
+   * Note that this may happen on many code paths in a {@code Publisher}, for example in an emission loop that terminates because of the
+   * {@code cancel} signal or because reaching a terminal state. Note also that eagerly nulling {@code Subscriber} references may not be necessary
+   * for this test to pass in case there is a self-contained chain of them (i.e., {@code Publisher.subscribe()} creates a chain of fresh
+   * {@code Subscriber} instances where each of them only references their downstream {@code Subscriber} thus the chain can get GC'd
+   * when the reference to the final {@code Subscriber} is dropped).
+   * </ul>
+   */
+  void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 3) and requests {@code Long.MAX_VALUE} from it, verifying that the
+   * {@code Publisher} emits all of its items and completes normally
+   * and does not keep spinning attempting to fulfill the {@code Long.MAX_VALUE} demand by some means.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.17'>3.17</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable;
+  /**
+   * Asks for a short {@code Publisher} (length 3) and requests {@code Long.MAX_VALUE} from it in total (split across
+   * two {@code Long.MAX_VALUE / 2} and one {@code request(1)}), verifying that the
+   * {@code Publisher} emits all of its items and completes normally.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.17'>3.17</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} implements adding individual request amounts together properly (not overflowing into zero or negative pending request amounts)
+   * or not properly deducing the number of emitted items from the pending amount,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable;
+  /**
+   * Asks for a very long {@code Publisher} (up to {@code Integer.MAX_VALUE}), requests {@code Long.MAX_VALUE - 1} after
+   * each received item and expects no failure due to a potential overflow in the pending emission count while consuming
+   * 10 items and cancelling the sequence.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.17'>3.17</a>
+   * <p>
+   * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than {@code Integer.MAX_VALUE}.
+   * <p>
+   * The request pattern is one {@code request(1)} upfront and ten {@code request(Long.MAX_VALUE - 1)} after.
+   * <p>
+   * If this test fails, the following could be checked within the {@code Publisher} implementation:
+   * <ul>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,</li>
+   * <li>make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,</li>
+   * <li>if the {@code Publisher} implementation considers the cumulative request amount it receives,</li>
+   * <li>if the {@code Publisher} implements adding individual request amounts together properly (not overflowing into zero or negative pending request amounts)
+   * or not properly deducing the number of emitted items from the pending amount,</li>
+   * <li>if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -&gt; emitting or emitting -&gt; keep emitting works properly.</li>
+   * </ul>
+   */
+  void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+import org.reactivestreams.tck.SubscriberBlackboxVerification;
+
+/**
+ * Internal TCK use only.
+ * Add / Remove tests for SubscriberBlackboxVerification here to make sure that they arre added/removed in the other places.
+ */
+public interface SubscriberBlackboxVerificationRules {
+  /**
+   * Asks for a {@code Subscriber} instance, expects it to call {@code request()} in
+   * a timely manner and signals as many {@code onNext} items as the very first request
+   * amount specified by the {@code Subscriber}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.1'>2.1</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>This test emits the number of items requested thus the {@code Subscriber} implementation
+   * should not request too much.</li>
+   * <li>Only the very first {@code request} amount is considered.</li>
+   * <li>This test doesn't signal {@code onComplete} after the first set of {@code onNext} signals
+   * has been emitted and may cause resource leak in
+   * {@code Subscriber}s that expect a finite {@code Publisher}.</li>
+   * <li>The test ignores cancellation from the {@code Subscriber} and emits the requested amount regardless.</li>
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} requires external stimulus to begin requesting; override the
+   * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method
+   *  in this case,</li>
+   * <li>the {@code TestEnvironment} has large enough timeout specified in case the {@code Subscriber} has some time-delay behavior,</li>
+   * <li>if the {@code Subscriber} requests zero or a negative value in some circumstances,</li>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onNext} methods.
+   * </ul>
+   */
+  void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable;
+  /**
+   * Currently, this test is skipped because there is no agreed upon approach how
+   * to detect if the {@code Subscriber} really goes async or just responds in
+   * a timely manner.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.2'>2.2</a>
+   */
+  void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception;
+  /**
+   * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onComplete} synchronously,
+   * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s
+   * {@code onComplete} implementation.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.3'>2.3</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The test checks for the presensce of method named "onComplete" in the current stacktrace when handling
+   * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}.
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>no calls happen to {@code request} or {@code cancel} in response to an {@code onComplete}
+   * directly or indirectly,</li>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onComplete} methods.
+   * </ul>
+   */
+  void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable;
+  /**
+   * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onError} synchronously,
+   * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s
+   * {@code onComplete} implementation.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.3'>2.3</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The test checks for the presensce of method named "onError" in the current stacktrace when handling
+   * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}.
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>no calls happen to {@code request} or {@code cancel} in response to an {@code onError}
+   * directly or indirectly,</li>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onError} methods.
+   * </ul>
+   */
+  void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable;
+  /**
+   * Currently, this test is skipped because there is no way to check what the {@code Subscriber} "considers"
+   * since rule §2.3 forbids interaction from within the {@code onError} and {@code onComplete} methods.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.4'>2.4</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>It would be possible to check if there was an async interaction with the test's {@code Subscription}
+   * within a grace period but such check is still not generally decisive.</li>
+   * </ul>
+   */
+  void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception;
+  /**
+   * Asks for a {@code Subscriber}, signals {@code onSubscribe} twice synchronously and expects the second {@code Subscription} gets
+   * cancelled in a timely manner and without any calls to its {@code request} method.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.5'>2.5</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The test doesn't signal any other events than {@code onSubscribe} and may cause resource leak in
+   * {@code Subscriber}s that expect a finite {@code Publisher}.
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscribe.onSubscribe} implementation actually tries to detect multiple calls to it,</li>
+   * <li>if the second {@code Subscription} is cancelled asynchronously and that takes longer time than
+   * the {@code TestEnvironment}'s timeout permits.</li>
+   * </ul>
+   */
+  void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception;
+
+  /**
+   * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation
+   * to make it cancel the {@code Subscription} for some external condition.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.6'>2.6</a>
+   */
+  void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception;
+  /**
+   * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation
+   * to issue requests based on external stimulus.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.7'>2.7</a>
+   */
+  void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception;
+  /**
+   * Currently, this test is skipped because there is no way to make the {@code Subscriber} implementation
+   * cancel the test's {@code Subscription} and check the outcome of sending {@code onNext}s after such
+   * cancel.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.8'>2.8</a>
+   */
+  void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable;
+  /**
+   * Asks for a {@code Subscriber}, expects it to request some amount and in turn be able to receive an {@code onComplete}
+   * synchronously from the {@code request} call without any {@code onNext} signals before that.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.9'>2.9</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The test ignores cancellation from the {@code Subscriber}.</li>
+   * <li>Invalid request amounts are ignored by this test.</li>
+   * <li>Concurrent calls to the test's {@code Subscription.request()} must be externally synchronized, otherwise
+   * such case results probabilistically in multiple {@code onComplete} calls by the test.</li>
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onComplete} methods.
+   * <li>if the {@code Subscriber} requires external stimulus to begin requesting; override the
+   * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method
+   *  in this case,</li>
+   * </ul>
+   */
+  void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable;
+  /**
+   * Asks for a {@code Subscriber} and expects it to handle {@code onComplete} independent of whether the {@code Subscriber}
+   * requests items or not.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.9'>2.9</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>Currently, the test doesn't call {@code onSubscribe} on the {@code Subscriber} which violates §1.9.
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onComplete} methods.
+   * </ul>
+   */
+  void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable;
+  /**
+   * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.10'>2.10</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>Despite the method name, the test doesn't expect a request signal from {@code Subscriber} and emits the
+   * {@code onError} signal anyway.
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onError} methods.
+   * </ul>
+   */
+  void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable;
+
+  /**
+   * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.10'>2.10</a>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or
+   * {@code onError} methods.
+   * </ul>
+   */
+  void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable;
+
+  /**
+   * Currently, this test is skipped because it would require analyzing what the {@code Subscriber} implementation
+   * does.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.11'>2.11</a>
+   */
+  void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception;
+  /**
+   * Currently, this test is skipped because the test for
+   * {@link #required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal §2.5}
+   * is in a better position to test for handling the reuse of the same {@code Subscriber}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.12'>2.12</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>In addition to §2.5, this rule could be better verified when testing a {@code Publisher}'s subscription behavior.
+   * </ul>
+   */
+  void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable;
+  /**
+   * Currently, this test is skipped because it would require more control over the {@code Subscriber} to
+   * fail internally in response to a set of legal event emissions, not throw any exception from the {@code Subscriber}
+   * methods and have it cancel the {@code Subscription}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a>
+   */
+  void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception;
+  /**
+   * Asks for a {@code Subscriber} and signals an {@code onSubscribe} event with {@code null} as a parameter and
+   * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onSubscribe} method.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onSubscribe} method
+   * in response to a {@code null} parameter and not some other unchecked exception or no exception at all.
+   * </ul>
+   */
+  void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable;
+  /**
+   * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a
+   * {@code onNext} with {@code null} as a parameter and
+   * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onNext} method.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The test ignores cancellation and requests from the {@code Subscriber} and emits the {@code onNext}
+   * signal with a {@code null} parameter anyway.</li>
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method
+   * in response to a {@code null} parameter and not some other unchecked exception or no exception at all.
+   * </ul>
+   */
+  void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable;
+  /**
+   * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a
+   * {@code onError} with {@code null} as a parameter and
+   * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onError} method.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#2.13'>2.13</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The test ignores cancellation from the {@code Subscriber} and emits the {@code onError}
+   * signal with a {@code null} parameter anyway.</li>
+   * </ul>
+   * <p>
+   * If this test fails, the following could be checked within the {@code Subscriber} implementation:
+   * <ul>
+   * <li>if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method
+   * in response to a {@code null} parameter and not some other unchecked exception or no exception at all.
+   * </ul>
+   */
+  void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable;
+  /**
+   * Currently, this test is skipped because there is no agreed upon way for specifying, enforcing and testing
+   * a {@code Subscriber} with an arbitrary context.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.1'>3.1</a>
+   */
+  void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception;
+  /**
+   * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and
+   * a {@code Subscription} is not expected to be the active element in an established subscription.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.8'>3.8</a>
+   */
+  void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable;
+  /**
+   * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and
+   * a {@code Subscription} is not expected to be the active element in an established subscription.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.10'>3.10</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>This could be tested with a synchronous source currently not available within the TCK.</li>
+   * </ul>
+   */
+  void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception;
+  /**
+   * Currently, this test is skipped because signal production is the responsibility of the {@code Publisher} and
+   * a {@code Subscription} is not expected to be the active element in an established subscription.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.11'>3.11</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>Tests {@link #required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() §2.9}
+   * and {@link #required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() §2.10} are
+   * supposed to cover this case from the {@code Subscriber's} perspective.</li>
+   * </ul>
+   */
+  void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception;
+  /**
+   * Currently, this test is skipped because it is the responsibility of the {@code Publisher} deal with the case
+   * that all subscribers have cancelled their subscription.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.14'>3.14</a>
+   * <p>
+   * Notes:
+   * <ul>
+   * <li>The specification lists this as an optional behavior because only some {@code Publisher} implementations
+   * (most likely {@code Processor}s) would coordinate with multiple {@code Subscriber}s.</li>
+   * </ul>
+   */
+  void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception;
+  /**
+   * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation
+   * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response
+   * to an exception thrown from {@code Subscription.cancel}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.15'>3.15</a>
+   */
+  void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception;
+  /**
+   * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation
+   * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response
+   * to an exception thrown from {@code Subscription.request}.
+   * <p>
+   * <b>Verifies rule:</b> <a href='https://github.com/reactive-streams/reactive-streams-jvm#3.16'>3.16</a>
+   */
+  void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+public final class SubscriberBufferOverflowException extends RuntimeException {
+  public SubscriberBufferOverflowException() {
+  }
+
+  public SubscriberBufferOverflowException(String message) {
+    super(message);
+  }
+
+  public SubscriberBufferOverflowException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public SubscriberBufferOverflowException(Throwable cause) {
+    super(cause);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+/**
+ * Internal TCK use only.
+ * Add / Remove tests for PublisherVerificaSubscriberWhiteboxVerification here to make sure that they arre added/removed in the other places.
+ */
+public interface SubscriberWhiteboxVerificationRules {
+  void required_exerciseWhiteboxHappyPath() throws Throwable;
+  void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable;
+  void untested_spec202_shouldAsynchronouslyDispatch() throws Exception;
+  void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable;
+  void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable;
+  void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception;
+  void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable;
+  void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception;
+  void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception;
+  void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable;
+  void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable;
+  void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable;
+  void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable;
+  void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable;
+  void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception;
+  void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable;
+  void untested_spec213_failingOnSignalInvocation() throws Exception;
+  void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable;
+  void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable;
+  void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable;
+  void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception;
+  void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable;
+  void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception;
+  void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception;
+  void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception;
+  void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception;
+  void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/TestException.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package org.reactivestreams.tck.flow.support;
+
+/**
+ * Exception used by the TCK to signal failures.
+ * May be thrown or signalled through {@link org.reactivestreams.Subscriber#onError(Throwable)}.
+ */
+public final class TestException extends RuntimeException {
+  public TestException() {
+    super("Test Exception: Boom!");
+  }
+}
--- a/test/jdk/java/nio/channels/FileChannel/MapTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/nio/channels/FileChannel/MapTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -24,7 +24,7 @@
 /* @test
  * @bug 4429043 8002180
  * @summary Test file mapping with FileChannel
- * @run main/othervm MapTest
+ * @run main/othervm/timeout=240 MapTest
  * @key randomness
  */
 
@@ -195,7 +195,7 @@
      * the data exercising various valid and invalid writeback ranges.
      */
     private static void testForce() throws Exception {
-        for (int x=0; x<100; x++) {
+        for (int x=0; x<50; x++) {
             try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) {
                 FileChannel fc = raf.getChannel();
                 final int BLOCK_SIZE = 64;
--- a/test/jdk/java/nio/channels/Selector/RacyDeregister.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/nio/channels/Selector/RacyDeregister.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -41,11 +41,6 @@
  */
 public class RacyDeregister {
 
-    // FIXME: NUM_OUTER_LOOP_ITERATIONS should be reverted to the hard-coded
-    // value 15 when JDK-8161083 is resolved as either a bug or a non-issue.
-    static final int NUM_OUTER_LOOP_ITERATIONS =
-        System.getProperty("os.name").startsWith("Windows") ? 150 : 15;
-
     // 90% of 1200 second timeout as milliseconds
     static final int TIMEOUT_THRESHOLD_MILLIS = 1200*900;
 
@@ -90,7 +85,7 @@
 
             public void run() {
                 try {
-                    for (int k = 0; k < NUM_OUTER_LOOP_ITERATIONS; k++) {
+                    for (int k = 0; k < 15; k++) {
                         System.out.format("outer loop %3d at %7d ms%n", k,
                             System.currentTimeMillis() - t0);
                         System.out.flush();
--- a/test/jdk/java/nio/file/Files/Misc.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/nio/file/Files/Misc.java	Mon Jul 08 16:04:25 2019 +0530
@@ -22,11 +22,14 @@
  */
 
 /* @test
- * @bug 4313887 6838333 8005566 8032220 8215467
+ * @bug 4313887 6838333 8005566 8032220 8215467 8227080
  * @summary Unit test for miscellenous methods in java.nio.file.Files
  * @library ..
  */
 
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.channels.ClosedChannelException;
 import java.nio.file.*;
 import static java.nio.file.Files.*;
 import static java.nio.file.LinkOption.*;
@@ -44,6 +47,7 @@
             testIsSameFile(dir);
             testFileTypeMethods(dir);
             testAccessMethods(dir);
+            testSkip(dir);
         } finally {
              TestUtil.removeAll(dir);
         }
@@ -372,6 +376,38 @@
         }
     }
 
+    /**
+     * Tests Files.newInputStream(Path).skip().
+     */
+    static void testSkip(Path tmpdir) throws IOException {
+        Path file = createFile(tmpdir.resolve("foo"));
+        try (OutputStream out = Files.newOutputStream(file)) {
+            byte[] blah = new byte[8192];
+            Arrays.fill(blah, (byte)42);
+            out.write(blah);
+            out.close();
+            try (InputStream in = Files.newInputStream(file)) {
+                assertTrue(in.skip(-1) == 0);
+                assertTrue(in.skip(0) == 0);
+                assertTrue(in.skip(blah.length/4) == blah.length/4);
+                assertTrue(in.skip(blah.length/2) == blah.length/2);
+                assertTrue(in.skip(Long.MAX_VALUE) == blah.length/4);
+                in.close();
+                try {
+                    long n = in.skip(1);
+                    throw new RuntimeException("skip() did not fail");
+                } catch (IOException ioe) {
+                    if (!(ioe.getCause() instanceof ClosedChannelException)) {
+                        throw new RuntimeException
+                            ("IOException not caused by ClosedChannelException");
+                    }
+                }
+            }
+        } finally {
+            delete(file);
+        }
+    }
+
     static void assertTrue(boolean okay) {
         if (!okay)
             throw new RuntimeException("Assertion Failed");
--- a/test/jdk/java/util/Locale/LocaleProvidersRun.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/util/Locale/LocaleProvidersRun.java	Mon Jul 08 16:04:25 2019 +0530
@@ -159,7 +159,9 @@
     private static void testRun(String prefList, String methodName,
             String param1, String param2, String param3) throws Throwable{
         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("java");
-        launcher.addToolArg("-cp")
+        launcher.addToolArg("-ea")
+                .addToolArg("-esa")
+                .addToolArg("-cp")
                 .addToolArg(Utils.TEST_CLASS_PATH)
                 .addToolArg("-Djava.locale.providers=" + prefList)
                 .addToolArg("--add-exports=java.base/sun.util.locale.provider=ALL-UNNAMED")
--- a/test/jdk/java/util/Locale/SoftKeys.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/java/util/Locale/SoftKeys.java	Mon Jul 08 16:04:25 2019 +0530
@@ -24,10 +24,10 @@
  * @test
  * @bug 8196869
  * @summary Make sure we deal with internal Key data being cleared properly
- * @run main/othervm -Xms16m -Xmx16m -esa SoftKeys
  * @ignore This test aims to provoke NPEs, but due to the need to constrain
  *         memory usage it fails intermittently with OOME on various systems
  *         with no way to ignore such failures.
+ * @run main/othervm -Xms16m -Xmx16m -esa SoftKeys
  */
 import java.util.*;
 
--- a/test/jdk/javax/net/ssl/SSLSession/SessionTimeOutTests.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/javax/net/ssl/SSLSession/SessionTimeOutTests.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -283,7 +283,7 @@
             }
             System.out.print(sess + "      " + lifetime);
             if (((timeout == 0) || (lifetime < timeout)) &&
-                                  (isTimedout == "YES")) {
+                                  (isTimedout.equals("YES"))) {
                 isTimedout = "Invalidated before timeout";
             }
 
--- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java	Mon Jul 08 16:04:25 2019 +0530
@@ -131,10 +131,7 @@
      * Create an instance of SSLContext for client use.
      */
     protected SSLContext createClientSSLContext() throws Exception {
-        return createSSLContext(trustedCertStrs,
-                endEntityCertStrs, endEntityPrivateKeys,
-                endEntityPrivateKeyAlgs,
-                endEntityPrivateKeyNames,
+        return createSSLContext(TRUSTED_CERTS, END_ENTITY_CERTS,
                 getClientContextParameters());
     }
 
@@ -142,10 +139,7 @@
      * Create an instance of SSLContext for server use.
      */
     protected SSLContext createServerSSLContext() throws Exception {
-        return createSSLContext(trustedCertStrs,
-                endEntityCertStrs, endEntityPrivateKeys,
-                endEntityPrivateKeyAlgs,
-                endEntityPrivateKeyNames,
+        return createSSLContext(TRUSTED_CERTS, END_ENTITY_CERTS,
                 getServerContextParameters());
     }
 
@@ -362,330 +356,24 @@
      * Certificates and keys used in the test.
      */
     // Trusted certificates.
-    private final static String[] trustedCertStrs = {
-        // SHA256withECDSA, curve prime256v1
-        // Validity
-        //     Not Before: May 22 07:18:16 2018 GMT
-        //     Not After : May 17 07:18:16 2038 GMT
-        // Subject Key Identifier:
-        //     60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +
-        "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
-        "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" +
-        "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" +
-        "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" +
-        "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" +
-        "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" +
-        "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" +
-        "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" +
-        "2YEHlSQUAbwwqCDEVB5KxaqP\n" +
-        "-----END CERTIFICATE-----",
-        // -----BEGIN PRIVATE KEY-----
-        // MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd
-        // XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd
-        // LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp
-        // -----END PRIVATE KEY-----
-
-        // SHA256withRSA, 2048 bits
-        // Validity
-        //     Not Before: May 22 07:18:16 2018 GMT
-        //     Not After : May 17 07:18:16 2038 GMT
-        // Subject Key Identifier:
-        //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
-        "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
-        "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" +
-        "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
-        "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" +
-        "JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" +
-        "huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" +
-        "evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" +
-        "g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" +
-        "oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" +
-        "RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" +
-        "IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +
-        "hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" +
-        "0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" +
-        "/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" +
-        "Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" +
-        "3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" +
-        "ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" +
-        "-----END CERTIFICATE-----",
-        // -----BEGIN PRIVATE KEY-----
-        // MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD
-        // Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB
-        // emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE
-        // +X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq
-        // 7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B
-        // qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4
-        // GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9
-        // rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF
-        // JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2
-        // kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/
-        // 25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/
-        // +5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO
-        // a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS
-        // zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h
-        // De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ
-        // HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W
-        // 9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2
-        // +MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF
-        // 2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg
-        // iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S
-        // Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx
-        // HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C
-        // kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh
-        // 63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K
-        // z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH
-        // zoXBInYwRG9KE/Bw5elhUw==
-        // -----END PRIVATE KEY-----
-
-        // SHA256withDSA, 2048 bits
-        // Validity
-        //     Not Before: May 22 07:18:18 2018 GMT
-        //     Not After : May 17 07:18:18 2038 GMT
-        // Subject Key Identifier:
-        //     76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
-        "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +
-        "Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" +
-        "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" +
-        "ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" +
-        "UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" +
-        "VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" +
-        "WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" +
-        "ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" +
-        "D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" +
-        "gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" +
-        "b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" +
-        "rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" +
-        "GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" +
-        "ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" +
-        "Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" +
-        "A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" +
-        "Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" +
-        "OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" +
-        "vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" +
-        "QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" +
-        "3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" +
-        "5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" +
-        "BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" +
-        "dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" +
-        "J+g=\n" +
-        "-----END CERTIFICATE-----"
-        // -----BEGIN PRIVATE KEY-----
-        // MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O
-        // Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt
-        // l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk
-        // p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW
-        // Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f
-        // qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA
-        // tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe
-        // 5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY
-        // sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X
-        // xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0
-        // eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU
-        // tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ
-        // xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4=
-        // -----END PRIVATE KEY-----
-        };
+    protected final static Cert[] TRUSTED_CERTS = {
+            Cert.CA_ECDSA_SECP256R1,
+            Cert.CA_RSA_2048,
+            Cert.CA_DSA_2048 };
 
     // End entity certificate.
-    private final static String[] endEntityCertStrs = {
-        // SHA256withECDSA, curve prime256v1
-        // Validity
-        //     Not Before: May 22 07:18:16 2018 GMT
-        //     Not After : May 17 07:18:16 2038 GMT
-        // Authority Key Identifier:
-        //     60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +
-        "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
-        "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" +
-        "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" +
-        "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" +
-        "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" +
-        "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" +
-        "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" +
-        "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" +
-        "-----END CERTIFICATE-----",
-
-        // SHA256withRSA, 2048 bits
-        // Validity
-        //     Not Before: May 22 07:18:16 2018 GMT
-        //     Not After : May 17 07:18:16 2038 GMT
-        // Authority Key Identifier:
-        //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
-        "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
-        "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" +
-        "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
-        "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" +
-        "AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" +
-        "QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" +
-        "4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" +
-        "0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" +
-        "/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" +
-        "cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" +
-        "gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" +
-        "Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" +
-        "GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" +
-        "Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" +
-        "2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" +
-        "92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" +
-        "e57NnbT7KM+Grw==\n" +
-        "-----END CERTIFICATE-----",
-
-        // SHA256withRSA, curv prime256v1
-        // Validity
-        //     Not Before: May 22 07:18:16 2018 GMT
-        //     Not After : May 21 07:18:16 2028 GMT
-        // Authority Key Identifier:
-        //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
-        "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
-        "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" +
-        "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
-        "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
-        "AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" +
-        "yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" +
-        "6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" +
-        "I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" +
-        "+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" +
-        "hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" +
-        "ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" +
-        "xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" +
-        "-----END CERTIFICATE-----",
-
-        // SHA256withDSA, 2048 bits
-        // Validity
-        //     Not Before: May 22 07:18:20 2018 GMT
-        //     Not After : May 17 07:18:20 2038 GMT
-        // Authority Key Identifier:
-        //     76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53
-        "-----BEGIN CERTIFICATE-----\n" +
-        "MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
-        "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +
-        "Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" +
-        "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" +
-        "GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" +
-        "AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" +
-        "ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" +
-        "QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" +
-        "sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" +
-        "7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" +
-        "fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" +
-        "jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" +
-        "X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" +
-        "zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" +
-        "ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" +
-        "XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" +
-        "hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" +
-        "bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" +
-        "Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" +
-        "SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" +
-        "1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" +
-        "fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" +
-        "W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" +
-        "AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" +
-        "JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" +
-        "-----END CERTIFICATE-----"
-        };
-
-    // Private key in the format of PKCS#8.
-    private final static String[] endEntityPrivateKeys = {
-        //
-        // EC private key related to cert endEntityCertStrs[0].
-        //
-        "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" +
-        "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" +
-        "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6",
-
-        //
-        // RSA private key related to cert endEntityCertStrs[1].
-        //
-        "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" +
-        "ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" +
-        "WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" +
-        "2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" +
-        "cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" +
-        "OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" +
-        "2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" +
-        "JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" +
-        "ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" +
-        "l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" +
-        "46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" +
-        "+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" +
-        "DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" +
-        "wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" +
-        "JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" +
-        "NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" +
-        "nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" +
-        "6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" +
-        "rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" +
-        "7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" +
-        "Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" +
-        "NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" +
-        "ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" +
-        "qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" +
-        "5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" +
-        "qAL3go42DYeYhu/WnECMeis=",
-
-        //
-        // EC private key related to cert endEntityCertStrs[2].
-        //
-        "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" +
-        "nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" +
-        "P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT",
-
-        //
-        // DSA private key related to cert endEntityCertStrs[3].
-        //
-        "MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" +
-        "SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" +
-        "e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" +
-        "UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" +
-        "vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" +
-        "QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" +
-        "mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" +
-        "Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" +
-        "j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" +
-        "mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" +
-        "gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" +
-        "5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" +
-        "TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw="
-        };
-
-    // Private key algorithm of endEntityPrivateKeys.
-    private final static String[] endEntityPrivateKeyAlgs = {
-        "EC",
-        "RSA",
-        "EC",
-        "DSA",
-        };
-
-    // Private key names of endEntityPrivateKeys.
-    private final static String[] endEntityPrivateKeyNames = {
-        "ecdsa",
-        "rsa",
-        "ec-rsa",
-        "dsa",
-        };
+    protected final static Cert[] END_ENTITY_CERTS = {
+            Cert.EE_ECDSA_SECP256R1,
+            Cert.EE_RSA_2048,
+            Cert.EE_EC_RSA_SECP256R1,
+            Cert.EE_DSA_2048 };
 
     /*
      * Create an instance of SSLContext with the specified trust/key materials.
      */
-    private SSLContext createSSLContext(
-            String[] trustedMaterials,
-            String[] keyMaterialCerts,
-            String[] keyMaterialKeys,
-            String[] keyMaterialKeyAlgs,
-            String[] keyMaterialKeyNames,
+    public static SSLContext createSSLContext(
+            Cert[] trustedCerts,
+            Cert[] endEntityCerts,
             ContextParameters params) throws Exception {
 
         KeyStore ts = null;     // trust store
@@ -697,51 +385,41 @@
 
         // Import the trused certs.
         ByteArrayInputStream is;
-        if (trustedMaterials != null && trustedMaterials.length != 0) {
+        if (trustedCerts != null && trustedCerts.length != 0) {
             ts = KeyStore.getInstance("JKS");
             ts.load(null, null);
 
-            Certificate[] trustedCert =
-                    new Certificate[trustedMaterials.length];
-            for (int i = 0; i < trustedMaterials.length; i++) {
-                String trustedCertStr = trustedMaterials[i];
-
-                is = new ByteArrayInputStream(trustedCertStr.getBytes());
+            Certificate[] trustedCert = new Certificate[trustedCerts.length];
+            for (int i = 0; i < trustedCerts.length; i++) {
+                is = new ByteArrayInputStream(trustedCerts[i].certStr.getBytes());
                 try {
                     trustedCert[i] = cf.generateCertificate(is);
                 } finally {
                     is.close();
                 }
 
-                ts.setCertificateEntry("trusted-cert-" + i, trustedCert[i]);
+                ts.setCertificateEntry(
+                        "trusted-cert-" + trustedCerts[i].name(), trustedCert[i]);
             }
         }
 
         // Import the key materials.
-        //
-        // Note that certification pathes bigger than one are not supported yet.
-        boolean hasKeyMaterials =
-            (keyMaterialCerts != null) && (keyMaterialCerts.length != 0) &&
-            (keyMaterialKeys != null) && (keyMaterialKeys.length != 0) &&
-            (keyMaterialKeyAlgs != null) && (keyMaterialKeyAlgs.length != 0) &&
-            (keyMaterialCerts.length == keyMaterialKeys.length) &&
-            (keyMaterialCerts.length == keyMaterialKeyAlgs.length);
-        if (hasKeyMaterials) {
+        if (endEntityCerts != null && endEntityCerts.length != 0) {
             ks = KeyStore.getInstance("JKS");
             ks.load(null, null);
 
-            for (int i = 0; i < keyMaterialCerts.length; i++) {
-                String keyCertStr = keyMaterialCerts[i];
-
+            for (int i = 0; i < endEntityCerts.length; i++) {
                 // generate the private key.
                 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
-                    Base64.getMimeDecoder().decode(keyMaterialKeys[i]));
+                    Base64.getMimeDecoder().decode(endEntityCerts[i].privKeyStr));
                 KeyFactory kf =
-                    KeyFactory.getInstance(keyMaterialKeyAlgs[i]);
+                    KeyFactory.getInstance(
+                            endEntityCerts[i].keyAlgo);
                 PrivateKey priKey = kf.generatePrivate(priKeySpec);
 
                 // generate certificate chain
-                is = new ByteArrayInputStream(keyCertStr.getBytes());
+                is = new ByteArrayInputStream(
+                        endEntityCerts[i].certStr.getBytes());
                 Certificate keyCert = null;
                 try {
                     keyCert = cf.generateCertificate(is);
@@ -752,7 +430,7 @@
                 Certificate[] chain = new Certificate[] { keyCert };
 
                 // import the key entry.
-                ks.setKeyEntry("cert-" + keyMaterialKeyNames[i],
+                ks.setKeyEntry("cert-" + endEntityCerts[i].name(),
                         priKey, passphrase, chain);
             }
         }
@@ -763,7 +441,7 @@
         tmf.init(ts);
 
         SSLContext context = SSLContext.getInstance(params.contextProtocol);
-        if (hasKeyMaterials && ks != null) {
+        if (endEntityCerts != null && endEntityCerts.length != 0 && ks != null) {
             KeyManagerFactory kmf =
                     KeyManagerFactory.getInstance(params.kmAlgorithm);
             kmf.init(ks, passphrase);
@@ -928,4 +606,413 @@
         System.out.println(prefix + ": " + cause);
         cause.printStackTrace(System.out);
     }
+
+    public static enum Cert {
+
+        CA_ECDSA_SECP256R1(
+                "EC",
+                // SHA256withECDSA, curve secp256r1
+                // Validity
+                //     Not Before: May 22 07:18:16 2018 GMT
+                //     Not After : May 17 07:18:16 2038 GMT
+                // Subject Key Identifier:
+                //     60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +
+                "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
+                "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" +
+                "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" +
+                "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" +
+                "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" +
+                "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" +
+                "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" +
+                "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" +
+                "2YEHlSQUAbwwqCDEVB5KxaqP\n" +
+                "-----END CERTIFICATE-----",
+                "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd\n" +
+                "XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd\n" +
+                "LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp"),
+
+        CA_ECDSA_SECP384R1(
+                "EC",
+                // SHA384withECDSA, curve secp384r1
+                // Validity
+                //     Not Before: Jun 24 08:15:06 2019 GMT
+                //     Not After : Jun 19 08:15:06 2039 GMT
+                // Subject Key Identifier:
+                //     0a:93:a9:a0:bf:e7:d5:48:9d:4f:89:15:c6:51:98:80:05:51:4e:4e
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIICCDCCAY6gAwIBAgIUCpOpoL/n1UidT4kVxlGYgAVRTk4wCgYIKoZIzj0EAwMw\n" +
+                "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" +
+                "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" +
+                "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" +
+                "dCBTZXJpdmNlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENVQN1wXWFdgC6u/dDdiC\n" +
+                "y+WtMTF66oL/0BSm+1ZqsogamzCryawOcHgiuXgWzx5CQ3LuOC+tDFyXpGfHuCvb\n" +
+                "dkzxPrP5n9NrR8/uRPe5l1KOUbchviU8z9cTP+LZxnZDo1MwUTAdBgNVHQ4EFgQU\n" +
+                "SktSFArR1p/5mXV0kyo0RxIVa/UwHwYDVR0jBBgwFoAUSktSFArR1p/5mXV0kyo0\n" +
+                "RxIVa/UwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjBZvoNmq3/v\n" +
+                "RD2gBTyvxjS9h0rsMRLHDnvul/KWngytwGPTOBo0Y8ixQXSjdKoc3rkCMQDkiNgx\n" +
+                "IDxuHedmrLQKIPnVcthTmwv7//jHiqGoKofwChMo2a1P+DQdhszmeHD/ARQ=\n" +
+                "-----END CERTIFICATE-----",
+                "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDChlbt0NF8oIKODSxn2\n" +
+                "WXCXuJm3z78LRkzYQS3Nx5NMjei5ytkFZz4qvD4XXMWlTEyhZANiAAQ1VA3XBdYV\n" +
+                "2ALq790N2ILL5a0xMXrqgv/QFKb7VmqyiBqbMKvJrA5weCK5eBbPHkJDcu44L60M\n" +
+                "XJekZ8e4K9t2TPE+s/mf02tHz+5E97mXUo5RtyG+JTzP1xM/4tnGdkM="),
+
+        CA_ECDSA_SECP521R1(
+                "EC",
+                // SHA512withECDSA, curve secp521r1
+                // Validity
+                //     Not Before: Jun 24 08:15:06 2019 GMT
+                //     Not After : Jun 19 08:15:06 2039 GMT
+                // Subject Key Identifier:
+                //     25:ca:68:76:6d:29:17:9b:71:78:45:2d:d4:c6:e4:5d:fe:25:ff:90
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIICUzCCAbSgAwIBAgIUJcpodm0pF5txeEUt1MbkXf4l/5AwCgYIKoZIzj0EAwQw\n" +
+                "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" +
+                "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" +
+                "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" +
+                "dCBTZXJpdmNlMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAmFD5VmB2MdyJ6k+E\n" +
+                "eP4JncrE65ySL07gVmFwnr8otOt3NtRAyzmviMNNXXjo5R5NqNjKP4pr92JjT0sO\n" +
+                "D65yngkBtH151Ev/fiKPLxkXL9GzfKdWHVhDX7Zg6DUydzukzZV2/dIyloAIqwlz\n" +
+                "QVKJqT7RypDufdng8hnE9YfKo6ypZiujUzBRMB0GA1UdDgQWBBRAIrxa7WqtqUCe\n" +
+                "HFuKREDC92spvTAfBgNVHSMEGDAWgBRAIrxa7WqtqUCeHFuKREDC92spvTAPBgNV\n" +
+                "HRMBAf8EBTADAQH/MAoGCCqGSM49BAMEA4GMADCBiAJCAe22iirZnODCmlpxcv57\n" +
+                "3g5BEE60C+dtYmTqR4DtFyDaTRQ5CFf4ZxvQPIbD+SXi5Cbrl6qtrZG0cjUihPkC\n" +
+                "Hi1hAkIAiEcO7nMPgQLny+GrciojfN+bZXME/dPz6KHBm/89f8Me+jawVnv6y+df\n" +
+                "2Sbafh1KV6ntWQtB4bK3MXV8Ym9Eg1I=\n" +
+                "-----END CERTIFICATE-----",
+                "MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAV8dZszV6+nLw3LeA\n" +
+                "Q+qLJLGaqyjlsQkaopCPcmoRdy1HX6AzB/YnKsPkHp/9DQN6A2JgUhFG5B0XvKSk\n" +
+                "BqNNuSGhgYkDgYYABACYUPlWYHYx3InqT4R4/gmdysTrnJIvTuBWYXCevyi063c2\n" +
+                "1EDLOa+Iw01deOjlHk2o2Mo/imv3YmNPSw4PrnKeCQG0fXnUS/9+Io8vGRcv0bN8\n" +
+                "p1YdWENftmDoNTJ3O6TNlXb90jKWgAirCXNBUompPtHKkO592eDyGcT1h8qjrKlm\n" +
+                "Kw=="),
+
+        CA_RSA_2048(
+                "RSA",
+                // SHA256withRSA, 2048 bits
+                // Validity
+                //     Not Before: May 22 07:18:16 2018 GMT
+                //     Not After : May 17 07:18:16 2038 GMT
+                // Subject Key Identifier:
+                //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
+                "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
+                "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" +
+                "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
+                "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" +
+                "JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" +
+                "huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" +
+                "evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" +
+                "g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" +
+                "oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" +
+                "RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" +
+                "IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +
+                "hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" +
+                "0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" +
+                "/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" +
+                "Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" +
+                "3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" +
+                "ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" +
+                "-----END CERTIFICATE-----",
+                "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD\n" +
+                "Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB\n" +
+                "emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE\n" +
+                "+X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq\n" +
+                "7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B\n" +
+                "qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4\n" +
+                "GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9\n" +
+                "rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF\n" +
+                "JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2\n" +
+                "kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/\n" +
+                "25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/\n" +
+                "+5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO\n" +
+                "a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS\n" +
+                "zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h\n" +
+                "De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ\n" +
+                "HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W\n" +
+                "9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2\n" +
+                "+MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF\n" +
+                "2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg\n" +
+                "iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S\n" +
+                "Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx\n" +
+                "HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C\n" +
+                "kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh\n" +
+                "63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K\n" +
+                "z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH\n" +
+                "zoXBInYwRG9KE/Bw5elhUw=="),
+
+        CA_DSA_2048(
+                "DSA",
+                // SHA256withDSA, 2048 bits
+                // Validity
+                //     Not Before: May 22 07:18:18 2018 GMT
+                //     Not After : May 17 07:18:18 2038 GMT
+                // Subject Key Identifier:
+                //     76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
+                "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+                "Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" +
+                "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" +
+                "ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" +
+                "UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" +
+                "VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" +
+                "WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" +
+                "ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" +
+                "D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" +
+                "gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" +
+                "b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" +
+                "rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" +
+                "GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" +
+                "ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" +
+                "Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" +
+                "A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" +
+                "Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" +
+                "OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" +
+                "vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" +
+                "QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" +
+                "3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" +
+                "5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" +
+                "BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" +
+                "dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" +
+                "J+g=\n" +
+                "-----END CERTIFICATE-----",
+                "MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O" +
+                "Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt" +
+                "l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk" +
+                "p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW" +
+                "Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f" +
+                "qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA" +
+                "tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe" +
+                "5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY" +
+                "sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X" +
+                "xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0" +
+                "eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU" +
+                "tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ" +
+                "xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4="),
+
+        EE_ECDSA_SECP256R1(
+                "EC",
+                // SHA256withECDSA, curve secp256r1
+                // Validity
+                //     Not Before: May 22 07:18:16 2018 GMT
+                //     Not After : May 17 07:18:16 2038 GMT
+                // Authority Key Identifier:
+                //     60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +
+                "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
+                "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" +
+                "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" +
+                "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" +
+                "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" +
+                "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" +
+                "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" +
+                "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" +
+                "-----END CERTIFICATE-----",
+                "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" +
+                "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" +
+                "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6"),
+
+        EE_ECDSA_SECP384R1(
+                "EC",
+                // SHA384withECDSA, curve secp384r1
+                // Validity
+                //     Not Before: Jun 24 08:15:06 2019 GMT
+                //     Not After : Jun 19 08:15:06 2039 GMT
+                // Authority Key Identifier:
+                //     40:2D:AA:EE:66:AA:33:27:AD:9B:5D:52:9B:60:67:6A:2B:AD:52:D2
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIICEjCCAZegAwIBAgIUS3F0AqAXWRg07CnbknJzxofyBQMwCgYIKoZIzj0EAwMw\n" +
+                "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" +
+                "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" +
+                "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" +
+                "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwdjAQBgcqhkjOPQIB\n" +
+                "BgUrgQQAIgNiAARqElz8b6T07eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/w\n" +
+                "G8ASSevpgqgpi6EzpBZaaJxE3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEj\n" +
+                "iLjYmt3O0pwpklijQjBAMB0GA1UdDgQWBBRALaruZqozJ62bXVKbYGdqK61S0jAf\n" +
+                "BgNVHSMEGDAWgBRKS1IUCtHWn/mZdXSTKjRHEhVr9TAKBggqhkjOPQQDAwNpADBm\n" +
+                "AjEArVDFKf48xijN6huVUJzKCOP0zlWB5Js+DItIkZmLQuhciPLhLIB/rChf3Y4C\n" +
+                "xuP4AjEAmfLhQRI0O3pifpYzYSVh2G7/jHNG4eO+2dvgAcU+Lh2IIj/cpLaPFSvL\n" +
+                "J8FXY9Nj\n" +
+                "-----END CERTIFICATE-----",
+                "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDASuI9EtK29APXPipkc\n" +
+                "qDA+qwlewMjv/OcjUJ77kP1Vz62oVF9iY9SRIyFIUju8wt+hZANiAARqElz8b6T0\n" +
+                "7eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/wG8ASSevpgqgpi6EzpBZaaJxE\n" +
+                "3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEjiLjYmt3O0pwpklg="),
+
+        EE_ECDSA_SECP521R1(
+                "EC",
+                // SHA512withECDSA, curve secp521r1
+                // Validity
+                //     Not Before: Jun 24 08:15:06 2019 GMT
+                //     Not After : Jun 19 08:15:06 2039 GMT
+                // Authority Key Identifier:
+                //     7B:AA:79:A4:49:DD:59:34:F0:86:6C:51:C7:30:F4:CE:C5:81:8A:28
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIICXDCCAb2gAwIBAgIUck4QTsbHNqUfPxfGPJLYbedFPdswCgYIKoZIzj0EAwQw\n" +
+                "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" +
+                "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" +
+                "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" +
+                "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwgZswEAYHKoZIzj0C\n" +
+                "AQYFK4EEACMDgYYABAGa2zDLhYQHHCLI3YBqFYJTzrnDIjzwXrxhcRTS8DYkcrjZ\n" +
+                "+Fih1YyNhix0sdjH+3EqElXAHHuVzn3n3hPOtQCWlQCICkErB34S0cvmtRkeW8Fi\n" +
+                "hrR5tvJEzEZjPSgwn81kKyhV2L70je6i7Cw884Va8bODckpgw0vTmbQb7T9dupkv\n" +
+                "1aNCMEAwHQYDVR0OBBYEFHuqeaRJ3Vk08IZsUccw9M7FgYooMB8GA1UdIwQYMBaA\n" +
+                "FEAivFrtaq2pQJ4cW4pEQML3aym9MAoGCCqGSM49BAMEA4GMADCBiAJCAb33KHdY\n" +
+                "WDbusORWoY8Euglpd5zsF15hJsk7wtpD5HST1/NWmdCx405w+TV6a9Gr4VPHeaIQ\n" +
+                "99i/+f237ALL5p6IAkIBbwwFL1vt3c/bx+niyuffQPNjly80rdC9puqAqriSiboS\n" +
+                "efhxjidJ9HLaIRCMEPyd6vAsC8mO8YvL1uCuEQLsiGM=\n" +
+                "-----END CERTIFICATE-----",
+                "MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB8C/2OX2Dt9vFszzV\n" +
+                "hcAe0CbkMlvu9uQ/L7Vz88heuIj0rUZIPGshvgIJt1hCMT8HZxYHvDa4lbUvqjFB\n" +
+                "+zafvPWhgYkDgYYABAGa2zDLhYQHHCLI3YBqFYJTzrnDIjzwXrxhcRTS8DYkcrjZ\n" +
+                "+Fih1YyNhix0sdjH+3EqElXAHHuVzn3n3hPOtQCWlQCICkErB34S0cvmtRkeW8Fi\n" +
+                "hrR5tvJEzEZjPSgwn81kKyhV2L70je6i7Cw884Va8bODckpgw0vTmbQb7T9dupkv\n" +
+                "1Q=="),
+
+        EE_RSA_2048(
+                "RSA",
+                // SHA256withRSA, 2048 bits
+                // Validity
+                //     Not Before: May 22 07:18:16 2018 GMT
+                //     Not After : May 17 07:18:16 2038 GMT
+                // Authority Key Identifier:
+                //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
+                "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
+                "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" +
+                "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
+                "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" +
+                "AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" +
+                "QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" +
+                "4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" +
+                "0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" +
+                "/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" +
+                "cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" +
+                "gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" +
+                "Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" +
+                "GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" +
+                "Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" +
+                "2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" +
+                "92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" +
+                "e57NnbT7KM+Grw==\n" +
+                "-----END CERTIFICATE-----",
+                "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" +
+                "ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" +
+                "WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" +
+                "2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" +
+                "cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" +
+                "OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" +
+                "2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" +
+                "JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" +
+                "ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" +
+                "l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" +
+                "46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" +
+                "+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" +
+                "DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" +
+                "wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" +
+                "JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" +
+                "NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" +
+                "nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" +
+                "6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" +
+                "rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" +
+                "7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" +
+                "Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" +
+                "NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" +
+                "ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" +
+                "qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" +
+                "5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" +
+                "qAL3go42DYeYhu/WnECMeis="),
+
+        EE_EC_RSA_SECP256R1(
+                "EC",
+                // SHA256withRSA, curve secp256r1
+                // Validity
+                //     Not Before: May 22 07:18:16 2018 GMT
+                //     Not After : May 21 07:18:16 2028 GMT
+                // Authority Key Identifier:
+                //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
+                "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
+                "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" +
+                "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
+                "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
+                "AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" +
+                "yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" +
+                "6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" +
+                "I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" +
+                "+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" +
+                "hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" +
+                "ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" +
+                "xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" +
+                "-----END CERTIFICATE-----",
+                "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" +
+                "nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" +
+                "P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT"),
+
+        EE_DSA_2048(
+                "DSA",
+                // SHA256withDSA, 2048 bits
+                // Validity
+                //     Not Before: May 22 07:18:20 2018 GMT
+                //     Not After : May 17 07:18:20 2038 GMT
+                // Authority Key Identifier:
+                //     76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53
+                "-----BEGIN CERTIFICATE-----\n" +
+                "MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
+                "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+                "Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" +
+                "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" +
+                "GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" +
+                "AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" +
+                "ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" +
+                "QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" +
+                "sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" +
+                "7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" +
+                "fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" +
+                "jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" +
+                "X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" +
+                "zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" +
+                "ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" +
+                "XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" +
+                "hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" +
+                "bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" +
+                "Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" +
+                "SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" +
+                "1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" +
+                "fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" +
+                "W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" +
+                "AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" +
+                "JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" +
+                "-----END CERTIFICATE-----",
+                "MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" +
+                "SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" +
+                "e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" +
+                "UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" +
+                "vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" +
+                "QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" +
+                "mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" +
+                "Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" +
+                "j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" +
+                "mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" +
+                "gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" +
+                "5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" +
+                "TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw=");
+
+        final String keyAlgo;
+        final String certStr;
+        final String privKeyStr;
+
+        Cert(String keyAlgo, String certStr, String privKeyStr) {
+            this.keyAlgo = keyAlgo;
+            this.certStr = certStr;
+            this.privKeyStr = privKeyStr;
+        }
+    }
 }
--- a/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,7 +27,7 @@
  * @summary FtpURLConnection doesn't close FTP connection when FileNotFoundException is thrown
  * @library ../www/ftptest/
  * @build FtpServer FtpCommandHandler FtpAuthHandler FtpFileSystemHandler
- * @run main FtpURLConnectionLeak
+ * @run main/othervm FtpURLConnectionLeak
  */
 import java.io.FileNotFoundException;
 import java.io.InputStream;
--- a/test/jdk/sun/net/www/http/HttpClient/RetryPost.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/http/HttpClient/RetryPost.java	Mon Jul 08 16:04:25 2019 +0530
@@ -54,23 +54,19 @@
     MyHandler httpHandler;
     ExecutorService executorService;
 
-    public static void main(String[] args) {
+    public static void main(String[] args) throws Exception {
         if (args.length == 1 && args[0].equals("noRetry"))
             shouldRetry = false;
 
         new RetryPost();
     }
 
-    public RetryPost() {
-        try {
-            startHttpServer(shouldRetry);
-            doClient();
-        } catch (IOException ioe) {
-            System.err.println(ioe);
-        }
+    public RetryPost() throws Exception {
+        startHttpServer(shouldRetry);
+        doClient();
     }
 
-    void doClient() {
+    void doClient() throws Exception {
         try {
             InetSocketAddress address = httpServer.getAddress();
             URL url = URIBuilder.newBuilder()
@@ -95,8 +91,6 @@
             else if (!shouldRetry && httpHandler.getCallCount() != 1)
                 throw new RuntimeException("Failed: Handler should have only been called once" +
                                            "It was called "+ httpHandler.getCallCount() + " times");
-        } catch (IOException e) {
-            e.printStackTrace();
         } finally {
             httpServer.stop(1);
             executorService.shutdown();
@@ -119,8 +113,8 @@
     }
 
     class MyHandler implements HttpHandler {
-        int callCount = 0;
-        boolean shouldRetry;
+        volatile int callCount = 0;
+        final boolean shouldRetry;
 
         public MyHandler(boolean shouldRetry) {
             this.shouldRetry = shouldRetry;
--- a/test/jdk/sun/net/www/protocol/http/B5017051.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/B5017051.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -25,7 +25,9 @@
  * @test
  * @bug 5017051 6360774
  * @modules jdk.httpserver
+ * @library /test/lib
  * @run main/othervm B5017051
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B5017051
  * @summary Tests CR 5017051 & 6360774
  */
 
@@ -35,6 +37,7 @@
 import com.sun.net.httpserver.*;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
+import jdk.test.lib.net.URIBuilder;
 
 /*
  * Part 1:
@@ -55,42 +58,47 @@
 
 public class B5017051
 {
-    com.sun.net.httpserver.HttpServer httpServer;
+    HttpServer httpServer;
     ExecutorService executorService;
 
-    public static void main(String[] args)
-    {
+    public static void main(String[] args) throws Exception {
         new B5017051();
     }
 
-    public B5017051()
-    {
-        try {
-            startHttpServer();
-            doClient();
-        } catch (IOException ioe) {
-            System.err.println(ioe);
-        }
+    public B5017051() throws Exception {
+        startHttpServer();
+        doClient();
     }
 
-    void doClient() {
+    void doClient() throws Exception {
         java.net.Authenticator.setDefault(new MyAuthenticator());
         CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
+        ProxySelector.setDefault(ProxySelector.of(null));
 
         try {
             InetSocketAddress address = httpServer.getAddress();
 
             // Part 1
-            URL url = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test/");
+            URL url = URIBuilder.newBuilder()
+                .scheme("http")
+                .host(address.getAddress())
+                .port(address.getPort())
+                .path("/test/")
+                .toURL();
             HttpURLConnection uc = (HttpURLConnection)url.openConnection();
             int resp = uc.getResponseCode();
             if (resp != 200)
-                throw new RuntimeException("Failed: Part 1, Response code is not 200");
+                throw new RuntimeException("Failed: Part 1, Response code is not 200: " + resp);
 
             System.out.println("Response code from Part 1 = 200 OK");
 
             // Part 2
-            URL url2 = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test2/");
+            URL url2 = URIBuilder.newBuilder()
+                .scheme("http")
+                .host(address.getAddress())
+                .port(address.getPort())
+                .path("/test2/")
+                .toURL();
 
             // can use the global CookieHandler used for the first test as the URL's are different
             CookieHandler ch = CookieHandler.getDefault();
@@ -106,15 +114,10 @@
             uc = (HttpURLConnection)url2.openConnection();
             resp = uc.getResponseCode();
             if (resp != 200)
-                throw new RuntimeException("Failed: Part 2, Response code is not 200");
+                throw new RuntimeException("Failed: Part 2, Response code is not 200: " + resp);
 
             System.out.println("Response code from Part 2 = 200 OK");
 
-
-        } catch (IOException e) {
-            e.printStackTrace();
-        } catch (URISyntaxException ue) {
-            ue.printStackTrace();
         } finally {
             httpServer.stop(1);
             executorService.shutdown();
@@ -125,7 +128,8 @@
      * Http Server
      */
     public void startHttpServer() throws IOException {
-        httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0);
 
         // create HttpServer context for Part 1.
         HttpContext ctx = httpServer.createContext("/test/", new MyHandler());
--- a/test/jdk/sun/net/www/protocol/http/B6296310.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/B6296310.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -28,6 +28,7 @@
  * @library ../../httptest/
  * @build HttpCallback TestHttpServer HttpTransaction
  * @run main/othervm B6296310
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6296310
  * @summary  REGRESSION: AppletClassLoader.getResourceAsStream() behaviour is wrong in some cases
  */
 
@@ -45,32 +46,26 @@
    static SimpleHttpTransaction httpTrans;
    static TestHttpServer server;
 
-   public static void main(String[] args)
+   public static void main(String[] args) throws Exception
    {
       ResponseCache.setDefault(new MyCacheHandler());
       startHttpServer();
-
       makeHttpCall();
    }
 
-   public static void startHttpServer() {
-      try {
-         httpTrans = new SimpleHttpTransaction();
-         server = new TestHttpServer(httpTrans, 1, 10, 0);
-      } catch (IOException e) {
-         e.printStackTrace();
-      }
+   public static void startHttpServer() throws IOException {
+     httpTrans = new SimpleHttpTransaction();
+     InetAddress loopback = InetAddress.getLoopbackAddress();
+     server = new TestHttpServer(httpTrans, 1, 10, loopback, 0);
    }
 
-   public static void makeHttpCall() {
+   public static void makeHttpCall() throws IOException {
       try {
          System.out.println("http server listen on: " + server.getLocalPort());
-         URL url = new URL("http" , InetAddress.getLocalHost().getHostAddress(),
+         URL url = new URL("http" , InetAddress.getLoopbackAddress().getHostAddress(),
                             server.getLocalPort(), "/");
-         HttpURLConnection uc = (HttpURLConnection)url.openConnection();
+         HttpURLConnection uc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
          System.out.println(uc.getResponseCode());
-      } catch (IOException e) {
-         e.printStackTrace();
       } finally {
          server.terminate();
       }
--- a/test/jdk/sun/net/www/protocol/http/B6299712.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/B6299712.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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,6 +26,7 @@
  * @bug 6299712 7150552
  * @modules jdk.httpserver
  * @run main/othervm B6299712
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6299712
  * @summary  NullPointerException in sun.net.www.protocol.http.HttpURLConnection.followRedirect
  */
 
@@ -54,13 +55,15 @@
 
     public static void main(String[] args) throws Exception {
         ResponseCache.setDefault(new DeployCacheHandler());
+        ProxySelector.setDefault(ProxySelector.of(null)); // no proxy
         startHttpServer();
 
         makeHttpCall();
     }
 
     public static void startHttpServer() throws IOException {
-        server = HttpServer.create(new InetSocketAddress(0), 0);
+        InetAddress address = InetAddress.getLocalHost();
+        server = HttpServer.create(new InetSocketAddress(address, 0), 0);
         server.createContext("/", new DefaultHandler());
         server.createContext("/redirect", new RedirectHandler());
         server.start();
--- a/test/jdk/sun/net/www/protocol/http/NoNTLM.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/NoNTLM.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
  * @modules java.base/sun.net.www
  *          java.base/sun.net.www.protocol.http:open
  * @run main/othervm NoNTLM
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true NoNTLM
  */
 
 import java.io.IOException;
@@ -155,8 +156,8 @@
         System.out.println("====================================");
         System.out.println("Expect client to choose: " + expected);
         System.out.println(reply);
-
-        try (ServerSocket ss = new ServerSocket(0)) {
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        try (ServerSocket ss = new ServerSocket(0, 0, loopback)) {
             Client.start(ss.getLocalPort());
 
             // client ---- GET ---> server
@@ -198,7 +199,8 @@
         System.out.println("Expect client to fail with 401 Unauthorized");
         System.out.println(reply);
 
-        try (ServerSocket ss = new ServerSocket(0)) {
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        try (ServerSocket ss = new ServerSocket(0, 0, loopback)) {
             Client client = new Client(ss.getLocalPort());
             Thread thr = new Thread(client);
             thr.start();
@@ -225,13 +227,14 @@
     }
 
     public static void main(String[] args) throws Exception {
+        boolean ntlmSupported = false;
         try {
             Class<?> ntlmProxyClass = Class.forName("sun.net.www.protocol.http.NTLMAuthenticationProxy", true, NoNTLM.class.getClassLoader());
             Field ntlmSupportedField = ntlmProxyClass.getDeclaredField("supported");
             ntlmSupportedField.setAccessible(true);
             if (ntlmSupportedField.getBoolean(null)) {
-                System.out.println("NTLM is supported. Nothing to do. Exiting.");
-                return;
+                System.out.println("NTLM is supported.");
+                ntlmSupported = true;
             }
         } catch (ClassNotFoundException okay) { }
 
@@ -247,15 +250,26 @@
         test("Basic");
         test("Digest");
         test("Basic", "Digest");
-        test("Basic", "NTLM");
+
+        if (ntlmSupported) {
+            System.out.println("====================================");
+            System.out.println("NTLM is supported: client would select NTLM: skipping `test(\"Basic\", \"NTLM\")`..");
+        } else {
+            test("Basic", "NTLM");
+        }
+
         test("Digest", "NTLM");
         test("Basic", "Digest", "NTLM");
 
-        // test NTLM only, this should fail with "401 Unauthorized"
-        testNTLM();
+        if (ntlmSupported) {
+            System.out.println("====================================");
+            System.out.println("NTLM is supported: client would select NTLM: skipping `testNTLM()`..");
+        } else {
+            // test NTLM only, this should fail with "401 Unauthorized"
+            testNTLM();
+        }
 
         System.out.println();
         System.out.println("TEST PASSED");
     }
 }
-
--- a/test/jdk/sun/net/www/protocol/http/UserAgent.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/UserAgent.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
  * @library /test/lib
  * @modules java.base/sun.net.www
  * @run main/othervm -Dhttp.agent=foo UserAgent
+ * @run main/othervm -Dhttp.agent=foo -Djava.net.preferIPv6Addresses=true UserAgent
  * @summary  HTTP header "User-Agent" format incorrect
  */
 
@@ -87,7 +88,9 @@
 public class UserAgent {
 
     public static void main(String[] args) throws Exception {
-        ServerSocket server = new ServerSocket (0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        ServerSocket server = new ServerSocket ();
+        server.bind(new InetSocketAddress(loopback, 0));
         Server s = new Server (server);
         s.start ();
         int port = server.getLocalPort ();
@@ -97,7 +100,7 @@
             .port(port)
             .toURL();
         System.out.println("URL: " + url);
-        URLConnection urlc = url.openConnection ();
+        URLConnection urlc = url.openConnection (Proxy.NO_PROXY);
         urlc.getInputStream ();
         s.join ();
         if (!s.succeeded()) {
--- a/test/jdk/sun/net/www/protocol/http/ZoneId.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/ZoneId.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -60,7 +60,7 @@
         out.println("Found an appropriate IPv6 address: " + address);
 
         out.println("Starting http server...");
-        HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
+        HttpServer server = HttpServer.create(new InetSocketAddress(address, 0), 0);
         CompletableFuture<Headers> headers = new CompletableFuture<>();
         server.createContext("/", createCapturingHandler(headers));
         server.start();
--- a/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -25,7 +25,9 @@
  * @test
  * @bug 4474255
  * @summary Can no longer obtain a com.sun.net.ssl.HttpsURLConnection
+ * @library /test/lib
  * @run main/othervm JavaxHTTPSConnection
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true JavaxHTTPSConnection
  *
  *     SunJSSE does not support dynamic system properties, no way to re-use
  *     system properties in samevm/agentvm mode.
@@ -36,6 +38,7 @@
 import java.net.*;
 import java.security.cert.*;
 import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
 
 /**
  * See if we can obtain a javax.net.ssl.HttpsURLConnection,
@@ -138,10 +141,13 @@
      */
     void doServerSide() throws Exception {
 
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        InetSocketAddress serverAddress = new InetSocketAddress(loopback, serverPort);
         SSLServerSocketFactory sslssf =
           (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
         SSLServerSocket sslServerSocket =
-            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+            (SSLServerSocket) sslssf.createServerSocket();
+        sslServerSocket.bind(serverAddress);
         serverPort = sslServerSocket.getLocalPort();
 
         /*
@@ -204,9 +210,14 @@
             }
 
             HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
-            URL url = new URL("https://" + "localhost:" + serverPort +
-                                    "/etc/hosts");
-            URLConnection urlc = url.openConnection();
+            URL url = URIBuilder.newBuilder()
+                .scheme("https")
+                .loopback()
+                .port(serverPort)
+                .path("/etc/hosts")
+                .toURL();
+            System.out.println("Client opening: " + url);
+            URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
 
             if (!(urlc instanceof javax.net.ssl.HttpsURLConnection)) {
                 throw new Exception("URLConnection ! instanceof " +
--- a/test/jdk/sun/security/krb5/auto/KDC.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/security/krb5/auto/KDC.java	Mon Jul 08 16:04:25 2019 +0530
@@ -1274,7 +1274,17 @@
 
             PAData[] inPAs = KDCReqDotPAData(asReq);
             List<PAData> enc_outPAs = new ArrayList<>();
-            if (inPAs == null || inPAs.length == 0) {
+
+            byte[] paEncTimestamp = null;
+            if (inPAs != null) {
+                for (PAData inPA : inPAs) {
+                    if (inPA.getType() == Krb5.PA_ENC_TIMESTAMP) {
+                        paEncTimestamp = inPA.getValue();
+                    }
+                }
+            }
+
+            if (paEncTimestamp == null) {
                 Object preauth = options.get(Option.PREAUTH_REQUIRED);
                 if (preauth == null || preauth.equals(Boolean.TRUE)) {
                     throw new KrbException(Krb5.KDC_ERR_PREAUTH_REQUIRED);
@@ -1283,7 +1293,7 @@
                 EncryptionKey pakey = null;
                 try {
                     EncryptedData data = newEncryptedData(
-                            new DerValue(inPAs[0].getValue()));
+                            new DerValue(paEncTimestamp));
                     pakey = keyForUser(body.cname, data.getEType(), false);
                     data.decrypt(pakey, KeyUsage.KU_PA_ENC_TS);
                 } catch (Exception e) {
--- a/test/jdk/sun/security/pkcs11/Signature/KeyAndParamCheckForPSS.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/security/pkcs11/Signature/KeyAndParamCheckForPSS.java	Mon Jul 08 16:04:25 2019 +0530
@@ -26,7 +26,7 @@
 
 /**
  * @test
- * @bug 8080462
+ * @bug 8080462 8226651
  * @summary Ensure that PSS key and params check are implemented properly
  *         regardless of call sequence
  * @library /test/lib ..
@@ -57,12 +57,19 @@
         }
         // NOTE: key length >= (digest length + 2) in bytes
         // otherwise, even salt length = 0 would not work
-        runTest(p, 1024, "SHA-384");
-        runTest(p, 1040, "SHA-512");
+        runTest(p, 1024, "SHA-256", "SHA-256");
+        runTest(p, 1024, "SHA-256", "SHA-384");
+        runTest(p, 1024, "SHA-256", "SHA-512");
+        runTest(p, 1024, "SHA-384", "SHA-256");
+        runTest(p, 1024, "SHA-384", "SHA-384");
+        runTest(p, 1024, "SHA-384", "SHA-512");
+        runTest(p, 1040, "SHA-512", "SHA-256");
+        runTest(p, 1040, "SHA-512", "SHA-384");
+        runTest(p, 1040, "SHA-512", "SHA-512");
     }
 
-    private void runTest(Provider p, int keySize, String hashAlg)
-            throws Exception {
+    private void runTest(Provider p, int keySize, String hashAlg,
+            String mgfHashAlg) throws Exception {
         System.out.println("Testing [" + keySize + " " + hashAlg + "]");
 
         // create a key pair with the supplied size
@@ -72,9 +79,9 @@
 
         int bigSaltLen = keySize/8 - 14;
         AlgorithmParameterSpec paramsBad = new PSSParameterSpec(hashAlg,
-            "MGF1", new MGF1ParameterSpec(hashAlg), bigSaltLen, 1);
+            "MGF1", new MGF1ParameterSpec(mgfHashAlg), bigSaltLen, 1);
         AlgorithmParameterSpec paramsGood = new PSSParameterSpec(hashAlg,
-            "MGF1", new MGF1ParameterSpec(hashAlg), 0, 1);
+            "MGF1", new MGF1ParameterSpec(mgfHashAlg), 0, 1);
 
         PrivateKey priv = kp.getPrivate();
         PublicKey pub = kp.getPublic();
--- a/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/security/pkcs11/Signature/SigInteropPSS.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,7 +27,7 @@
 
 /*
  * @test
- * @bug 8080462
+ * @bug 8080462 8226651
  * @summary testing interoperability of PSS signatures of PKCS11 provider
  *         against SunRsaSign provider
  * @library /test/lib ..
@@ -64,42 +64,31 @@
         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", p);
         kpg.initialize(3072);
         KeyPair kp = kpg.generateKeyPair();
-        boolean status;
-        try {
-            status = runTest(sigSunRsaSign, sigPkcs11, kp);
-            status &= runTest(sigPkcs11, sigSunRsaSign, kp);
-        } catch (Exception e) {
-            System.out.println("Unexpected exception: " + e);
-            e.printStackTrace(System.out);
-            status = false;
-        }
 
-        if (!status) {
-            throw new RuntimeException("One or more test failed");
-        }
+        runTest(sigSunRsaSign, sigPkcs11, kp);
+        runTest(sigPkcs11, sigSunRsaSign, kp);
+
         System.out.println("Test passed");
     }
 
-    static boolean runTest(Signature signer, Signature verifier, KeyPair kp) throws Exception {
+    static void runTest(Signature signer, Signature verifier, KeyPair kp)
+            throws Exception {
         System.out.println("\tSign using " + signer.getProvider().getName());
         System.out.println("\tVerify using " + verifier.getProvider().getName());
 
-        boolean status;
-        for (String digestAlg : DIGESTS) {
-            System.out.println("\tDigest = " + digestAlg);
-            PSSParameterSpec params = new PSSParameterSpec(digestAlg, "MGF1",
-                    new MGF1ParameterSpec(digestAlg), 0, 1);
-            try {
+        for (String hash : DIGESTS) {
+            for (String mgfHash : DIGESTS) {
+                System.out.println("\tDigest = " + hash);
+                System.out.println("\tMGF = MGF1_" + mgfHash);
+
+                PSSParameterSpec params = new PSSParameterSpec(hash, "MGF1",
+                    new MGF1ParameterSpec(mgfHash), 0, 1);
+
                 signer.setParameter(params);
                 signer.initSign(kp.getPrivate());
                 verifier.setParameter(params);
                 verifier.initVerify(kp.getPublic());
-            } catch (Exception e) {
-                System.out.println("\tERROR: unexpected ex during init" + e);
-                status = false;
-                continue;
-            }
-            try {
+
                 signer.update(MSG);
                 byte[] sigBytes = signer.sign();
                 verifier.update(MSG);
@@ -107,15 +96,9 @@
                 if (isValid) {
                     System.out.println("\tPSS Signature verified");
                 } else {
-                    System.out.println("\tERROR verifying PSS Signature");
-                    status = false;
+                    throw new RuntimeException("ERROR verifying PSS Signature");
                 }
-            } catch (Exception e) {
-                System.out.println("\tERROR: unexpected ex" + e);
-                e.printStackTrace();
-                status = false;
             }
         }
-        return true;
     }
 }
--- a/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/jdk/sun/security/pkcs11/Signature/SignatureTestPSS.java	Mon Jul 08 16:04:25 2019 +0530
@@ -27,7 +27,7 @@
 
 /**
  * @test
- * @bug 8080462
+ * @bug 8080462 8226651
  * @summary Generate a RSASSA-PSS signature and verify it using PKCS11 provider
  * @library /test/lib ..
  * @modules jdk.crypto.cryptoki
@@ -86,17 +86,19 @@
         test(DIGESTS, kpair.getPrivate(), kpair.getPublic(), data);
     }
 
-    private void test(String[] testAlgs, PrivateKey privKey,
+    private void test(String[] digestAlgs, PrivateKey privKey,
             PublicKey pubKey, byte[] data) throws RuntimeException {
         // For signature algorithm, create and verify a signature
-        for (String testAlg : testAlgs) {
-            try {
-                checkSignature(data, pubKey, privKey, testAlg);
-            } catch (NoSuchAlgorithmException | InvalidKeyException |
-                     SignatureException | NoSuchProviderException ex) {
-                throw new RuntimeException(ex);
-            } catch (InvalidAlgorithmParameterException ex2) {
-                System.out.println("Skip test due to " + ex2);
+        for (String hash : digestAlgs) {
+            for (String mgfHash : digestAlgs) {
+                try {
+                    checkSignature(data, pubKey, privKey, hash, mgfHash);
+                } catch (NoSuchAlgorithmException | InvalidKeyException |
+                         SignatureException | NoSuchProviderException ex) {
+                    throw new RuntimeException(ex);
+                } catch (InvalidAlgorithmParameterException ex2) {
+                    System.out.println("Skip test due to " + ex2);
+                }
             }
         };
     }
@@ -109,13 +111,14 @@
     }
 
     private void checkSignature(byte[] data, PublicKey pub,
-            PrivateKey priv, String mdAlg) throws NoSuchAlgorithmException,
-            InvalidKeyException, SignatureException, NoSuchProviderException,
+            PrivateKey priv, String hash, String mgfHash)
+            throws NoSuchAlgorithmException, InvalidKeyException,
+            SignatureException, NoSuchProviderException,
             InvalidAlgorithmParameterException {
-        System.out.println("Testing against " + mdAlg);
+        System.out.println("Testing against " + hash + " and MGF1_" + mgfHash);
         Signature sig = Signature.getInstance(SIGALG, prov);
         AlgorithmParameterSpec params = new PSSParameterSpec(
-            mdAlg, "MGF1", new MGF1ParameterSpec(mdAlg), 0, 1);
+            hash, "MGF1", new MGF1ParameterSpec(mgfHash), 0, 1);
         sig.setParameter(params);
         sig.initSign(priv);
         for (int i = 0; i < UPDATE_TIMES_HUNDRED; i++) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/NamedGroupsWithCipherSuite.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2019, 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 javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+
+/*
+  * @test
+  * @bug 8224650
+  * @library /javax/net/ssl/templates
+  *          /javax/net/ssl/TLSCommon
+  * @summary Test TLS ciphersuite with each individual supported group
+  * @run main/othervm NamedGroupsWithCipherSuite x25519
+  * @run main/othervm NamedGroupsWithCipherSuite x448
+  * @run main/othervm NamedGroupsWithCipherSuite secp256r1
+  * @run main/othervm NamedGroupsWithCipherSuite secp384r1
+  * @run main/othervm NamedGroupsWithCipherSuite secp521r1
+  * @run main/othervm NamedGroupsWithCipherSuite ffdhe2048
+  * @run main/othervm NamedGroupsWithCipherSuite ffdhe3072
+  * @run main/othervm NamedGroupsWithCipherSuite ffdhe4096
+  * @run main/othervm NamedGroupsWithCipherSuite ffdhe6144
+  * @run main/othervm NamedGroupsWithCipherSuite ffdhe8192
+ */
+public class NamedGroupsWithCipherSuite extends SSLSocketTemplate {
+
+    private static final Protocol[] PROTOCOLS = new Protocol[] {
+            Protocol.TLSV1_3,
+            Protocol.TLSV1_2,
+            Protocol.TLSV1_1,
+            Protocol.TLSV1
+    };
+
+    private static final CipherSuite[] CIPHER_SUITES = new CipherSuite[] {
+            CipherSuite.TLS_AES_128_GCM_SHA256,
+            CipherSuite.TLS_AES_256_GCM_SHA384,
+            CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
+
+            CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+            CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+            CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+            CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+
+            CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+            CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+            CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+            CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+
+            CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+            CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+
+            CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+            CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+            CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+    };
+
+    private String protocol;
+    private String cipher;
+
+    private SSLSocketTemplate.Cert[] trustedCerts = TRUSTED_CERTS;
+    private SSLSocketTemplate.Cert[] endEntityCerts = END_ENTITY_CERTS;
+
+    NamedGroupsWithCipherSuite(
+            String protocol,
+            String cipher,
+            String namedGroup) {
+        this.protocol = protocol;
+        this.cipher = cipher;
+
+        if (cipher.startsWith("TLS_ECDHE_ECDSA")) {
+            switch (namedGroup) {
+            case "secp256r1":
+                trustedCerts = new SSLSocketTemplate.Cert[] {
+                        SSLSocketTemplate.Cert.CA_ECDSA_SECP256R1 };
+                endEntityCerts = new SSLSocketTemplate.Cert[] {
+                        SSLSocketTemplate.Cert.EE_ECDSA_SECP256R1 };
+                break;
+            case "secp384r1":
+                trustedCerts = new SSLSocketTemplate.Cert[] {
+                        SSLSocketTemplate.Cert.CA_ECDSA_SECP384R1 };
+                endEntityCerts = new SSLSocketTemplate.Cert[] {
+                        SSLSocketTemplate.Cert.EE_ECDSA_SECP384R1 };
+                break;
+            case "secp521r1":
+                trustedCerts = new SSLSocketTemplate.Cert[] {
+                        SSLSocketTemplate.Cert.CA_ECDSA_SECP521R1 };
+                endEntityCerts = new SSLSocketTemplate.Cert[] {
+                        SSLSocketTemplate.Cert.EE_ECDSA_SECP521R1 };
+            }
+        }
+    }
+
+    protected SSLContext createClientSSLContext() throws Exception {
+        return createSSLContext(trustedCerts, endEntityCerts,
+                getClientContextParameters());
+    }
+
+    protected SSLContext createServerSSLContext() throws Exception {
+        return createSSLContext(trustedCerts, endEntityCerts,
+                getServerContextParameters());
+    }
+
+    // Servers are configured before clients, increment test case after.
+    @Override
+    protected void configureClientSocket(SSLSocket socket) {
+        socket.setEnabledProtocols(new String[] { protocol });
+        socket.setEnabledCipherSuites(new String[] { cipher });
+    }
+
+    @Override
+    protected void configureServerSocket(SSLServerSocket serverSocket) {
+        serverSocket.setEnabledProtocols(new String[] { protocol });
+        serverSocket.setEnabledCipherSuites(new String[] { cipher });
+    }
+
+    public static void main(String[] args) throws Exception {
+        String namedGroup = args[0];
+
+        System.setProperty("jdk.tls.namedGroups", namedGroup);
+        System.out.println("NamedGroup: " + namedGroup);
+
+        for (Protocol protocol : PROTOCOLS) {
+            for (CipherSuite cipherSuite : CIPHER_SUITES) {
+                if (cipherSuite.supportedByProtocol(protocol)
+                        && groupSupportdByCipher(namedGroup, cipherSuite)) {
+                    System.out.printf("Protocol: %s, cipher suite: %s%n",
+                            protocol, cipherSuite);
+
+                    new NamedGroupsWithCipherSuite(protocol.name,
+                            cipherSuite.name(), namedGroup).run();
+                }
+            }
+        }
+    }
+
+    private static boolean groupSupportdByCipher(String group,
+            CipherSuite cipherSuite) {
+        return (group.startsWith("x")
+                        && xdhGroupSupportdByCipher(cipherSuite))
+                || (group.startsWith("secp")
+                        && ecdhGroupSupportdByCipher(cipherSuite))
+                || (group.startsWith("ffdhe")
+                        && ffdhGroupSupportdByCipher(cipherSuite));
+    }
+
+    private static boolean xdhGroupSupportdByCipher(
+            CipherSuite cipherSuite) {
+        return cipherSuite.keyExAlgorithm == null
+                || cipherSuite.keyExAlgorithm == KeyExAlgorithm.ECDHE_RSA;
+    }
+
+    private static boolean ecdhGroupSupportdByCipher(
+            CipherSuite cipherSuite) {
+        return cipherSuite.keyExAlgorithm == null
+                || cipherSuite.keyExAlgorithm == KeyExAlgorithm.ECDHE_RSA
+                || cipherSuite.keyExAlgorithm == KeyExAlgorithm.ECDHE_ECDSA;
+    }
+
+    private static boolean ffdhGroupSupportdByCipher(
+            CipherSuite cipherSuite) {
+        return cipherSuite.keyExAlgorithm == null
+                || cipherSuite.keyExAlgorithm == KeyExAlgorithm.DHE_DSS
+                || cipherSuite.keyExAlgorithm == KeyExAlgorithm.DHE_RSA;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/util/locale/provider/CalendarDataRegression.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, 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 8226876
+ * @summary Test CalendarDataUtility class not throwing AssertionError
+ * @run main/othervm -ea -esa -Djava.locale.providers=HOST CalendarDataRegression
+ */
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+public class CalendarDataRegression {
+    public static void main(String[] args) {
+        // Host locale provider on Windows returns 0 for
+        // firstDayOfWeek/minimalDaysInFirstWeek, which should
+        // default to non-zero value. Otherwise AssertionError
+        // will be thrown.
+        DateFormat.getDateInstance(DateFormat.FULL, Locale.US);
+    }
+}
--- a/test/langtools/tools/javac/diags/examples/BreakOutsideSwitchExpression.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/diags/examples/BreakOutsideSwitchExpression.java	Mon Jul 08 16:04:25 2019 +0530
@@ -30,7 +30,8 @@
     int t(int i) {
         OUT: while (true) {
             return switch (i) {
-                default: break OUT;
+                case 0: break OUT;
+                default: yield 0;
             };
         }
         return -1;
--- a/test/langtools/tools/javac/diags/examples/ContinueOutsideSwitchExpression.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/diags/examples/ContinueOutsideSwitchExpression.java	Mon Jul 08 16:04:25 2019 +0530
@@ -30,7 +30,8 @@
     int t(int i) {
         OUT: while (true) {
             return switch (i) {
-                default: continue OUT;
+                case 0: continue OUT;
+                default: yield 0;
             };
         }
     }
--- a/test/langtools/tools/javac/diags/examples/ReturnOutsideSwitchExpression.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/diags/examples/ReturnOutsideSwitchExpression.java	Mon Jul 08 16:04:25 2019 +0530
@@ -29,7 +29,8 @@
 class ReturnOutsideSwitchExpression {
     int t(int i) {
         return switch (i) {
-            default: return -1;
+            case 0: return -1;
+            default: yield 0;
         };
     }
 }
--- a/test/langtools/tools/javac/diags/examples/RuleCompletesNormally.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/diags/examples/RuleCompletesNormally.java	Mon Jul 08 16:04:25 2019 +0530
@@ -29,7 +29,8 @@
 class RuleCompletesNormally {
     public String convert(int i) {
         return switch (i) {
-            default -> {}
+            case 0 -> {}
+            default -> "";
         };
     }
 }
--- a/test/langtools/tools/javac/diags/examples/SwitchExpressionCompletesNormally.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/diags/examples/SwitchExpressionCompletesNormally.java	Mon Jul 08 16:04:25 2019 +0530
@@ -29,6 +29,7 @@
 class SwitchExpressionCompletesNormally {
     public String convert(int i) {
         return switch (i) {
+            case 0: yield "";
             default:
         };
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SwitchExpressionNoResultExpressions.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+// key: compiler.err.switch.expression.no.result.expressions
+// key: compiler.note.preview.filename
+// key: compiler.note.preview.recompile
+// options: --enable-preview -source ${jdk.version}
+
+class SwitchExpressionCompletesNormally {
+    public String convert(int i) {
+        return switch (i) {
+            default -> throw new AssertionError();
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/recovery/LocalVarHiding.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2019, 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 8227010
+ * @summary Verify error recovery after variable redeclaration
+ * @compile/fail/ref=LocalVarHiding.out -XDrawDiagnostics LocalVarHiding.java
+ */
+
+public class LocalVarHiding {
+    public void test(Decl l1) {
+        System.err.println(l1.originalMethod());
+
+        OverrideVar l1 = new OverrideVar();
+
+        System.err.println(l1.overrideMethod());
+
+        Decl l2 = new Decl();
+
+        System.err.println(l2.originalMethod());
+
+        OverrideVar l2 = new OverrideVar();
+
+        System.err.println(l2.overrideMethod());
+
+        Decl l3 = new Decl();
+
+        System.err.println(l3.originalMethod());
+
+        {
+            OverrideVar l3 = new OverrideVar();
+
+            System.err.println(l3.overrideMethod());
+        }
+
+        Decl l4 = new Decl();
+
+        System.err.println(l4.originalMethod());
+
+        try {
+            throw new OverrideVar();
+        } catch (OverrideVar l4) {
+            System.err.println(l4.overrideMethod());
+        }
+
+        Decl l5 = new Decl();
+
+        System.err.println(l5.originalMethod());
+
+        try (OverrideVar l5 = null) {
+            System.err.println(l5.overrideMethod());
+        }
+
+        Decl l6 = new Decl();
+
+        System.err.println(l6.originalMethod());
+
+        I i1 = l6 -> {
+            System.err.println(l6.overrideMethod());
+        };
+        I i2 = (OverrideVar l6) -> {
+            System.err.println(l6.overrideMethod());
+        };
+    }
+
+    public class Decl {
+        public int originalMethod() {}
+    }
+
+    public class OverrideVar extends Exception implements AutoCloseable {
+        @Override public void close() throws Exception {}
+        public int overrideMethod() {}
+    }
+
+    public interface I {
+        public void run(OverrideVar ov);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/recovery/LocalVarHiding.out	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,8 @@
+LocalVarHiding.java:35:21: compiler.err.already.defined: kindname.variable, l1, kindname.method, test(LocalVarHiding.Decl)
+LocalVarHiding.java:43:21: compiler.err.already.defined: kindname.variable, l2, kindname.method, test(LocalVarHiding.Decl)
+LocalVarHiding.java:52:25: compiler.err.already.defined: kindname.variable, l3, kindname.method, test(LocalVarHiding.Decl)
+LocalVarHiding.java:63:30: compiler.err.already.defined: kindname.variable, l4, kindname.method, test(LocalVarHiding.Decl)
+LocalVarHiding.java:71:26: compiler.err.already.defined: kindname.variable, l5, kindname.method, test(LocalVarHiding.Decl)
+LocalVarHiding.java:79:16: compiler.err.already.defined: kindname.variable, l6, kindname.method, test(LocalVarHiding.Decl)
+LocalVarHiding.java:82:29: compiler.err.already.defined: kindname.variable, l6, kindname.method, test(LocalVarHiding.Decl)
+7 errors
--- a/test/langtools/tools/javac/switchexpr/EmptySwitch.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/EmptySwitch.java	Mon Jul 08 16:04:25 2019 +0530
@@ -23,15 +23,29 @@
 
 /*
  * @test
- * @bug 8206986
- * @summary Verify than an empty switch expression is rejected.
- * @compile/fail/ref=EmptySwitch.out --enable-preview -source ${jdk.version} -XDrawDiagnostics EmptySwitch.java
+ * @bug 8206986 8226510
+ * @summary Verify than a switch that does not yield a value is rejected.
+ * @compile/fail/ref=EmptySwitch.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=FLOW EmptySwitch.java
  */
 
 public class EmptySwitch {
     private void print(EmptySwitchEnum t) {
         (switch (t) {
         }).toString();
+        (switch (t) {
+            default -> throw new IllegalStateException();
+        }).toString();
+        (switch (t) {
+            default: throw new IllegalStateException();
+        }).toString();
+        (switch (0) {
+            case 0: yield "";
+            default:
+        }).toString();
+        (switch (0) {
+            case 0 -> { yield ""; }
+            default -> { }
+        }).toString();
     }
 
     enum EmptySwitchEnum {
--- a/test/langtools/tools/javac/switchexpr/EmptySwitch.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/EmptySwitch.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,4 +1,8 @@
 EmptySwitch.java:33:10: compiler.err.switch.expression.empty
+EmptySwitch.java:35:10: compiler.err.switch.expression.no.result.expressions
+EmptySwitch.java:38:10: compiler.err.switch.expression.no.result.expressions
+EmptySwitch.java:44:9: compiler.err.switch.expression.completes.normally
+EmptySwitch.java:47:26: compiler.err.rule.completes.normally
 - compiler.note.preview.filename: EmptySwitch.java
 - compiler.note.preview.recompile
-1 error
+5 errors
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchBreaks2.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchBreaks2.java	Mon Jul 08 16:04:25 2019 +0530
@@ -41,9 +41,11 @@
         }
         }
         j: print(switch (i) {
+            case 0: yield 0;
             default: break j;
         }, 0);
         j2: print(switch (i) {
+            case 0: yield 0;
             default: break j2;
         }, 0);
         return null;
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchBreaks2.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchBreaks2.out	Mon Jul 08 16:04:25 2019 +0530
@@ -5,8 +5,8 @@
 ExpressionSwitchBreaks2.java:30:29: compiler.err.undef.label: UNKNOWN
 ExpressionSwitchBreaks2.java:40:17: compiler.err.no.switch.expression
 ExpressionSwitchBreaks2.java:40:29: compiler.err.cant.resolve.location: kindname.variable, undef, , , (compiler.misc.location: kindname.class, ExpressionSwitchBreaks2, null)
-ExpressionSwitchBreaks2.java:44:22: compiler.err.break.outside.switch.expression
-ExpressionSwitchBreaks2.java:47:22: compiler.err.break.outside.switch.expression
+ExpressionSwitchBreaks2.java:45:22: compiler.err.break.outside.switch.expression
+ExpressionSwitchBreaks2.java:49:22: compiler.err.break.outside.switch.expression
 - compiler.note.preview.filename: ExpressionSwitchBreaks2.java
 - compiler.note.preview.recompile
-9 errors
+9 errors
\ No newline at end of file
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchFlow.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchFlow.java	Mon Jul 08 16:04:25 2019 +0530
@@ -22,6 +22,7 @@
     private String test3(int i) {
         return switch (i) {
             case 0 -> {}
+            case 1 -> "";
             default -> throw new IllegalStateException();
         };
     }
@@ -40,17 +41,20 @@
     private String test6(int i) {
         return switch (i) {
             case 0 -> throw new IllegalStateException();
+            case 1 -> "";
             default -> {}
         };
     }
     private String test7(int i) {
         return switch (i) {
             case 0: throw new IllegalStateException();
+            case 1: yield "";
             default:
         };
     }
     private String test8(int i) {
         return switch (i) {
+            case 1: yield "";
             case 0: i++;
             default: {
             }
@@ -58,6 +62,7 @@
     }
     private String test9(int i) {
         return switch (i) {
+            case 1: yield "";
             case 0:
             default:
                 System.err.println();
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitchFlow.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchFlow.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,12 +1,12 @@
 ExpressionSwitchFlow.java:11:24: compiler.err.rule.completes.normally
 ExpressionSwitchFlow.java:18:13: compiler.err.rule.completes.normally
 ExpressionSwitchFlow.java:24:24: compiler.err.rule.completes.normally
-ExpressionSwitchFlow.java:31:25: compiler.err.rule.completes.normally
-ExpressionSwitchFlow.java:37:25: compiler.err.rule.completes.normally
-ExpressionSwitchFlow.java:43:25: compiler.err.rule.completes.normally
-ExpressionSwitchFlow.java:50:9: compiler.err.switch.expression.completes.normally
-ExpressionSwitchFlow.java:57:9: compiler.err.switch.expression.completes.normally
-ExpressionSwitchFlow.java:64:9: compiler.err.switch.expression.completes.normally
+ExpressionSwitchFlow.java:32:25: compiler.err.rule.completes.normally
+ExpressionSwitchFlow.java:38:25: compiler.err.rule.completes.normally
+ExpressionSwitchFlow.java:45:25: compiler.err.rule.completes.normally
+ExpressionSwitchFlow.java:53:9: compiler.err.switch.expression.completes.normally
+ExpressionSwitchFlow.java:61:9: compiler.err.switch.expression.completes.normally
+ExpressionSwitchFlow.java:69:9: compiler.err.switch.expression.completes.normally
 - compiler.note.preview.filename: ExpressionSwitchFlow.java
 - compiler.note.preview.recompile
 9 errors
--- a/test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8223305
+ * @bug 8223305 8226522
  * @summary Verify correct warnings w.r.t. yield
  * @compile/ref=WarnWrongYieldTest.out -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=ATTR WarnWrongYieldTest.java
  */
@@ -159,4 +159,12 @@
         //OK - yield is a variable:
         yield[0] = 5;
     }
+
+    private void lambda() {
+        SAM s = (yield y) -> {};
+    }
+
+    interface SAM {
+        public void m(yield o);
+    }
 }
--- a/test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.out	Mon Jul 08 16:04:25 2019 +0530
@@ -11,8 +11,11 @@
 WarnWrongYieldTest.java:118:9: compiler.warn.invalid.yield
 WarnWrongYieldTest.java:123:22: compiler.warn.invalid.yield
 WarnWrongYieldTest.java:152:24: compiler.warn.invalid.yield
+WarnWrongYieldTest.java:164:18: compiler.warn.restricted.type.not.allowed.preview: yield, 13
+WarnWrongYieldTest.java:168:23: compiler.warn.restricted.type.not.allowed.preview: yield, 13
 WarnWrongYieldTest.java:34:28: compiler.warn.illegal.ref.to.restricted.type: yield
 WarnWrongYieldTest.java:45:5: compiler.warn.illegal.ref.to.restricted.type: yield
+WarnWrongYieldTest.java:168:23: compiler.warn.illegal.ref.to.restricted.type: yield
 WarnWrongYieldTest.java:72:9: compiler.warn.illegal.ref.to.restricted.type: yield
 WarnWrongYieldTest.java:75:9: compiler.warn.illegal.ref.to.restricted.type: yield
 WarnWrongYieldTest.java:75:24: compiler.warn.illegal.ref.to.restricted.type: yield
@@ -22,4 +25,5 @@
 WarnWrongYieldTest.java:84:27: compiler.warn.illegal.ref.to.restricted.type: yield
 WarnWrongYieldTest.java:84:43: compiler.warn.illegal.ref.to.restricted.type: yield
 WarnWrongYieldTest.java:153:24: compiler.warn.illegal.ref.to.restricted.type: yield
-24 warnings
+WarnWrongYieldTest.java:164:18: compiler.warn.illegal.ref.to.restricted.type: yield
+28 warnings
\ No newline at end of file
--- a/test/langtools/tools/javac/switchexpr/WrongBreakTest.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/WrongBreakTest.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,8 +1,9 @@
 WrongBreakTest.java:36:41: compiler.err.illegal.start.of.expr
 WrongBreakTest.java:35:39: compiler.err.break.outside.switch.expression
+WrongBreakTest.java:35:17: compiler.err.switch.expression.no.result.expressions
 WrongBreakTest.java:36:9: compiler.err.ref.ambiguous: test, kindname.method, test(int), WrongBreakTest, kindname.method, test(java.lang.Object), WrongBreakTest
 WrongBreakTest.java:38:13: compiler.err.no.switch.expression
 WrongBreakTest.java:41:13: compiler.err.no.switch.expression
 - compiler.note.preview.filename: WrongBreakTest.java
 - compiler.note.preview.recompile
-5 errors
+6 errors
--- a/test/langtools/tools/javac/switchexpr/WrongYieldTest.java	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/WrongYieldTest.java	Mon Jul 08 16:04:25 2019 +0530
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8223305
+ * @bug 8223305 8226522
  * @summary Ensure proper errors are returned for yields.
  * @compile/fail/ref=WrongYieldTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=ATTR WrongYieldTest.java
  */
@@ -222,4 +222,12 @@
         //OK - yield is a variable:
         yield[0] = 5;
     }
+
+    private void lambda() {
+        SAM s = (yield y) -> {};
+    }
+
+    interface SAM {
+        public void m(Object o);
+    }
 }
--- a/test/langtools/tools/javac/switchexpr/WrongYieldTest.out	Fri Jun 28 15:22:18 2019 +0530
+++ b/test/langtools/tools/javac/switchexpr/WrongYieldTest.out	Mon Jul 08 16:04:25 2019 +0530
@@ -1,11 +1,13 @@
 WrongYieldTest.java:39:11: compiler.err.restricted.type.not.allowed: yield, 13
 WrongYieldTest.java:45:5: compiler.err.restricted.type.not.allowed.here: yield
+WrongYieldTest.java:123:15: compiler.err.restricted.type.not.allowed.here: yield
 WrongYieldTest.java:136:9: compiler.err.invalid.yield
 WrongYieldTest.java:146:9: compiler.err.invalid.yield
 WrongYieldTest.java:151:9: compiler.err.invalid.yield
 WrongYieldTest.java:161:9: compiler.err.invalid.yield
 WrongYieldTest.java:166:22: compiler.err.invalid.yield
 WrongYieldTest.java:215:24: compiler.err.invalid.yield
+WrongYieldTest.java:227:18: compiler.err.restricted.type.not.allowed.here: yield
 WrongYieldTest.java:34:24: compiler.err.illegal.ref.to.restricted.type: yield
 WrongYieldTest.java:95:9: compiler.err.no.switch.expression
 WrongYieldTest.java:95:15: compiler.err.cant.resolve.location: kindname.variable, y1, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
@@ -26,4 +28,4 @@
 WrongYieldTest.java:216:24: compiler.err.illegal.ref.to.restricted.type: yield
 - compiler.note.preview.filename: WrongYieldTest.java
 - compiler.note.preview.recompile
-26 errors
+28 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/java/net/NetworkInterfaceLookup.java	Mon Jul 08 16:04:25 2019 +0530
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package org.openjdk.bench.java.net;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Assess time to perform native NetworkInterface lookups; uses
+ * reflection to access both package-private isBoundInetAddress and
+ * public getByInetAddress (to get comparable numbers)
+ */
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.SECONDS)
+@State(Scope.Thread)
+@Fork(2)
+@Warmup(iterations = 5, time = 2)
+@Measurement(iterations = 10, time = 2)
+public class NetworkInterfaceLookup {
+
+    static final InetAddress address = InetAddress.getLoopbackAddress();
+
+    static final Method isBoundInetAddress_method;
+
+    static final Method getByInetAddress_method;
+
+    static {
+        Method isBound = null;
+        Method getByInet = null;
+
+        try {
+            isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class);
+            isBound.setAccessible(true);
+        } catch (Exception e) {
+            System.out.println("NetworkInterface.isBoundInetAddress not found");
+        }
+
+        try {
+            getByInet = NetworkInterface.class.getDeclaredMethod("getByInetAddress", InetAddress.class);
+        } catch (Exception e) {
+            System.out.println("NetworkInterface.getByInetAddress not found");
+        }
+        isBoundInetAddress_method = isBound;
+        getByInetAddress_method = getByInet;
+    }
+
+    @Benchmark
+    public boolean bound() throws Exception {
+        return (boolean)isBoundInetAddress_method.invoke(null, address);
+    }
+
+    @Benchmark
+    public NetworkInterface getByInetAddress() throws Exception {
+        return (NetworkInterface)getByInetAddress_method.invoke(null, address);
+    }
+}