Merge JDK-8200758-branch
authorherrick
Wed, 14 Aug 2019 08:23:16 -0400
branchJDK-8200758-branch
changeset 57744 d462d0422e1d
parent 57743 8d6f0aff03fc (current diff)
parent 57739 6717d7e59db4 (diff)
child 57750 1a9e496d54d2
Merge
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -100,6 +100,9 @@
 
   if (access.is_oop()) {
     result = load_reference_barrier(access.gen(), result);
+    LIR_Opr tmp = gen->new_register(type);
+    __ move(result, tmp);
+    result = tmp;
     if (ShenandoahSATBBarrier) {
       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
                   result /* pre_val */);
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -521,23 +521,45 @@
 }
 
 void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
+  ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
 
   Register obj = stub->obj()->as_register();
   Register res = stub->result()->as_register();
+  Register tmp1 = stub->tmp1()->as_register();
+  Register tmp2 = stub->tmp2()->as_register();
 
-  Label done;
-
-  __ bind(*stub->entry());
+  assert(res == r0, "result must arrive in r0");
 
   if (res != obj) {
     __ mov(res, obj);
   }
+
   // Check for null.
-  __ cbz(res, done);
+  __ cbz(res, *stub->continuation());
+
+  // Check for object in cset.
+  __ mov(tmp2, ShenandoahHeap::in_cset_fast_test_addr());
+  __ lsr(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint());
+  __ ldrb(tmp2, Address(tmp2, tmp1));
+  __ cbz(tmp2, *stub->continuation());
 
-  load_reference_barrier_not_null(ce->masm(), res, rscratch1);
+  // Check if object is already forwarded.
+  Label slow_path;
+  __ ldr(tmp1, Address(res, oopDesc::mark_offset_in_bytes()));
+  __ eon(tmp1, tmp1, zr);
+  __ ands(zr, tmp1, markOopDesc::lock_mask_in_place);
+  __ br(Assembler::NE, slow_path);
 
-  __ bind(done);
+  // Decode forwarded object.
+  __ orr(tmp1, tmp1, markOopDesc::marked_value);
+  __ eon(res, tmp1, zr);
+  __ b(*stub->continuation());
+
+  __ bind(slow_path);
+  ce->store_parameter(res, 0);
+  __ far_call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin()));
+
   __ b(*stub->continuation());
 }
 
@@ -591,6 +613,21 @@
   __ epilogue();
 }
 
+void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("shenandoah_load_reference_barrier", false);
+  // arg0 : object to be resolved
+
+  __ push_call_clobbered_registers();
+  __ load_parameter(0, r0);
+  __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier));
+  __ blr(lr);
+  __ mov(rscratch1, r0);
+  __ pop_call_clobbered_registers();
+  __ mov(r0, rscratch1);
+
+  __ epilogue();
+}
+
 #undef __
 
 #endif // COMPILER1
@@ -625,11 +662,18 @@
   __ ret(lr);
   __ bind(work);
 
-  __ mov(rscratch2, r0);
-  resolve_forward_pointer_not_null(cgen->assembler(), r0, rscratch1);
-  __ cmp(rscratch2, r0);
-  __ br(Assembler::NE, done);
+  Label slow_path;
+  __ ldr(rscratch1, Address(r0, oopDesc::mark_offset_in_bytes()));
+  __ eon(rscratch1, rscratch1, zr);
+  __ ands(zr, rscratch1, markOopDesc::lock_mask_in_place);
+  __ br(Assembler::NE, slow_path);
 
+  // Decode forwarded object.
+  __ orr(rscratch1, rscratch1, markOopDesc::marked_value);
+  __ eon(r0, rscratch1, zr);
+  __ ret(lr);
+
+  __ bind(slow_path);
   __ enter(); // required for proper stackwalking of RuntimeStub frame
 
   __ push_call_clobbered_registers();
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -71,6 +71,7 @@
   void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
   void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
   void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm);
 #endif
 
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1248,7 +1248,8 @@
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
@@ -1274,7 +1275,7 @@
                                        (OopMapSet*)NULL);
   }
   bool is_critical_native = true;
-  address native_func = method->critical_native_function();
+  address native_func = critical_entry;
   if (native_func == NULL) {
     native_func = method->native_function();
     is_critical_native = false;
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -752,7 +752,8 @@
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1849,7 +1849,8 @@
                                                 int compile_id,
                                                 BasicType *in_sig_bt,
                                                 VMRegPair *in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
 #ifdef COMPILER2
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
@@ -1874,7 +1875,7 @@
   }
 
   bool is_critical_native = true;
-  address native_func = method->critical_native_function();
+  address native_func = critical_entry;
   if (native_func == NULL) {
     native_func = method->native_function();
     is_critical_native = false;
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1518,7 +1518,8 @@
                                                 int compile_id,
                                                 BasicType *in_sig_bt,
                                                 VMRegPair *in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
 #ifdef COMPILER2
   int total_in_args = method->size_of_parameters();
   if (method->is_method_handle_intrinsic()) {
@@ -1554,7 +1555,7 @@
   ///////////////////////////////////////////////////////////////////////
 
   bool is_critical_native = true;
-  address native_func = method->critical_native_function();
+  address native_func = critical_entry;
   if (native_func == NULL) {
     native_func = method->native_function();
     is_critical_native = false;
--- a/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1751,7 +1751,8 @@
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
@@ -1774,7 +1775,7 @@
                                        (OopMapSet*)NULL);
   }
   bool is_critical_native = true;
-  address native_func = method->critical_native_function();
+  address native_func = critical_entry;
   if (native_func == NULL) {
     native_func = method->native_function();
     is_critical_native = false;
--- a/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shenandoah/c1/shenandoahBarrierSetC1_x86.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -111,6 +111,9 @@
 
   if (access.is_oop()) {
     result = load_reference_barrier(access.gen(), result);
+    LIR_Opr tmp = gen->new_register(type);
+    __ move(result, tmp);
+    result = tmp;
     if (ShenandoahSATBBarrier) {
       pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
                   result /* pre_val */);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -752,108 +752,6 @@
   }
 }
 
-void ShenandoahBarrierSetAssembler::save_vector_registers(MacroAssembler* masm) {
-  int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
-  if (UseAVX > 2) {
-    num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
-  }
-
-  if (UseSSE == 1)  {
-    __ subptr(rsp, sizeof(jdouble)*8);
-    for (int n = 0; n < 8; n++) {
-      __ movflt(Address(rsp, n*sizeof(jdouble)), as_XMMRegister(n));
-    }
-  } else if (UseSSE >= 2)  {
-    if (UseAVX > 2) {
-      __ push(rbx);
-      __ movl(rbx, 0xffff);
-      __ kmovwl(k1, rbx);
-      __ pop(rbx);
-    }
-#ifdef COMPILER2
-    if (MaxVectorSize > 16) {
-      if(UseAVX > 2) {
-        // Save upper half of ZMM registers
-        __ subptr(rsp, 32*num_xmm_regs);
-        for (int n = 0; n < num_xmm_regs; n++) {
-          __ vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n));
-        }
-      }
-      assert(UseAVX > 0, "256 bit vectors are supported only with AVX");
-      // Save upper half of YMM registers
-      __ subptr(rsp, 16*num_xmm_regs);
-      for (int n = 0; n < num_xmm_regs; n++) {
-        __ vextractf128_high(Address(rsp, n*16), as_XMMRegister(n));
-      }
-    }
-#endif
-    // Save whole 128bit (16 bytes) XMM registers
-    __ subptr(rsp, 16*num_xmm_regs);
-#ifdef _LP64
-    if (VM_Version::supports_evex()) {
-      for (int n = 0; n < num_xmm_regs; n++) {
-        __ vextractf32x4(Address(rsp, n*16), as_XMMRegister(n), 0);
-      }
-    } else {
-      for (int n = 0; n < num_xmm_regs; n++) {
-        __ movdqu(Address(rsp, n*16), as_XMMRegister(n));
-      }
-    }
-#else
-    for (int n = 0; n < num_xmm_regs; n++) {
-      __ movdqu(Address(rsp, n*16), as_XMMRegister(n));
-    }
-#endif
-  }
-}
-
-void ShenandoahBarrierSetAssembler::restore_vector_registers(MacroAssembler* masm) {
-  int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
-  if (UseAVX > 2) {
-    num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
-  }
-  if (UseSSE == 1)  {
-    for (int n = 0; n < 8; n++) {
-      __ movflt(as_XMMRegister(n), Address(rsp, n*sizeof(jdouble)));
-    }
-    __ addptr(rsp, sizeof(jdouble)*8);
-  } else if (UseSSE >= 2)  {
-    // Restore whole 128bit (16 bytes) XMM registers
-#ifdef _LP64
-    if (VM_Version::supports_evex()) {
-      for (int n = 0; n < num_xmm_regs; n++) {
-        __ vinsertf32x4(as_XMMRegister(n), as_XMMRegister(n), Address(rsp, n*16), 0);
-      }
-    } else {
-      for (int n = 0; n < num_xmm_regs; n++) {
-        __ movdqu(as_XMMRegister(n), Address(rsp, n*16));
-      }
-    }
-#else
-    for (int n = 0; n < num_xmm_regs; n++) {
-      __ movdqu(as_XMMRegister(n), Address(rsp, n*16));
-    }
-#endif
-    __ addptr(rsp, 16*num_xmm_regs);
-
-#ifdef COMPILER2
-    if (MaxVectorSize > 16) {
-      // Restore upper half of YMM registers.
-      for (int n = 0; n < num_xmm_regs; n++) {
-        __ vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16));
-      }
-      __ addptr(rsp, 16*num_xmm_regs);
-      if (UseAVX > 2) {
-        for (int n = 0; n < num_xmm_regs; n++) {
-          __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32));
-        }
-        __ addptr(rsp, 32*num_xmm_regs);
-      }
-    }
-#endif
-  }
-}
-
 #undef __
 
 #ifdef COMPILER1
@@ -885,11 +783,17 @@
 }
 
 void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
+  ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
   __ bind(*stub->entry());
 
-  Label done;
   Register obj = stub->obj()->as_register();
   Register res = stub->result()->as_register();
+  Register tmp1 = stub->tmp1()->as_register();
+  Register tmp2 = stub->tmp2()->as_register();
+
+  Label slow_path;
+
+  assert(res == rax, "result must arrive in rax");
 
   if (res != obj) {
     __ mov(res, obj);
@@ -897,11 +801,35 @@
 
   // Check for null.
   __ testptr(res, res);
-  __ jcc(Assembler::zero, done);
+  __ jcc(Assembler::zero, *stub->continuation());
+
+  // Check for object being in the collection set.
+  __ mov(tmp1, res);
+  __ shrptr(tmp1, ShenandoahHeapRegion::region_size_bytes_shift_jint());
+  __ movptr(tmp2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr());
+  __ movbool(tmp2, Address(tmp2, tmp1, Address::times_1));
+  __ testbool(tmp2);
+  __ jcc(Assembler::zero, *stub->continuation());
 
-  load_reference_barrier_not_null(ce->masm(), res);
+  // Test if object is resolved.
+  __ movptr(tmp1, Address(res, oopDesc::mark_offset_in_bytes()));
+  // Test if both lowest bits are set. We trick it by negating the bits
+  // then test for both bits clear.
+  __ notptr(tmp1);
+  __ testb(tmp1, markOopDesc::marked_value);
+  __ jccb(Assembler::notZero, slow_path);
+  // Clear both lower bits. It's still inverted, so set them, and then invert back.
+  __ orptr(tmp1, markOopDesc::marked_value);
+  __ notptr(tmp1);
+  // At this point, tmp1 contains the decoded forwarding pointer.
+  __ mov(res, tmp1);
 
-  __ bind(done);
+  __ jmp(*stub->continuation());
+
+  __ bind(slow_path);
+  ce->store_parameter(res, 0);
+  __ call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin()));
+
   __ jmp(*stub->continuation());
 }
 
@@ -965,6 +893,18 @@
   __ epilogue();
 }
 
+void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("shenandoah_load_reference_barrier", false);
+  // arg0 : object to be resolved
+
+  __ save_live_registers_no_oop_map(true);
+  __ load_parameter(0, c_rarg0);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), c_rarg0);
+  __ restore_live_registers_except_rax(true);
+
+  __ epilogue();
+}
+
 #undef __
 
 #endif // COMPILER1
@@ -981,11 +921,11 @@
   StubCodeMark mark(cgen, "StubRoutines", "shenandoah_lrb");
   address start = __ pc();
 
-  Label resolve_oop, slow_path;
+  Label resolve_oop, slow_path, done;
 
   // We use RDI, which also serves as argument register for slow call.
-  // RAX always holds the src object ptr, except after the slow call and
-  // the cmpxchg, then it holds the result. R8/RBX is used as temporary register.
+  // RAX always holds the src object ptr, except after the slow call,
+  // then it holds the result. R8/RBX is used as temporary register.
 
   Register tmp1 = rdi;
   Register tmp2 = LP64_ONLY(r8) NOT_LP64(rbx);
@@ -994,26 +934,18 @@
   __ push(tmp2);
 
   // Check for object being in the collection set.
-  // TODO: Can we use only 1 register here?
-  // The source object arrives here in rax.
-  // live: rax
-  // live: tmp1
   __ mov(tmp1, rax);
   __ shrptr(tmp1, ShenandoahHeapRegion::region_size_bytes_shift_jint());
-  // live: tmp2
   __ movptr(tmp2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr());
   __ movbool(tmp2, Address(tmp2, tmp1, Address::times_1));
-  // unlive: tmp1
   __ testbool(tmp2);
-  // unlive: tmp2
   __ jccb(Assembler::notZero, resolve_oop);
-
   __ pop(tmp2);
   __ pop(tmp1);
   __ ret(0);
 
+  // Test if object is already resolved.
   __ bind(resolve_oop);
-
   __ movptr(tmp2, Address(rax, oopDesc::mark_offset_in_bytes()));
   // Test if both lowest bits are set. We trick it by negating the bits
   // then test for both bits clear.
@@ -1026,6 +958,7 @@
   // At this point, tmp2 contains the decoded forwarding pointer.
   __ mov(rax, tmp2);
 
+  __ bind(done);
   __ pop(tmp2);
   __ pop(tmp1);
   __ ret(0);
@@ -1047,10 +980,7 @@
   __ push(r15);
 #endif
 
-  save_vector_registers(cgen->assembler());
-  __ movptr(rdi, rax);
-  __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), rdi);
-  restore_vector_registers(cgen->assembler());
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), rax);
 
 #ifdef _LP64
   __ pop(r15);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -64,9 +64,6 @@
 
   address generate_shenandoah_lrb(StubCodeGenerator* cgen);
 
-  void save_vector_registers(MacroAssembler* masm);
-  void restore_vector_registers(MacroAssembler* masm);
-
 public:
   static address shenandoah_lrb();
 
@@ -75,6 +72,7 @@
   void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
   void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
   void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm);
 #endif
 
   void load_reference_barrier(MacroAssembler* masm, Register dst);
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1524,7 +1524,8 @@
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
@@ -1547,7 +1548,7 @@
                                        (OopMapSet*)NULL);
   }
   bool is_critical_native = true;
-  address native_func = method->critical_native_function();
+  address native_func = critical_entry;
   if (native_func == NULL) {
     native_func = method->native_function();
     is_critical_native = false;
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1924,7 +1924,8 @@
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
   if (method->is_method_handle_intrinsic()) {
     vmIntrinsics::ID iid = method->intrinsic_id();
     intptr_t start = (intptr_t)__ pc();
@@ -1947,7 +1948,7 @@
                                        (OopMapSet*)NULL);
   }
   bool is_critical_native = true;
-  address native_func = method->critical_native_function();
+  address native_func = critical_entry;
   if (native_func == NULL) {
     native_func = method->native_function();
     is_critical_native = false;
--- a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -75,7 +75,8 @@
                                                 int compile_id,
                                                 BasicType *sig_bt,
                                                 VMRegPair *regs,
-                                                BasicType ret_type) {
+                                                BasicType ret_type,
+                                                address critical_entry) {
   ShouldNotCallThis();
   return NULL;
 }
--- a/src/hotspot/os/posix/os_posix.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1695,8 +1695,8 @@
   if ((status = pthread_mutexattr_settype(_mutexAttr, PTHREAD_MUTEX_NORMAL)) != 0) {
     fatal("pthread_mutexattr_settype: %s", os::strerror(status));
   }
-  // Solaris has it's own PlatformMonitor, distinct from the one for POSIX.
-  NOT_SOLARIS(os::PlatformMonitor::init();)
+  // Solaris has it's own PlatformMutex, distinct from the one for POSIX.
+  NOT_SOLARIS(os::PlatformMutex::init();)
 }
 
 #ifndef SOLARIS
@@ -2274,33 +2274,29 @@
   }
 }
 
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementation
 
-os::PlatformMonitor::Impl::Impl() : _next(NULL) {
-  int status = pthread_cond_init(&_cond, _condAttr);
-  assert_status(status == 0, status, "cond_init");
-  status = pthread_mutex_init(&_mutex, _mutexAttr);
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+
+os::PlatformMutex::Mutex::Mutex() : _next(NULL) {
+  int status = pthread_mutex_init(&_mutex, _mutexAttr);
   assert_status(status == 0, status, "mutex_init");
 }
 
-os::PlatformMonitor::Impl::~Impl() {
-  int status = pthread_cond_destroy(&_cond);
-  assert_status(status == 0, status, "cond_destroy");
-  status = pthread_mutex_destroy(&_mutex);
+os::PlatformMutex::Mutex::~Mutex() {
+  int status = pthread_mutex_destroy(&_mutex);
   assert_status(status == 0, status, "mutex_destroy");
 }
 
-#if PLATFORM_MONITOR_IMPL_INDIRECT
+pthread_mutex_t os::PlatformMutex::_freelist_lock;
+os::PlatformMutex::Mutex* os::PlatformMutex::_mutex_freelist = NULL;
 
-pthread_mutex_t os::PlatformMonitor::_freelist_lock;
-os::PlatformMonitor::Impl* os::PlatformMonitor::_freelist = NULL;
-
-void os::PlatformMonitor::init() {
+void os::PlatformMutex::init() {
   int status = pthread_mutex_init(&_freelist_lock, _mutexAttr);
   assert_status(status == 0, status, "freelist lock init");
 }
 
-struct os::PlatformMonitor::WithFreeListLocked : public StackObj {
+struct os::PlatformMutex::WithFreeListLocked : public StackObj {
   WithFreeListLocked() {
     int status = pthread_mutex_lock(&_freelist_lock);
     assert_status(status == 0, status, "freelist lock");
@@ -2312,24 +2308,78 @@
   }
 };
 
-os::PlatformMonitor::PlatformMonitor() {
+os::PlatformMutex::PlatformMutex() {
   {
     WithFreeListLocked wfl;
-    _impl = _freelist;
+    _impl = _mutex_freelist;
     if (_impl != NULL) {
-      _freelist = _impl->_next;
+      _mutex_freelist = _impl->_next;
       _impl->_next = NULL;
       return;
     }
   }
-  _impl = new Impl();
+  _impl = new Mutex();
+}
+
+os::PlatformMutex::~PlatformMutex() {
+  WithFreeListLocked wfl;
+  assert(_impl->_next == NULL, "invariant");
+  _impl->_next = _mutex_freelist;
+  _mutex_freelist = _impl;
+}
+
+os::PlatformMonitor::Cond::Cond() : _next(NULL) {
+  int status = pthread_cond_init(&_cond, _condAttr);
+  assert_status(status == 0, status, "cond_init");
+}
+
+os::PlatformMonitor::Cond::~Cond() {
+  int status = pthread_cond_destroy(&_cond);
+  assert_status(status == 0, status, "cond_destroy");
+}
+
+os::PlatformMonitor::Cond* os::PlatformMonitor::_cond_freelist = NULL;
+
+os::PlatformMonitor::PlatformMonitor() {
+  {
+    WithFreeListLocked wfl;
+    _impl = _cond_freelist;
+    if (_impl != NULL) {
+      _cond_freelist = _impl->_next;
+      _impl->_next = NULL;
+      return;
+    }
+  }
+  _impl = new Cond();
 }
 
 os::PlatformMonitor::~PlatformMonitor() {
   WithFreeListLocked wfl;
   assert(_impl->_next == NULL, "invariant");
-  _impl->_next = _freelist;
-  _freelist = _impl;
+  _impl->_next = _cond_freelist;
+  _cond_freelist = _impl;
+}
+
+#else
+
+os::PlatformMutex::PlatformMutex() {
+  int status = pthread_mutex_init(&_mutex, _mutexAttr);
+  assert_status(status == 0, status, "mutex_init");
+}
+
+os::PlatformMutex::~PlatformMutex() {
+  int status = pthread_mutex_destroy(&_mutex);
+  assert_status(status == 0, status, "mutex_destroy");
+}
+
+os::PlatformMonitor::PlatformMonitor() {
+  int status = pthread_cond_init(&_cond, _condAttr);
+  assert_status(status == 0, status, "cond_init");
+}
+
+os::PlatformMonitor::~PlatformMonitor() {
+  int status = pthread_cond_destroy(&_cond);
+  assert_status(status == 0, status, "cond_destroy");
 }
 
 #endif // PLATFORM_MONITOR_IMPL_INDIRECT
--- a/src/hotspot/os/posix/os_posix.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -234,7 +234,7 @@
 
 // Workaround for a bug in macOSX kernel's pthread support (fixed in Mojave?).
 // Avoid ever allocating a pthread_mutex_t at the same address as one of our
-// former pthread_cond_t, by using a freelist of mutex/condvar pairs.
+// former pthread_cond_t, by using freelists of mutexes and condvars.
 // Conditional to avoid extra indirection and padding loss on other platforms.
 #ifdef __APPLE__
 #define PLATFORM_MONITOR_IMPL_INDIRECT 1
@@ -242,53 +242,98 @@
 #define PLATFORM_MONITOR_IMPL_INDIRECT 0
 #endif
 
-// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj<mtSynchronizer> {
-  class Impl : public CHeapObj<mtSynchronizer> {
-  public:
+// Platform specific implementations that underpin VM Mutex/Monitor classes
+
+class PlatformMutex : public CHeapObj<mtSynchronizer> {
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+  class Mutex : public CHeapObj<mtSynchronizer> {
+   public:
     pthread_mutex_t _mutex;
-    pthread_cond_t _cond;
-    Impl* _next;
+    Mutex* _next;
 
-    Impl();
-    ~Impl();
+    Mutex();
+    ~Mutex();
   };
 
-#if PLATFORM_MONITOR_IMPL_INDIRECT
+  Mutex* _impl;
 
-  Impl* _impl;
+  static pthread_mutex_t _freelist_lock; // used for mutex and cond freelists
+  static Mutex* _mutex_freelist;
 
+ protected:
+  class WithFreeListLocked;
   pthread_mutex_t* mutex() { return &(_impl->_mutex); }
-  pthread_cond_t* cond() { return &(_impl->_cond); }
+
+ public:
+  PlatformMutex();              // Use freelist allocation of impl.
+  ~PlatformMutex();
+
+  static void init();           // Initialize the freelist.
+
+#else
+
+  pthread_mutex_t _mutex;
+
+ protected:
+  pthread_mutex_t* mutex() { return &_mutex; }
+
+ public:
+  static void init() {}         // Nothing needed for the non-indirect case.
+
+  PlatformMutex();
+  ~PlatformMutex();
+
+#endif // PLATFORM_MONITOR_IMPL_INDIRECT
 
-  class WithFreeListLocked;
-  static pthread_mutex_t _freelist_lock;
-  static Impl* _freelist;
+private:
+  // Disable copying
+  PlatformMutex(const PlatformMutex&);
+  PlatformMutex& operator=(const PlatformMutex&);
+
+ public:
+  void lock();
+  void unlock();
+  bool try_lock();
+};
+
+class PlatformMonitor : public PlatformMutex {
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+  class Cond : public CHeapObj<mtSynchronizer> {
+   public:
+    pthread_cond_t _cond;
+    Cond* _next;
+
+    Cond();
+    ~Cond();
+  };
+
+  Cond* _impl;
+
+  static Cond* _cond_freelist;
+
+  pthread_cond_t* cond() { return &(_impl->_cond); }
 
  public:
   PlatformMonitor();            // Use freelist allocation of impl.
   ~PlatformMonitor();
 
-  static void init();           // Initialize the freelist.
-
 #else
 
-  Impl _impl;
-
-  pthread_mutex_t* mutex() { return &(_impl._mutex); }
-  pthread_cond_t* cond() { return &(_impl._cond); }
+  pthread_cond_t _cond;
+  pthread_cond_t* cond() { return &_cond; }
 
  public:
-  static void init() {}         // Nothing needed for the non-indirect case.
-
-  // Default constructor and destructor.
+  PlatformMonitor();
+  ~PlatformMonitor();
 
 #endif // PLATFORM_MONITOR_IMPL_INDIRECT
 
+ private:
+  // Disable copying
+  PlatformMonitor(const PlatformMonitor&);
+  PlatformMonitor& operator=(const PlatformMonitor&);
+
  public:
-  void lock();
-  void unlock();
-  bool try_lock();
   int wait(jlong millis);
   void notify();
   void notify_all();
--- a/src/hotspot/os/posix/os_posix.inline.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.inline.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -47,19 +47,19 @@
 
 #ifndef SOLARIS
 
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementation
 
-inline void os::PlatformMonitor::lock() {
+inline void os::PlatformMutex::lock() {
   int status = pthread_mutex_lock(mutex());
   assert_status(status == 0, status, "mutex_lock");
 }
 
-inline void os::PlatformMonitor::unlock() {
+inline void os::PlatformMutex::unlock() {
   int status = pthread_mutex_unlock(mutex());
   assert_status(status == 0, status, "mutex_unlock");
 }
 
-inline bool os::PlatformMonitor::try_lock() {
+inline bool os::PlatformMutex::try_lock() {
   int status = pthread_mutex_trylock(mutex());
   assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
   return status == 0;
--- a/src/hotspot/os/solaris/os_solaris.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -5149,36 +5149,42 @@
   }
 }
 
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementations
+
+os::PlatformMutex::PlatformMutex() {
+  int status = os::Solaris::mutex_init(&_mutex);
+  assert_status(status == 0, status, "mutex_init");
+}
+
+os::PlatformMutex::~PlatformMutex() {
+  int status = os::Solaris::mutex_destroy(&_mutex);
+  assert_status(status == 0, status, "mutex_destroy");
+}
+
+void os::PlatformMutex::lock() {
+  int status = os::Solaris::mutex_lock(&_mutex);
+  assert_status(status == 0, status, "mutex_lock");
+}
+
+void os::PlatformMutex::unlock() {
+  int status = os::Solaris::mutex_unlock(&_mutex);
+  assert_status(status == 0, status, "mutex_unlock");
+}
+
+bool os::PlatformMutex::try_lock() {
+  int status = os::Solaris::mutex_trylock(&_mutex);
+  assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
+  return status == 0;
+}
 
 os::PlatformMonitor::PlatformMonitor() {
   int status = os::Solaris::cond_init(&_cond);
   assert_status(status == 0, status, "cond_init");
-  status = os::Solaris::mutex_init(&_mutex);
-  assert_status(status == 0, status, "mutex_init");
 }
 
 os::PlatformMonitor::~PlatformMonitor() {
   int status = os::Solaris::cond_destroy(&_cond);
   assert_status(status == 0, status, "cond_destroy");
-  status = os::Solaris::mutex_destroy(&_mutex);
-  assert_status(status == 0, status, "mutex_destroy");
-}
-
-void os::PlatformMonitor::lock() {
-  int status = os::Solaris::mutex_lock(&_mutex);
-  assert_status(status == 0, status, "mutex_lock");
-}
-
-void os::PlatformMonitor::unlock() {
-  int status = os::Solaris::mutex_unlock(&_mutex);
-  assert_status(status == 0, status, "mutex_unlock");
-}
-
-bool os::PlatformMonitor::try_lock() {
-  int status = os::Solaris::mutex_trylock(&_mutex);
-  assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
-  return status == 0;
 }
 
 // Must already be locked
--- a/src/hotspot/os/solaris/os_solaris.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/solaris/os_solaris.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -335,18 +335,34 @@
   }
 };
 
-// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj<mtSynchronizer> {
+// Platform specific implementations that underpin VM Mutex/Monitor classes
+
+class PlatformMutex : public CHeapObj<mtSynchronizer> {
+  // Disable copying
+  PlatformMutex(const PlatformMutex&);
+  PlatformMutex& operator=(const PlatformMutex&);
+
+ protected:
+  mutex_t _mutex; // Native mutex for locking
+
+ public:
+  PlatformMutex();
+  ~PlatformMutex();
+  void lock();
+  void unlock();
+  bool try_lock();
+};
+
+class PlatformMonitor : public PlatformMutex {
  private:
-  mutex_t _mutex; // Native mutex for locking
   cond_t  _cond;  // Native condition variable for blocking
+  // Disable copying
+  PlatformMonitor(const PlatformMonitor&);
+  PlatformMonitor& operator=(const PlatformMonitor&);
 
  public:
   PlatformMonitor();
   ~PlatformMonitor();
-  void lock();
-  void unlock();
-  bool try_lock();
   int wait(jlong millis);
   void notify();
   void notify_all();
--- a/src/hotspot/os/windows/os_windows.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -187,18 +187,34 @@
 
 } ;
 
-// Platform specific implementation that underpins VM Monitor/Mutex class
-class PlatformMonitor : public CHeapObj<mtSynchronizer> {
+// Platform specific implementations that underpin VM Mutex/Monitor classes
+
+class PlatformMutex : public CHeapObj<mtSynchronizer> {
+  // Disable copying
+  PlatformMutex(const PlatformMutex&);
+  PlatformMutex& operator=(const PlatformMutex&);
+
+ protected:
+  CRITICAL_SECTION   _mutex; // Native mutex for locking
+
+ public:
+  PlatformMutex();
+  ~PlatformMutex();
+  void lock();
+  void unlock();
+  bool try_lock();
+};
+
+class PlatformMonitor : public PlatformMutex {
  private:
-  CRITICAL_SECTION   _mutex; // Native mutex for locking
   CONDITION_VARIABLE _cond;  // Native condition variable for blocking
+  // Disable copying
+  PlatformMonitor(const PlatformMonitor&);
+  PlatformMonitor& operator=(const PlatformMonitor&);
 
  public:
   PlatformMonitor();
   ~PlatformMonitor();
-  void lock();
-  void unlock();
-  bool try_lock();
   int wait(jlong millis);
   void notify();
   void notify_all();
--- a/src/hotspot/os/windows/os_windows.inline.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.inline.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -81,26 +81,33 @@
   win32::exit_process_or_thread(win32::EPT_PROCESS, num);
 }
 
-// Platform Monitor implementation
+// Platform Mutex/Monitor implementation
+
+inline os::PlatformMutex::PlatformMutex() {
+  InitializeCriticalSection(&_mutex);
+}
+
+inline os::PlatformMutex::~PlatformMutex() {
+  DeleteCriticalSection(&_mutex);
+}
 
 inline os::PlatformMonitor::PlatformMonitor() {
   InitializeConditionVariable(&_cond);
-  InitializeCriticalSection(&_mutex);
 }
 
 inline os::PlatformMonitor::~PlatformMonitor() {
-  DeleteCriticalSection(&_mutex);
+  // There is no DeleteConditionVariable API
 }
 
-inline void os::PlatformMonitor::lock() {
+inline void os::PlatformMutex::lock() {
   EnterCriticalSection(&_mutex);
 }
 
-inline void os::PlatformMonitor::unlock() {
+inline void os::PlatformMutex::unlock() {
   LeaveCriticalSection(&_mutex);
 }
 
-inline bool os::PlatformMonitor::try_lock() {
+inline bool os::PlatformMutex::try_lock() {
   return TryEnterCriticalSection(&_mutex);
 }
 
--- a/src/hotspot/share/ci/ciMethodData.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/ci/ciMethodData.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -258,14 +258,12 @@
 void ciReceiverTypeData::translate_receiver_data_from(const ProfileData* data) {
   for (uint row = 0; row < row_limit(); row++) {
     Klass* k = data->as_ReceiverTypeData()->receiver(row);
-    if (k != NULL) {
-      if (k->is_loader_alive()) {
-        ciKlass* klass = CURRENT_ENV->get_klass(k);
-        set_receiver(row, klass);
-      } else {
-        // With concurrent class unloading, the MDO could have stale metadata; override it
-        clear_row(row);
-      }
+    if (k != NULL && k->is_loader_alive()) {
+      ciKlass* klass = CURRENT_ENV->get_klass(k);
+      set_receiver(row, klass);
+    } else {
+      // With concurrent class unloading, the MDO could have stale metadata; override it
+      clear_row(row);
     }
   }
 }
--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -47,6 +47,10 @@
   bs->gen_load_reference_barrier_stub(ce, this);
 }
 
+ShenandoahBarrierSetC1::ShenandoahBarrierSetC1() :
+  _pre_barrier_c1_runtime_code_blob(NULL),
+  _load_reference_barrier_rt_code_blob(NULL) {}
+
 void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) {
   // First we test whether marking is in progress.
   BasicType flag_type;
@@ -114,8 +118,10 @@
 
   obj = ensure_in_register(gen, obj);
   assert(obj->is_register(), "must be a register at this point");
-  LIR_Opr result = gen->new_register(T_OBJECT);
+  LIR_Opr result = gen->result_register_for(obj->value_type());
   __ move(obj, result);
+  LIR_Opr tmp1 = gen->new_register(T_OBJECT);
+  LIR_Opr tmp2 = gen->new_register(T_OBJECT);
 
   LIR_Opr thrd = gen->getThreadPointer();
   LIR_Address* active_flag_addr =
@@ -140,7 +146,7 @@
   }
   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
 
-  CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result);
+  CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, tmp1, tmp2);
   __ branch(lir_cond_notEqual, T_INT, slow);
   __ branch_destination(slow->continuation());
 
@@ -238,11 +244,25 @@
   }
 };
 
+class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
+  virtual OopMapSet* generate_code(StubAssembler* sasm) {
+    ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
+    bs->generate_c1_load_reference_barrier_runtime_stub(sasm);
+    return NULL;
+  }
+};
+
 void ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) {
   C1ShenandoahPreBarrierCodeGenClosure pre_code_gen_cl;
   _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1,
                                                               "shenandoah_pre_barrier_slow",
                                                               false, &pre_code_gen_cl);
+  if (ShenandoahLoadRefBarrier) {
+    C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_code_gen_cl;
+    _load_reference_barrier_rt_code_blob = Runtime1::generate_blob(buffer_blob, -1,
+                                                                  "shenandoah_load_reference_barrier_slow",
+                                                                  false, &lrb_code_gen_cl);
+  }
 }
 
 const char* ShenandoahBarrierSetC1::rtcall_name_for_address(address entry) {
--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -90,23 +90,31 @@
 private:
   LIR_Opr _obj;
   LIR_Opr _result;
+  LIR_Opr _tmp1;
+  LIR_Opr _tmp2;
 
 public:
-  ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr result) :
-    _obj(obj), _result(result)
+  ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2) :
+    _obj(obj), _result(result), _tmp1(tmp1), _tmp2(tmp2)
   {
     assert(_obj->is_register(), "should be register");
     assert(_result->is_register(), "should be register");
+    assert(_tmp1->is_register(), "should be register");
+    assert(_tmp2->is_register(), "should be register");
   }
 
   LIR_Opr obj() const { return _obj; }
   LIR_Opr result() const { return _result; }
+  LIR_Opr tmp1() const { return _tmp1; }
+  LIR_Opr tmp2() const { return _tmp2; }
 
   virtual void emit_code(LIR_Assembler* e);
   virtual void visit(LIR_OpVisitState* visitor) {
     visitor->do_slow_case();
     visitor->do_input(_obj);
     visitor->do_temp(_result);
+    visitor->do_temp(_tmp1);
+    visitor->do_temp(_tmp2);
   }
 #ifndef PRODUCT
   virtual void print_name(outputStream* out) const { out->print("ShenandoahLoadReferenceBarrierStub"); }
@@ -174,6 +182,7 @@
 class ShenandoahBarrierSetC1 : public BarrierSetC1 {
 private:
   CodeBlob* _pre_barrier_c1_runtime_code_blob;
+  CodeBlob* _load_reference_barrier_rt_code_blob;
 
   void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val);
 
@@ -185,7 +194,17 @@
   LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj);
 
 public:
-  CodeBlob* pre_barrier_c1_runtime_code_blob() { return _pre_barrier_c1_runtime_code_blob; }
+  ShenandoahBarrierSetC1();
+
+  CodeBlob* pre_barrier_c1_runtime_code_blob() {
+    assert(_pre_barrier_c1_runtime_code_blob != NULL, "");
+    return _pre_barrier_c1_runtime_code_blob;
+  }
+
+  CodeBlob* load_reference_barrier_rt_code_blob() {
+    assert(_load_reference_barrier_rt_code_blob != NULL, "");
+    return _load_reference_barrier_rt_code_blob;
+  }
 
 protected:
 
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -179,10 +179,6 @@
       if (trace) {tty->print_cr("NULL");}
     } else if (!in->bottom_type()->make_ptr()->make_oopptr()) {
       if (trace) {tty->print_cr("Non oop");}
-    } else if (t == ShenandoahLoad && ShenandoahOptimizeStableFinals &&
-               in->bottom_type()->make_ptr()->isa_aryptr() &&
-               in->bottom_type()->make_ptr()->is_aryptr()->is_stable()) {
-      if (trace) {tty->print_cr("Stable array load");}
     } else {
       if (in->is_ConstraintCast()) {
         in = in->in(1);
@@ -323,34 +319,8 @@
                    adr_type->is_instptr()->klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&
                    adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset) {
           if (trace) {tty->print_cr("Reference.get()");}
-        } else {
-          bool verify = true;
-          if (adr_type->isa_instptr()) {
-            const TypeInstPtr* tinst = adr_type->is_instptr();
-            ciKlass* k = tinst->klass();
-            assert(k->is_instance_klass(), "");
-            ciInstanceKlass* ik = (ciInstanceKlass*)k;
-            int offset = adr_type->offset();
-
-            if ((ik->debug_final_field_at(offset) && ShenandoahOptimizeInstanceFinals) ||
-                (ik->debug_stable_field_at(offset) && ShenandoahOptimizeStableFinals)) {
-              if (trace) {tty->print_cr("Final/stable");}
-              verify = false;
-            } else if (k == ciEnv::current()->Class_klass() &&
-                       tinst->const_oop() != NULL &&
-                       tinst->offset() >= (ik->size_helper() * wordSize)) {
-              ciInstanceKlass* k = tinst->const_oop()->as_instance()->java_lang_Class_klass()->as_instance_klass();
-              ciField* field = k->get_field_by_offset(tinst->offset(), true);
-              if ((ShenandoahOptimizeStaticFinals && field->is_final()) ||
-                  (ShenandoahOptimizeStableFinals && field->is_stable())) {
-                verify = false;
-              }
-            }
-          }
-
-          if (verify && !verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
-            report_verify_failure("Shenandoah verification: Load should have barriers", n);
-          }
+        } else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {
+          report_verify_failure("Shenandoah verification: Load should have barriers", n);
         }
       }
     } else if (n->is_Store()) {
@@ -3113,6 +3083,10 @@
   Unique_Node_List visited;
   Node_Stack stack(0);
   stack.push(this, 0);
+
+  // Look for strongest strength: go over nodes looking for STRONG ones.
+  // Stop once we encountered STRONG. Otherwise, walk until we ran out of nodes,
+  // and then the overall strength is NONE.
   Strength strength = NONE;
   while (strength != STRONG && stack.size() > 0) {
     Node* n = stack.node();
@@ -3123,22 +3097,7 @@
     visited.push(n);
     bool visit_users = false;
     switch (n->Opcode()) {
-      case Op_StoreN:
-      case Op_StoreP: {
-        strength = STRONG;
-        break;
-      }
-      case Op_CmpP: {
-        if (!n->in(1)->bottom_type()->higher_equal(TypePtr::NULL_PTR) &&
-            !n->in(2)->bottom_type()->higher_equal(TypePtr::NULL_PTR)) {
-          strength = STRONG;
-        }
-        break;
-      }
-      case Op_CallStaticJava: {
-        strength = STRONG;
-        break;
-      }
+      case Op_CallStaticJava:
       case Op_CallDynamicJava:
       case Op_CallLeaf:
       case Op_CallLeafNoFP:
@@ -3189,6 +3148,8 @@
       case Op_StoreLConditional:
       case Op_StoreI:
       case Op_StoreIConditional:
+      case Op_StoreN:
+      case Op_StoreP:
       case Op_StoreVector:
       case Op_StrInflatedCopy:
       case Op_StrCompressedCopy:
@@ -3196,8 +3157,24 @@
       case Op_CastP2X:
       case Op_SafePoint:
       case Op_EncodeISOArray:
+      case Op_AryEq:
+      case Op_StrEquals:
+      case Op_StrComp:
+      case Op_StrIndexOf:
+      case Op_StrIndexOfChar:
+      case Op_HasNegatives:
+        // Known to require barriers
         strength = STRONG;
         break;
+      case Op_CmpP: {
+        if (n->in(1)->bottom_type()->higher_equal(TypePtr::NULL_PTR) ||
+            n->in(2)->bottom_type()->higher_equal(TypePtr::NULL_PTR)) {
+          // One of the sides is known null, no need for barrier.
+        } else {
+          strength = STRONG;
+        }
+        break;
+      }
       case Op_LoadB:
       case Op_LoadUB:
       case Op_LoadUS:
@@ -3215,42 +3192,20 @@
         ciField* field = alias_type->field();
         bool is_static = field != NULL && field->is_static();
         bool is_final = field != NULL && field->is_final();
-        bool is_stable = field != NULL && field->is_stable();
+
         if (ShenandoahOptimizeStaticFinals && is_static && is_final) {
-          // Leave strength as is.
-        } else if (ShenandoahOptimizeInstanceFinals && !is_static && is_final) {
-          // Leave strength as is.
-        } else if (ShenandoahOptimizeStableFinals && (is_stable || (adr_type->isa_aryptr() && adr_type->isa_aryptr()->is_stable()))) {
-          // Leave strength as is.
+          // Loading the constant does not require barriers: it should be handled
+          // as part of GC roots already.
         } else {
-          strength = WEAK;
+          strength = STRONG;
         }
         break;
       }
-      case Op_AryEq: {
-        Node* n1 = n->in(2);
-        Node* n2 = n->in(3);
-        if (!ShenandoahOptimizeStableFinals ||
-            !n1->bottom_type()->isa_aryptr() || !n1->bottom_type()->isa_aryptr()->is_stable() ||
-            !n2->bottom_type()->isa_aryptr() || !n2->bottom_type()->isa_aryptr()->is_stable()) {
-          strength = WEAK;
-        }
-        break;
-      }
-      case Op_StrEquals:
-      case Op_StrComp:
-      case Op_StrIndexOf:
-      case Op_StrIndexOfChar:
-      case Op_HasNegatives:
-        if (!ShenandoahOptimizeStableFinals) {
-           strength = WEAK;
-        }
-        break;
       case Op_Conv2B:
       case Op_LoadRange:
       case Op_LoadKlass:
       case Op_LoadNKlass:
-        // NONE, i.e. leave current strength as is
+        // Do not require barriers
         break;
       case Op_AddP:
       case Op_CheckCastPP:
@@ -3258,26 +3213,19 @@
       case Op_CMoveP:
       case Op_Phi:
       case Op_ShenandoahLoadReferenceBarrier:
+        // Whether or not these need the barriers depends on their users
         visit_users = true;
         break;
       default: {
 #ifdef ASSERT
-        tty->print_cr("Unknown node in get_barrier_strength:");
-        n->dump(1);
-        ShouldNotReachHere();
+        fatal("Unknown node in get_barrier_strength: %s", NodeClassNames[n->Opcode()]);
 #else
+        // Default to strong: better to have excess barriers, rather than miss some.
         strength = STRONG;
 #endif
       }
     }
-#ifdef ASSERT
-/*
-    if (strength == STRONG) {
-      tty->print("strengthening node: ");
-      n->dump();
-    }
-    */
-#endif
+
     stack.pop();
     if (visit_users) {
       for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -231,7 +231,7 @@
   };
 
   enum Strength {
-    NONE, WEAK, STRONG, NA
+    NONE, STRONG
   };
 
 private:
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -276,20 +276,9 @@
 
 void ShenandoahConcurrentMark::update_roots(ShenandoahPhaseTimings::Phase root_phase) {
   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
-
-  bool update_code_cache = true; // initialize to safer value
-  switch (root_phase) {
-    case ShenandoahPhaseTimings::update_roots:
-    case ShenandoahPhaseTimings::final_update_refs_roots:
-      update_code_cache = false;
-      break;
-    case ShenandoahPhaseTimings::full_gc_roots:
-    case ShenandoahPhaseTimings::degen_gc_update_roots:
-      update_code_cache = true;
-      break;
-    default:
-      ShouldNotReachHere();
-  }
+  assert(root_phase == ShenandoahPhaseTimings::full_gc_roots ||
+         root_phase == ShenandoahPhaseTimings::degen_gc_update_roots,
+         "Only for these phases");
 
   ShenandoahGCPhase phase(root_phase);
 
@@ -299,7 +288,7 @@
 
   uint nworkers = _heap->workers()->active_workers();
 
-  ShenandoahRootUpdater root_updater(nworkers, root_phase, update_code_cache);
+  ShenandoahRootUpdater root_updater(nworkers, root_phase);
   ShenandoahUpdateRootsTask update_roots(&root_updater);
   _heap->workers()->run_task(&update_roots);
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -184,10 +184,9 @@
   _dedup_roots.oops_do(&always_true, oops, worker_id);
 }
 
-ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) :
+ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
   ShenandoahRootProcessor(phase),
-  _thread_roots(n_workers > 1),
-  _update_code_cache(update_code_cache) {
+  _thread_roots(n_workers > 1) {
 }
 
 ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -295,10 +295,9 @@
   ShenandoahWeakRoots<false /*concurrent*/>                 _weak_roots;
   ShenandoahStringDedupRoots                                _dedup_roots;
   ShenandoahCodeCacheRoots<ShenandoahCsetCodeRootsIterator> _code_roots;
-  const bool                                                _update_code_cache;
 
 public:
-  ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache);
+  ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase);
 
   template<typename IsAlive, typename KeepAlive>
   void roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.inline.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -272,10 +272,7 @@
 
   _thread_roots.oops_do(keep_alive, NULL, worker_id);
   _cld_roots.cld_do(&clds, worker_id);
-
-  if(_update_code_cache) {
-    _code_roots.code_blobs_do(&update_blobs, worker_id);
-  }
+  _code_roots.code_blobs_do(&update_blobs, worker_id);
 
   _serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
   _weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -706,7 +706,7 @@
 #if COMPILER2_OR_JVMCI
   DerivedPointerTable::clear();
 #endif
-  ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots, true /* update code cache */);
+  ShenandoahRootUpdater rp(_heap->workers()->active_workers(), ShenandoahPhaseTimings::final_traversal_update_roots);
   ShenandoahTraversalFixRootsTask update_roots_task(&rp);
   _heap->workers()->run_task(&update_roots_task);
 #if COMPILER2_OR_JVMCI
--- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -378,21 +378,11 @@
           " 1 - parallel iterator;"                                         \
           " 2 - parallel iterator with cset filters;")                      \
                                                                             \
-  experimental(bool, ShenandoahOptimizeStaticFinals, true,                  \
+  diagnostic(bool, ShenandoahOptimizeStaticFinals, true,                    \
           "Optimize barriers on static final fields. "                      \
           "Turn it off for maximum compatibility with reflection or JNI "   \
           "code that manipulates final fields.")                            \
                                                                             \
-  experimental(bool, ShenandoahOptimizeInstanceFinals, false,               \
-          "Optimize barriers on final instance fields."                     \
-          "Turn it off for maximum compatibility with reflection or JNI "   \
-          "code that manipulates final fields.")                            \
-                                                                            \
-  experimental(bool, ShenandoahOptimizeStableFinals, false,                 \
-          "Optimize barriers on stable fields."                             \
-          "Turn it off for maximum compatibility with reflection or JNI "   \
-          "code that manipulates final fields.")                            \
-                                                                            \
   experimental(bool, ShenandoahCommonGCStateLoads, false,                   \
          "Enable commonming for GC state loads in generated code.")         \
                                                                             \
--- a/src/hotspot/share/gc/z/zStat.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/gc/z/zStat.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -63,7 +63,7 @@
 
   void add(const ZStatSamplerData& new_sample) {
     _nsamples += new_sample._nsamples;
-    _sum += new_sample._nsamples;
+    _sum += new_sample._sum;
     _max = MAX2(_max, new_sample._max);
   }
 };
--- a/src/hotspot/share/oops/method.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/oops/method.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -828,11 +828,6 @@
   clear_code();
 }
 
-address Method::critical_native_function() {
-  methodHandle mh(this);
-  return NativeLookup::lookup_critical_entry(mh);
-}
-
 
 void Method::set_signature_handler(address handler) {
   address* signature_handler =  signature_handler_addr();
--- a/src/hotspot/share/oops/method.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/oops/method.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -533,7 +533,6 @@
     native_bind_event_is_interesting = true
   };
   address native_function() const                { return *(native_function_addr()); }
-  address critical_native_function();
 
   // Must specify a real function (not NULL).
   // Use clear_native_function() to unregister.
--- a/src/hotspot/share/opto/c2_globals.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/c2_globals.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -510,7 +510,7 @@
           "Sets max value cached by the java.lang.Integer autobox cache")   \
           range(0, max_jint)                                                \
                                                                             \
-  experimental(bool, AggressiveUnboxing, false,                             \
+  experimental(bool, AggressiveUnboxing, true,                              \
           "Control optimizations for aggressive boxing elimination")        \
                                                                             \
   develop(bool, TracePostallocExpand, false, "Trace expanding nodes after"  \
--- a/src/hotspot/share/opto/gcm.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/gcm.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -663,6 +663,19 @@
         // instead of control + memory.
         if (mstore->ideal_Opcode() == Op_SafePoint)
           continue;
+
+        // Check if the store is a membar on which the load is control dependent.
+        // Inserting an anti-dependency between that membar and the load would
+        // create a cycle that causes local scheduling to fail.
+        if (mstore->isa_MachMemBar()) {
+          Node* dom = load->find_exact_control(load->in(0));
+          while (dom != NULL && dom != dom->in(0) && dom != mstore) {
+            dom = dom->in(0);
+          }
+          if (dom == mstore) {
+            continue;
+          }
+        }
       } else {
         // Some raw memory, such as the load of "top" at an allocation,
         // can be control dependent on the previous safepoint. See
@@ -747,7 +760,7 @@
       // Found a possibly-interfering store in the load's 'early' block.
       // This means 'load' cannot sink at all in the dominator tree.
       // Add an anti-dep edge, and squeeze 'load' into the highest block.
-      assert(store != load->in(0), "dependence cycle found");
+      assert(store != load->find_exact_control(load->in(0)), "dependence cycle found");
       if (verify) {
         assert(store->find_edge(load) != -1, "missing precedence edge");
       } else {
@@ -787,7 +800,7 @@
       Block* store_block = get_block_for_node(store);
       if (store_block == LCA) {
         // add anti_dependence from store to load in its own block
-        assert(store != load->in(0), "dependence cycle found");
+        assert(store != load->find_exact_control(load->in(0)), "dependence cycle found");
         if (verify) {
           assert(store->find_edge(load) != -1, "missing precedence edge");
         } else {
--- a/src/hotspot/share/opto/memnode.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/memnode.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1435,8 +1435,6 @@
     }
   }
 
-  bool load_boxed_phi = load_boxed_values && base_is_phi && (base->in(0) == mem->in(0));
-
   // Split through Phi (see original code in loopopts.cpp).
   assert(C->have_alias_type(t_oop), "instance should have alias type");
 
--- a/src/hotspot/share/opto/node.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/opto/node.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1228,12 +1228,10 @@
     if (sub == up && sub->is_Loop()) {
       // Take loop entry path on the way up to 'dom'.
       up = sub->in(1); // in(LoopNode::EntryControl);
-    } else if (sub == up && sub->is_Region() && sub->req() != 3) {
-      // Always take in(1) path on the way up to 'dom' for clone regions
-      // (with only one input) or regions which merge > 2 paths
-      // (usually used to merge fast/slow paths).
+    } else if (sub == up && sub->is_Region() && sub->req() == 2) {
+      // Take in(1) path on the way up to 'dom' for regions with only one input
       up = sub->in(1);
-    } else if (sub == up && sub->is_Region()) {
+    } else if (sub == up && sub->is_Region() && sub->req() == 3) {
       // Try both paths for Regions with 2 input paths (it may be a loop head).
       // It could give conservative 'false' answer without information
       // which region's input is the entry path.
--- a/src/hotspot/share/prims/nativeLookup.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/prims/nativeLookup.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -38,6 +38,7 @@
 #include "prims/unsafe.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -258,7 +259,7 @@
 // Check all the formats of native implementation name to see if there is one
 // for the specified method.
 address NativeLookup::lookup_critical_entry(const methodHandle& method) {
-  if (!CriticalJNINatives) return NULL;
+  assert(CriticalJNINatives, "or should not be here");
 
   if (method->is_synchronized() ||
       !method->is_static()) {
@@ -284,6 +285,9 @@
     }
   }
 
+  // dll handling requires I/O. Don't do that while in _thread_in_vm (safepoint may get requested).
+  ThreadToNativeFromVM thread_in_native(JavaThread::current());
+
   void* dll = dll_load(method);
   address entry = NULL;
 
--- a/src/hotspot/share/runtime/objectMonitor.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/objectMonitor.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -1143,31 +1143,34 @@
   return;
 }
 
-
-// -----------------------------------------------------------------------------
-// A macro is used below because there may already be a pending
-// exception which should not abort the execution of the routines
-// which use this (which is why we don't put this into check_slow and
-// call it with a CHECK argument).
-
-#define CHECK_OWNER()                                                       \
-  do {                                                                      \
-    if (THREAD != _owner) {                                                 \
-      if (THREAD->is_lock_owned((address) _owner)) {                        \
-        _owner = THREAD;  /* Convert from basiclock addr to Thread addr */  \
-        _recursions = 0;                                                    \
-      } else {                                                              \
-        THROW(vmSymbols::java_lang_IllegalMonitorStateException());         \
-      }                                                                     \
-    }                                                                       \
+// Checks that the current THREAD owns this monitor and causes an
+// immediate return if it doesn't. We don't use the CHECK macro
+// because we want the IMSE to be the only exception that is thrown
+// from the call site when false is returned. Any other pending
+// exception is ignored.
+#define CHECK_OWNER()                                                  \
+  do {                                                                 \
+    if (!check_owner(THREAD)) {                                        \
+       assert(HAS_PENDING_EXCEPTION, "expected a pending IMSE here."); \
+       return;                                                         \
+     }                                                                 \
   } while (false)
 
-// check_slow() is a misnomer.  It's called to simply to throw an IMSX exception.
-// TODO-FIXME: remove check_slow() -- it's likely dead.
-
-void ObjectMonitor::check_slow(TRAPS) {
-  assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
-  THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner");
+// Returns true if the specified thread owns the ObjectMonitor.
+// Otherwise returns false and throws IllegalMonitorStateException
+// (IMSE). If there is a pending exception and the specified thread
+// is not the owner, that exception will be replaced by the IMSE.
+bool ObjectMonitor::check_owner(Thread* THREAD) {
+  if (_owner == THREAD) {
+    return true;
+  }
+  if (THREAD->is_lock_owned((address)_owner)) {
+    _owner = THREAD;  // convert from BasicLock addr to Thread addr
+    _recursions = 0;
+    return true;
+  }
+  THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
+             "current thread is not owner", false);
 }
 
 static void post_monitor_wait_event(EventJavaMonitorWait* event,
@@ -1197,8 +1200,7 @@
 
   assert(InitDone, "Unexpectedly not initialized");
 
-  // Throw IMSX or IEX.
-  CHECK_OWNER();
+  CHECK_OWNER();  // Throws IMSE if not owner.
 
   EventJavaMonitorWait event;
 
@@ -1477,7 +1479,7 @@
 // that suggests a lost wakeup bug.
 
 void ObjectMonitor::notify(TRAPS) {
-  CHECK_OWNER();
+  CHECK_OWNER();  // Throws IMSE if not owner.
   if (_WaitSet == NULL) {
     return;
   }
@@ -1495,7 +1497,7 @@
 // mode the waitset will be empty and the EntryList will be "DCBAXYZ".
 
 void ObjectMonitor::notifyAll(TRAPS) {
-  CHECK_OWNER();
+  CHECK_OWNER();  // Throws IMSE if not owner.
   if (_WaitSet == NULL) {
     return;
   }
--- a/src/hotspot/share/runtime/objectMonitor.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/objectMonitor.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -285,8 +285,9 @@
   void*     object_addr();
   void      set_object(void* obj);
 
-  bool      check(TRAPS);       // true if the thread owns the monitor.
-  void      check_slow(TRAPS);
+  // Returns true if the specified thread owns the ObjectMonitor. Otherwise
+  // returns false and throws IllegalMonitorStateException (IMSE).
+  bool      check_owner(Thread* THREAD);
   void      clear();
 
   void      enter(TRAPS);
--- a/src/hotspot/share/runtime/objectMonitor.inline.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -77,19 +77,6 @@
   _object = obj;
 }
 
-inline bool ObjectMonitor::check(TRAPS) {
-  if (THREAD != _owner) {
-    if (THREAD->is_lock_owned((address) _owner)) {
-      _owner = THREAD;  // regain ownership of inflated monitor
-      assert (_recursions == 0, "invariant") ;
-    } else {
-      check_slow(THREAD);
-      return false;
-    }
-  }
-  return true;
-}
-
 // return number of threads contending for this monitor
 inline jint ObjectMonitor::contentions() const {
   return _contentions;
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -2849,11 +2849,17 @@
 void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
   ResourceMark rm;
   nmethod* nm = NULL;
+  address critical_entry = NULL;
 
   assert(method->is_native(), "must be native");
   assert(method->is_method_handle_intrinsic() ||
          method->has_native_function(), "must have something valid to call!");
 
+  if (CriticalJNINatives && !method->is_method_handle_intrinsic()) {
+    // We perform the I/O with transition to native before acquiring AdapterHandlerLibrary_lock.
+    critical_entry = NativeLookup::lookup_critical_entry(method);
+  }
+
   {
     // Perform the work while holding the lock, but perform any printing outside the lock
     MutexLocker mu(AdapterHandlerLibrary_lock);
@@ -2898,7 +2904,7 @@
       int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, is_outgoing);
 
       // Generate the compiled-to-native wrapper code
-      nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type);
+      nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type, critical_entry);
 
       if (nm != NULL) {
         method->set_code(method, nm);
--- a/src/hotspot/share/runtime/sharedRuntime.hpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp	Wed Aug 14 08:23:16 2019 -0400
@@ -485,7 +485,8 @@
                                           int compile_id,
                                           BasicType* sig_bt,
                                           VMRegPair* regs,
-                                          BasicType ret_type);
+                                          BasicType ret_type,
+                                          address critical_entry);
 
   // Block before entering a JNI critical method
   static void block_for_jni_critical(JavaThread* thread);
--- a/src/hotspot/share/runtime/synchronizer.cpp	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/hotspot/share/runtime/synchronizer.cpp	Wed Aug 14 08:23:16 2019 -0400
@@ -429,9 +429,10 @@
   assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
 
   ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
-  // If this thread has locked the object, exit the monitor.  Note:  can't use
-  // monitor->check(CHECK); must exit even if an exception is pending.
-  if (monitor->check(THREAD)) {
+  // If this thread has locked the object, exit the monitor. We
+  // intentionally do not use CHECK here because we must exit the
+  // monitor even if an exception is pending.
+  if (monitor->check_owner(THREAD)) {
     monitor->exit(true, THREAD);
   }
 }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed Aug 14 08:23:16 2019 -0400
@@ -334,7 +334,7 @@
      * </tr>
      * <tr>
      *     <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</th>
-     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
+     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (FT) C.f;}</td>
      * </tr>
      * <tr>
      *     <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</th>
@@ -377,8 +377,8 @@
      *     <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
      * </tr>
      * <tr>
-     *     <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</th>
-     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
+     *     <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#unreflectSpecial lookup.unreflectSpecial(aMethod,this.class)}</th>
+     *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
      * </tr>
      * <tr>
      *     <th scope="row">{@link java.lang.invoke.MethodHandles.Lookup#findClass lookup.findClass("C")}</th>
@@ -403,7 +403,7 @@
      * stands for a null reference if the accessed method or field is static,
      * and {@code this} otherwise.
      * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
-     * for reflective objects corresponding to the given members.
+     * for reflective objects corresponding to the given members declared in type {@code C}.
      * <p>
      * The bytecode behavior for a {@code findClass} operation is a load of a constant class,
      * as if by {@code ldc CONSTANT_Class}.
@@ -2504,7 +2504,7 @@
          * @throws NullPointerException if any argument is null
          */
         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
-            checkSpecialCaller(specialCaller, null);
+            checkSpecialCaller(specialCaller, m.getDeclaringClass());
             Lookup specialLookup = this.in(specialCaller);
             MemberName method = new MemberName(m, true);
             assert(method.isMethod());
--- a/src/java.base/share/classes/java/security/SecureRandom.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/security/SecureRandom.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -32,6 +32,7 @@
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
+import sun.security.provider.SunEntries;
 import sun.security.util.Debug;
 
 /**
@@ -875,6 +876,13 @@
      */
     private static String getPrngAlgorithm() {
         for (Provider p : Providers.getProviderList().providers()) {
+            // For SUN provider, we use SunEntries.DEFF_SECURE_RANDOM_ALGO
+            // as the default SecureRandom algorithm; for other providers,
+            // we continue to iterate through to the 1st SecureRandom
+            // service
+            if (p.getName().equals("SUN")) {
+                return SunEntries.DEF_SECURE_RANDOM_ALGO;
+            }
             for (Service s : p.getServices()) {
                 if (s.getType().equals("SecureRandom")) {
                     return s.getAlgorithm();
--- a/src/java.base/share/classes/java/time/OffsetDateTime.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/time/OffsetDateTime.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, 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
@@ -1654,8 +1654,14 @@
     public long until(Temporal endExclusive, TemporalUnit unit) {
         OffsetDateTime end = OffsetDateTime.from(endExclusive);
         if (unit instanceof ChronoUnit) {
-            end = end.withOffsetSameInstant(offset);
-            return dateTime.until(end.dateTime, unit);
+            OffsetDateTime start = this;
+            try {
+                end = end.withOffsetSameInstant(offset);
+            } catch (DateTimeException ex) {
+                // end may be out of valid range. Adjust to end's offset.
+                start = withOffsetSameInstant(end.offset);
+            }
+            return start.dateTime.until(end.dateTime, unit);
         }
         return unit.between(this, end);
     }
--- a/src/java.base/share/classes/java/time/ZonedDateTime.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/java/time/ZonedDateTime.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, 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
@@ -2129,11 +2129,17 @@
     public long until(Temporal endExclusive, TemporalUnit unit) {
         ZonedDateTime end = ZonedDateTime.from(endExclusive);
         if (unit instanceof ChronoUnit) {
-            end = end.withZoneSameInstant(zone);
+            ZonedDateTime start = this;
+            try {
+                end = end.withZoneSameInstant(zone);
+            } catch (DateTimeException ex) {
+                // end may be out of valid range. Adjust to end's zone.
+                start = withZoneSameInstant(end.zone);
+            }
             if (unit.isDateBased()) {
-                return dateTime.until(end.dateTime, unit);
+                return start.dateTime.until(end.dateTime, unit);
             } else {
-                return toOffsetDateTime().until(end.toOffsetDateTime(), unit);
+                return start.toOffsetDateTime().until(end.toOffsetDateTime(), unit);
             }
         }
         return unit.between(this, end);
--- a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java	Wed Aug 14 08:23:16 2019 -0400
@@ -183,7 +183,7 @@
         this.parent = parent;
         this.ucp = ucp;
 
-        this.nameToModule = new ConcurrentHashMap<>();
+        this.nameToModule = new ConcurrentHashMap<>(32);
         this.moduleToReader = new ConcurrentHashMap<>();
     }
 
--- a/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java	Wed Aug 14 08:23:16 2019 -0400
@@ -81,7 +81,7 @@
     }
 
     // service name -> list of providers
-    private final Map<String, List<ServiceProvider>> map = new ConcurrentHashMap<>();
+    private final Map<String, List<ServiceProvider>> map = new ConcurrentHashMap<>(32);
 
     private ServicesCatalog() { }
 
--- a/src/java.base/share/classes/sun/net/www/MessageHeader.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/net/www/MessageHeader.java	Wed Aug 14 08:23:16 2019 -0400
@@ -288,14 +288,44 @@
         return Collections.unmodifiableMap(m);
     }
 
+    /** Check if a line of message header looks like a request line.
+     * This method does not perform a full validation but simply
+     * returns false if the line does not end with 'HTTP/[1-9].[0-9]'
+     * @param line the line to check.
+     * @return true if the line might be a request line.
+     */
+    private boolean isRequestline(String line) {
+        String k = line.trim();
+        int i = k.lastIndexOf(' ');
+        if (i <= 0) return false;
+        int len = k.length();
+        if (len - i < 9) return false;
+
+        char c1 = k.charAt(len-3);
+        char c2 = k.charAt(len-2);
+        char c3 = k.charAt(len-1);
+        if (c1 < '1' || c1 > '9') return false;
+        if (c2 != '.') return false;
+        if (c3 < '0' || c3 > '9') return false;
+
+        return (k.substring(i+1, len-3).equalsIgnoreCase("HTTP/"));
+    }
+
+
     /** Prints the key-value pairs represented by this
-        header.  Also prints the RFC required blank line
-        at the end. Omits pairs with a null key. */
+        header. Also prints the RFC required blank line
+        at the end. Omits pairs with a null key. Omits
+        colon if key-value pair is the requestline. */
     public synchronized void print(PrintStream p) {
         for (int i = 0; i < nkeys; i++)
             if (keys[i] != null) {
-                p.print(keys[i] +
-                    (values[i] != null ? ": "+values[i]: "") + "\r\n");
+                StringBuilder sb = new StringBuilder(keys[i]);
+                if (values[i] != null) {
+                    sb.append(": " + values[i]);
+                } else if (i != 0 || !isRequestline(keys[i])) {
+                    sb.append(":");
+                }
+                p.print(sb.append("\r\n"));
             }
         p.print("\r\n");
         p.flush();
--- a/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -77,6 +77,9 @@
 
 public final class SunEntries {
 
+    // the default algo used by SecureRandom class for new SecureRandom() calls
+    public static final String DEF_SECURE_RANDOM_ALGO;
+
     // create an aliases List from the specified aliases
     public static List<String> createAliases(String ... aliases) {
         return Arrays.asList(aliases);
@@ -89,7 +92,6 @@
         return Arrays.asList(result);
     }
 
-    // extend LinkedHashSet to preserve the ordering (needed by SecureRandom?)
     SunEntries(Provider p) {
         services = new LinkedHashSet<>(50, 0.9f);
 
@@ -99,41 +101,27 @@
         HashMap<String, String> attrs = new HashMap<>(3);
 
         /*
-         * SecureRandom
-         *
-         * Register these first to speed up "new SecureRandom()",
-         * which iterates through the list of algorithms
+         * SecureRandom engines
          */
-        // register the native PRNG, if available
-        // if user selected /dev/urandom, we put it before SHA1PRNG,
-        // otherwise after it
-        boolean nativeAvailable = NativePRNG.isAvailable();
-        boolean useNativePRNG = seedSource.equals(URL_DEV_URANDOM) ||
-            seedSource.equals(URL_DEV_RANDOM);
-
         attrs.put("ThreadSafe", "true");
-        if (nativeAvailable && useNativePRNG) {
+        if (NativePRNG.isAvailable()) {
             add(p, "SecureRandom", "NativePRNG",
-               "sun.security.provider.NativePRNG", null, attrs);
+                    "sun.security.provider.NativePRNG",
+                    null, attrs);
         }
-        attrs.put("ImplementedIn", "Software");
-        add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG", null, attrs);
-        add(p, "SecureRandom", "SHA1PRNG",
-            "sun.security.provider.SecureRandom", null, attrs);
-        attrs.remove("ImplementedIn");
-        if (nativeAvailable && !useNativePRNG) {
-            add(p, "SecureRandom", "NativePRNG", "sun.security.provider.NativePRNG",
-               null, attrs);
-        }
-
         if (NativePRNG.Blocking.isAvailable()) {
             add(p, "SecureRandom", "NativePRNGBlocking",
-                "sun.security.provider.NativePRNG$Blocking", null, attrs);
+                    "sun.security.provider.NativePRNG$Blocking", null, attrs);
         }
         if (NativePRNG.NonBlocking.isAvailable()) {
             add(p, "SecureRandom", "NativePRNGNonBlocking",
-                "sun.security.provider.NativePRNG$NonBlocking", null, attrs);
+                    "sun.security.provider.NativePRNG$NonBlocking", null, attrs);
         }
+        attrs.put("ImplementedIn", "Software");
+        add(p, "SecureRandom", "DRBG", "sun.security.provider.DRBG",
+               null, attrs);
+        add(p, "SecureRandom", "SHA1PRNG",
+                "sun.security.provider.SecureRandom", null, attrs);
 
         /*
          * Signature engines
@@ -148,9 +136,9 @@
 
         add(p, "Signature", "SHA1withDSA",
                 "sun.security.provider.DSA$SHA1withDSA",
-                createAliasesWithOid("1.2.840.10040.4.3", "DSA", "DSS", "SHA/DSA",
-                    "SHA-1/DSA", "SHA1/DSA", "SHAwithDSA", "DSAWithSHA1",
-                    "1.3.14.3.2.13", "1.3.14.3.2.27"), attrs);
+                createAliasesWithOid("1.2.840.10040.4.3", "DSA", "DSS",
+                    "SHA/DSA", "SHA-1/DSA", "SHA1/DSA", "SHAwithDSA",
+                    "DSAWithSHA1", "1.3.14.3.2.13", "1.3.14.3.2.27"), attrs);
         add(p, "Signature", "NONEwithDSA", "sun.security.provider.DSA$RawDSA",
                 createAliases("RawDSA"), attrs);
 
@@ -195,7 +183,8 @@
          * Algorithm Parameter Generator engines
          */
         add(p, "AlgorithmParameterGenerator", "DSA",
-            "sun.security.provider.DSAParameterGenerator", dsaAliases, attrs);
+                "sun.security.provider.DSAParameterGenerator", dsaAliases,
+                attrs);
         attrs.remove("KeySize");
 
         /*
@@ -307,8 +296,8 @@
     }
 
     private void add(Provider p, String type, String algo, String cn,
-             List<String> aliases, HashMap<String, String> attrs) {
-         services.add(new Provider.Service(p, type, algo, cn, aliases, attrs));
+            List<String> aliases, HashMap<String, String> attrs) {
+        services.add(new Provider.Service(p, type, algo, cn, aliases, attrs));
     }
 
     private LinkedHashSet<Provider.Service> services;
@@ -344,6 +333,11 @@
                 return egdSource;
             }
         });
+
+        DEF_SECURE_RANDOM_ALGO  = (NativePRNG.isAvailable() &&
+            (seedSource.equals(URL_DEV_URANDOM) ||
+             seedSource.equals(URL_DEV_RANDOM)) ?
+            "NativePRNG" : "DRBG");
     }
 
     static String getSeedSource() {
--- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1034,6 +1034,7 @@
                 // Don't select a signature scheme unless we will be able to
                 // produce a CertificateVerify message later
                 if (SignatureScheme.getPreferableAlgorithm(
+                        hc.algorithmConstraints,
                         hc.peerRequestedSignatureSchemes,
                         ss, hc.negotiatedProtocol) == null) {
 
--- a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -736,6 +736,7 @@
                 // Don't select a signature scheme unless we will be able to
                 // produce a CertificateVerify message later
                 if (SignatureScheme.getPreferableAlgorithm(
+                        hc.algorithmConstraints,
                         hc.peerRequestedSignatureSchemes,
                         ss, hc.negotiatedProtocol) == null) {
 
--- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java	Wed Aug 14 08:23:16 2019 -0400
@@ -564,6 +564,7 @@
             // This happens in client side only.
             ClientHandshakeContext chc = (ClientHandshakeContext)context;
             this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
+                    chc.algorithmConstraints,
                     chc.peerRequestedSignatureSchemes,
                     x509Possession,
                     chc.negotiatedProtocol);
@@ -865,6 +866,7 @@
             super(context);
 
             this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
+                    context.algorithmConstraints,
                     context.peerRequestedSignatureSchemes,
                     x509Possession,
                     context.negotiatedProtocol);
--- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java	Wed Aug 14 08:23:16 2019 -0400
@@ -35,8 +35,8 @@
 import static sun.security.ssl.CipherSuite.KeyExchange.*;
 import static sun.security.ssl.CipherSuite.MacAlg.*;
 import static sun.security.ssl.SSLCipher.*;
-import sun.security.ssl.NamedGroup.NamedGroupType;
-import static sun.security.ssl.NamedGroup.NamedGroupType.*;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
+import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
 
 /**
  * Enum for SSL/(D)TLS cipher suites.
@@ -1125,12 +1125,12 @@
         // name of the key exchange algorithm, e.g. DHE_DSS
         final String name;
         final boolean allowed;
-        final NamedGroupType[] groupTypes;
+        final NamedGroupSpec[] groupTypes;
         private final boolean alwaysAvailable;
         private final boolean isAnonymous;
 
         KeyExchange(String name, boolean allowed,
-                boolean isAnonymous, NamedGroupType... groupTypes) {
+                boolean isAnonymous, NamedGroupSpec... groupTypes) {
             this.name = name;
             this.groupTypes = groupTypes;
             this.allowed = allowed;
@@ -1144,8 +1144,8 @@
                 return true;
             }
 
-            if (NamedGroupType.arrayContains(
-                    groupTypes, NamedGroupType.NAMED_GROUP_ECDHE)) {
+            if (NamedGroupSpec.arrayContains(groupTypes,
+                    NamedGroupSpec.NAMED_GROUP_ECDHE)) {
                 return (allowed && JsseJce.isEcAvailable());
             } else {
                 return allowed;
--- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java	Wed Aug 14 08:23:16 2019 -0400
@@ -41,7 +41,7 @@
 import javax.crypto.spec.DHParameterSpec;
 import javax.crypto.spec.DHPublicKeySpec;
 import sun.security.action.GetPropertyAction;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 import sun.security.ssl.X509Authentication.X509Possession;
 import sun.security.util.KeyUtil;
@@ -76,7 +76,7 @@
         static DHECredentials valueOf(NamedGroup ng,
             byte[] encodedPublic) throws IOException, GeneralSecurityException {
 
-            if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+            if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
                 throw new RuntimeException(
                         "Credentials decoding:  Not FFDHE named group");
             }
@@ -85,11 +85,7 @@
                 return null;
             }
 
-            DHParameterSpec params = (DHParameterSpec)ng.getParameterSpec();
-            if (params == null) {
-                return null;
-            }
-
+            DHParameterSpec params = (DHParameterSpec)ng.keAlgParamSpec;
             KeyFactory kf = KeyFactory.getInstance("DiffieHellman");
             DHPublicKeySpec spec = new DHPublicKeySpec(
                     new BigInteger(1, encodedPublic),
@@ -110,9 +106,7 @@
             try {
                 KeyPairGenerator kpg =
                         KeyPairGenerator.getInstance("DiffieHellman");
-                DHParameterSpec params =
-                        (DHParameterSpec)namedGroup.getParameterSpec();
-                kpg.initialize(params, random);
+                kpg.initialize(namedGroup.keAlgParamSpec, random);
                 KeyPair kp = generateDHKeyPair(kpg);
                 if (kp == null) {
                     throw new RuntimeException("Could not generate DH keypair");
@@ -321,11 +315,10 @@
                     (context.clientRequestedNamedGroups != null) &&
                     (!context.clientRequestedNamedGroups.isEmpty())) {
                 preferableNamedGroup =
-                        SupportedGroups.getPreferredGroup(
-                                context.negotiatedProtocol,
+                        SupportedGroups.getPreferredGroup(context.negotiatedProtocol,
                                 context.algorithmConstraints,
-                                new NamedGroupType [] {
-                                    NamedGroupType.NAMED_GROUP_FFDHE },
+                                new NamedGroupSpec [] {
+                                    NamedGroupSpec.NAMED_GROUP_FFDHE },
                                 context.clientRequestedNamedGroups);
                 if (preferableNamedGroup != null) {
                     return new DHEPossession(preferableNamedGroup,
--- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java	Wed Aug 14 08:23:16 2019 -0400
@@ -125,6 +125,7 @@
                 Signature signer = null;
                 if (useExplicitSigAlgorithm) {
                     signatureScheme = SignatureScheme.getPreferableAlgorithm(
+                            shc.algorithmConstraints,
                             shc.peerRequestedSignatureSchemes,
                             x509Possession,
                             shc.negotiatedProtocol);
--- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java	Wed Aug 14 08:23:16 2019 -0400
@@ -36,7 +36,6 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.interfaces.ECPublicKey;
-import java.security.spec.ECGenParameterSpec;
 import java.security.spec.ECParameterSpec;
 import java.security.spec.ECPoint;
 import java.security.spec.ECPublicKeySpec;
@@ -44,7 +43,7 @@
 import javax.crypto.KeyAgreement;
 import javax.crypto.SecretKey;
 import javax.net.ssl.SSLHandshakeException;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 import sun.security.ssl.X509Authentication.X509Credentials;
 import sun.security.ssl.X509Authentication.X509Possession;
@@ -88,7 +87,7 @@
         static ECDHECredentials valueOf(NamedGroup namedGroup,
             byte[] encodedPoint) throws IOException, GeneralSecurityException {
 
-            if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
+            if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_ECDHE) {
                 throw new RuntimeException(
                     "Credentials decoding:  Not ECDHE named group");
             }
@@ -98,11 +97,7 @@
             }
 
             ECParameterSpec parameters =
-                    ECUtil.getECParameterSpec(null, namedGroup.oid);
-            if (parameters == null) {
-                return null;
-            }
-
+                    (ECParameterSpec)namedGroup.keAlgParamSpec;
             ECPoint point = ECUtil.decodePoint(
                     encodedPoint, parameters.getCurve());
             KeyFactory factory = KeyFactory.getInstance("EC");
@@ -120,9 +115,7 @@
         ECDHEPossession(NamedGroup namedGroup, SecureRandom random) {
             try {
                 KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
-                ECGenParameterSpec params =
-                        (ECGenParameterSpec)namedGroup.getParameterSpec();
-                kpg.initialize(params, random);
+                kpg.initialize(namedGroup.keAlgParamSpec, random);
                 KeyPair kp = kpg.generateKeyPair();
                 privateKey = kp.getPrivate();
                 publicKey = (ECPublicKey)kp.getPublic();
@@ -248,17 +241,17 @@
                 preferableNamedGroup = SupportedGroups.getPreferredGroup(
                         context.negotiatedProtocol,
                         context.algorithmConstraints,
-                        new NamedGroupType[] {
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            NamedGroupType.NAMED_GROUP_XDH },
+                        new NamedGroupSpec[] {
+                            NamedGroupSpec.NAMED_GROUP_ECDHE,
+                            NamedGroupSpec.NAMED_GROUP_XDH },
                         context.clientRequestedNamedGroups);
             } else {
                 preferableNamedGroup = SupportedGroups.getPreferredGroup(
                         context.negotiatedProtocol,
                         context.algorithmConstraints,
-                        new NamedGroupType[] {
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            NamedGroupType.NAMED_GROUP_XDH });
+                        new NamedGroupSpec[] {
+                            NamedGroupSpec.NAMED_GROUP_ECDHE,
+                            NamedGroupSpec.NAMED_GROUP_XDH });
             }
 
             if (preferableNamedGroup != null) {
@@ -308,7 +301,8 @@
 
                 NamedGroup ng = NamedGroup.valueOf(params);
                 if (ng == null) {
-                    // unlikely, have been checked during cipher suite negotiation.
+                    // unlikely, have been checked during cipher suite
+                    // negotiation.
                     throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
                         "Unsupported EC server cert for ECDH key exchange");
                 }
@@ -480,7 +474,7 @@
             }
 
             String alg;
-            switch (namedGroup.type) {
+            switch (namedGroup.spec) {
                 case NAMED_GROUP_ECDHE:
                     alg = "ECDH";
                     break;
--- a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java	Wed Aug 14 08:23:16 2019 -0400
@@ -38,6 +38,7 @@
 import java.security.SignatureException;
 import java.text.MessageFormat;
 import java.util.Locale;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import sun.security.ssl.SSLHandshake.HandshakeMessage;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 import sun.security.ssl.X509Authentication.X509Credentials;
@@ -110,13 +111,18 @@
 
             // Find the NamedGroup used for the ephemeral keys.
             namedGroup = namedGroupPossession.getNamedGroup();
+            if ((namedGroup == null) || (!namedGroup.isAvailable)) {
+                // unlikely
+                throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+                    "Missing or improper named group: " + namedGroup);
+            }
+
             publicPoint = namedGroup.encodePossessionPublicKey(
                     namedGroupPossession);
-
-            if ((namedGroup == null) || (namedGroup.oid == null) ) {
+            if (publicPoint == null) {
                 // unlikely
                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
-                    "Missing Named Group");
+                    "Missing public point for named group: " + namedGroup);
             }
 
             if (x509Possession == null) {
@@ -130,6 +136,7 @@
                 Signature signer = null;
                 if (useExplicitSigAlgorithm) {
                     signatureScheme = SignatureScheme.getPreferableAlgorithm(
+                            shc.algorithmConstraints,
                             shc.peerRequestedSignatureSchemes,
                             x509Possession,
                             shc.negotiatedProtocol);
--- a/src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java	Wed Aug 14 08:23:16 2019 -0400
@@ -34,7 +34,7 @@
 import sun.security.ssl.SSLExtension.ExtensionConsumer;
 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
 import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 
 /**
  * Pack of the "ec_point_formats" extensions [RFC 4492].
@@ -179,7 +179,7 @@
             // Produce the extension.
             //
             // produce the extension only if EC cipher suite is activated.
-            if (NamedGroupType.NAMED_GROUP_ECDHE.isSupported(
+            if (NamedGroupSpec.NAMED_GROUP_ECDHE.isSupported(
                     chc.activeCipherSuites)) {
                 // We are using uncompressed ECPointFormat only at present.
                 byte[] extData = new byte[] {0x01, 0x00};
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java	Wed Aug 14 08:23:16 2019 -0400
@@ -46,8 +46,8 @@
 import javax.net.ssl.SNIServerName;
 import javax.net.ssl.SSLHandshakeException;
 import javax.security.auth.x500.X500Principal;
-import sun.security.ssl.NamedGroup.NamedGroupType;
-import static sun.security.ssl.NamedGroup.NamedGroupType.*;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
+import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 
 abstract class HandshakeContext implements ConnectionContext {
@@ -283,8 +283,8 @@
             }
 
             boolean found = false;
-            Map<NamedGroupType, Boolean> cachedStatus =
-                    new EnumMap<>(NamedGroupType.class);
+            Map<NamedGroupSpec, Boolean> cachedStatus =
+                    new EnumMap<>(NamedGroupSpec.class);
             for (CipherSuite suite : enabledCipherSuites) {
                 if (suite.isAvailable() && suite.supports(protocol)) {
                     if (isActivatable(suite,
@@ -323,8 +323,8 @@
 
         List<CipherSuite> suites = new LinkedList<>();
         if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
-            Map<NamedGroupType, Boolean> cachedStatus =
-                    new EnumMap<>(NamedGroupType.class);
+            Map<NamedGroupSpec, Boolean> cachedStatus =
+                    new EnumMap<>(NamedGroupSpec.class);
             for (CipherSuite suite : enabledCipherSuites) {
                 if (!suite.isAvailable()) {
                     continue;
@@ -509,7 +509,7 @@
 
     private static boolean isActivatable(CipherSuite suite,
             AlgorithmConstraints algorithmConstraints,
-            Map<NamedGroupType, Boolean> cachedStatus) {
+            Map<NamedGroupSpec, Boolean> cachedStatus) {
 
         if (algorithmConstraints.permits(
                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) {
@@ -520,8 +520,8 @@
 
             // Is at least one of the group types available?
             boolean groupAvailable, retval = false;
-            NamedGroupType[] groupTypes = suite.keyExchange.groupTypes;
-            for (NamedGroupType groupType : groupTypes) {
+            NamedGroupSpec[] groupTypes = suite.keyExchange.groupTypes;
+            for (NamedGroupSpec groupType : groupTypes) {
                 if (groupType != NAMED_GROUP_NONE) {
                     Boolean checkedStatus = cachedStatus.get(groupType);
                     if (checkedStatus == null) {
--- a/src/java.base/share/classes/sun/security/ssl/NamedGroup.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/NamedGroup.java	Wed Aug 14 08:23:16 2019 -0400
@@ -29,16 +29,15 @@
 import java.io.IOException;
 import java.security.*;
 import java.security.spec.*;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.crypto.*;
+import java.util.Set;
+import javax.crypto.KeyAgreement;
 import sun.security.ssl.DHKeyExchange.DHEPossession;
 import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
+import sun.security.util.CurveDB;
 
-import sun.security.util.ECUtil;
 
 /**
  * An enum containing all known named groups for use in TLS.
@@ -52,186 +51,253 @@
     // See sun.security.util.CurveDB for the OIDs
     // NIST K-163
 
-    SECT163_K1(0x0001, "sect163k1", "1.3.132.0.1",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECT163_R1(0x0002, "sect163r1", "1.3.132.0.2",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT163_K1(0x0001, "sect163k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect163k1")),
+    SECT163_R1(0x0002, "sect163r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect163r1")),
 
     // NIST B-163
-    SECT163_R2(0x0003, "sect163r2", "1.3.132.0.15",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECT193_R1(0x0004, "sect193r1", "1.3.132.0.24",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECT193_R2(0x0005, "sect193r2", "1.3.132.0.25",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT163_R2(0x0003, "sect163r2",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect163r2")),
+    SECT193_R1(0x0004, "sect193r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect193r1")),
+    SECT193_R2(0x0005, "sect193r2",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect193r2")),
 
     // NIST K-233
-    SECT233_K1(0x0006, "sect233k1", "1.3.132.0.26",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT233_K1(0x0006, "sect233k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect233k1")),
 
     // NIST B-233
-    SECT233_R1(0x0007, "sect233r1", "1.3.132.0.27",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECT239_K1(0x0008, "sect239k1", "1.3.132.0.3",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT233_R1(0x0007, "sect233r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect233r1")),
+    SECT239_K1(0x0008, "sect239k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect239k1")),
 
     // NIST K-283
-    SECT283_K1(0x0009, "sect283k1", "1.3.132.0.16",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT283_K1(0x0009, "sect283k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect283k1")),
 
     // NIST B-283
-    SECT283_R1(0x000A, "sect283r1", "1.3.132.0.17",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT283_R1(0x000A, "sect283r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect283r1")),
 
     // NIST K-409
-    SECT409_K1(0x000B, "sect409k1", "1.3.132.0.36",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT409_K1(0x000B, "sect409k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect409k1")),
 
     // NIST B-409
-    SECT409_R1(0x000C, "sect409r1", "1.3.132.0.37",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT409_R1(0x000C, "sect409r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect409r1")),
 
     // NIST K-571
-    SECT571_K1(0x000D, "sect571k1", "1.3.132.0.38",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT571_K1(0x000D, "sect571k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect571k1")),
 
     // NIST B-571
-    SECT571_R1(0x000E, "sect571r1", "1.3.132.0.39",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECP160_K1(0x000F, "secp160k1", "1.3.132.0.9",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECP160_R1(0x0010, "secp160r1", "1.3.132.0.8",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECP160_R2(0x0011, "secp160r2", "1.3.132.0.30",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECP192_K1(0x0012, "secp192k1", "1.3.132.0.31",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECT571_R1(0x000E, "sect571r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("sect571r1")),
+    SECP160_K1(0x000F, "secp160k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp160k1")),
+    SECP160_R1(0x0010, "secp160r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp160r1")),
+    SECP160_R2(0x0011, "secp160r2",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp160r2")),
+    SECP192_K1(0x0012, "secp192k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp192k1")),
 
     // NIST P-192
-    SECP192_R1(0x0013, "secp192r1", "1.2.840.10045.3.1.1",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECP224_K1(0x0014, "secp224k1", "1.3.132.0.32",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECP192_R1(0x0013, "secp192r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp192r1")),
+    SECP224_K1(0x0014, "secp224k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp224k1")),
 
     // NIST P-224
-    SECP224_R1(0x0015, "secp224r1", "1.3.132.0.33",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    SECP256_K1(0x0016, "secp256k1", "1.3.132.0.10",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_12),
+    SECP224_R1(0x0015, "secp224r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp224r1")),
+    SECP256_K1(0x0016, "secp256k1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            CurveDB.lookup("secp256k1")),
 
     // NIST P-256
-    SECP256_R1(0x0017, "secp256r1", "1.2.840.10045.3.1.7",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
+    SECP256_R1(0x0017, "secp256r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            CurveDB.lookup("secp256r1")),
 
     // NIST P-384
-    SECP384_R1(0x0018, "secp384r1", "1.3.132.0.34",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
+    SECP384_R1(0x0018, "secp384r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            CurveDB.lookup("secp384r1")),
 
     // NIST P-521
-    SECP521_R1(0x0019, "secp521r1", "1.3.132.0.35",
-            NamedGroupType.NAMED_GROUP_ECDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
+    SECP521_R1(0x0019, "secp521r1",
+            NamedGroupSpec.NAMED_GROUP_ECDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            CurveDB.lookup("secp521r1")),
 
     // x25519 and x448 (RFC 8422/8446)
-    X25519(0x001D, "x25519", "1.3.101.110",
-            NamedGroupType.NAMED_GROUP_XDH,
-            ProtocolVersion.PROTOCOLS_TO_13),
-    X448(0x001E, "x448", "1.3.101.111",
-            NamedGroupType.NAMED_GROUP_XDH,
-            ProtocolVersion.PROTOCOLS_TO_13),
+    X25519(0x001D, "x25519",
+            NamedGroupSpec.NAMED_GROUP_XDH,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            NamedParameterSpec.X25519),
+    X448(0x001E, "x448",
+            NamedGroupSpec.NAMED_GROUP_XDH,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            NamedParameterSpec.X448),
 
     // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
-    FFDHE_2048(0x0100, "ffdhe2048", null,
-            NamedGroupType.NAMED_GROUP_FFDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
-    FFDHE_3072(0x0101, "ffdhe3072", null,
-            NamedGroupType.NAMED_GROUP_FFDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
-    FFDHE_4096(0x0102, "ffdhe4096", null,
-            NamedGroupType.NAMED_GROUP_FFDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
-    FFDHE_6144(0x0103, "ffdhe6144", null,
-            NamedGroupType.NAMED_GROUP_FFDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
-    FFDHE_8192(0x0104, "ffdhe8192", null,
-            NamedGroupType.NAMED_GROUP_FFDHE,
-            ProtocolVersion.PROTOCOLS_TO_13),
+    FFDHE_2048(0x0100, "ffdhe2048",
+            NamedGroupSpec.NAMED_GROUP_FFDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            PredefinedDHParameterSpecs.ffdheParams.get(2048)),
+
+    FFDHE_3072(0x0101, "ffdhe3072",
+            NamedGroupSpec.NAMED_GROUP_FFDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            PredefinedDHParameterSpecs.ffdheParams.get(3072)),
+    FFDHE_4096(0x0102, "ffdhe4096",
+            NamedGroupSpec.NAMED_GROUP_FFDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            PredefinedDHParameterSpecs.ffdheParams.get(4096)),
+    FFDHE_6144(0x0103, "ffdhe6144",
+            NamedGroupSpec.NAMED_GROUP_FFDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            PredefinedDHParameterSpecs.ffdheParams.get(6144)),
+    FFDHE_8192(0x0104, "ffdhe8192",
+            NamedGroupSpec.NAMED_GROUP_FFDHE,
+            ProtocolVersion.PROTOCOLS_TO_13,
+            PredefinedDHParameterSpecs.ffdheParams.get(8192)),
 
     // Elliptic Curves (RFC 4492)
     //
     // arbitrary prime and characteristic-2 curves
-    ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", null,
-            NamedGroupType.NAMED_GROUP_ARBITRARY,
-            ProtocolVersion.PROTOCOLS_TO_12),
-    ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", null,
-            NamedGroupType.NAMED_GROUP_ARBITRARY,
-            ProtocolVersion.PROTOCOLS_TO_12);
+    ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves",
+            NamedGroupSpec.NAMED_GROUP_ARBITRARY,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            null),
+    ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves",
+            NamedGroupSpec.NAMED_GROUP_ARBITRARY,
+            ProtocolVersion.PROTOCOLS_TO_12,
+            null);
 
     final int id;               // hash + signature
-    final NamedGroupType type;  // group type
     final String name;          // literal name
-    final String oid;           // object identifier of the named group
-    final String algorithm;     // signature algorithm
+    final NamedGroupSpec spec;  // group type
     final ProtocolVersion[] supportedProtocols;
-    private final NamedGroupFunctions functions;    // may be null
+    final String algorithm;     // key exchange algorithm
+    final AlgorithmParameterSpec keAlgParamSpec;
+    final AlgorithmParameters keAlgParams;
+    final boolean isAvailable;
+
+    // performance optimization
+    private static final Set<CryptoPrimitive> KEY_AGREEMENT_PRIMITIVE_SET =
+        Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.KEY_AGREEMENT));
 
     // Constructor used for all NamedGroup types
-    private NamedGroup(int id, String name, String oid,
-            NamedGroupType namedGroupType,
-            ProtocolVersion[] supportedProtocols) {
+    private NamedGroup(int id, String name,
+            NamedGroupSpec namedGroupSpec,
+            ProtocolVersion[] supportedProtocols,
+            AlgorithmParameterSpec keAlgParamSpec) {
         this.id = id;
         this.name = name;
-        this.oid = oid;
-        this.type = namedGroupType;
+        this.spec = namedGroupSpec;
+        this.algorithm = namedGroupSpec.algorithm;
         this.supportedProtocols = supportedProtocols;
+        this.keAlgParamSpec = keAlgParamSpec;
 
-        if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
-            this.functions = ECDHFunctions.getInstance();
-            this.algorithm = "EC";
-        } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
-            this.functions = FFDHFunctions.getInstance();
-            this.algorithm = "DiffieHellman";
-        } else if (this.type == NamedGroupType.NAMED_GROUP_XDH) {
-            this.functions = XDHFunctions.getInstance();
-            this.algorithm = "XDH";
-        } else if (this.type == NamedGroupType.NAMED_GROUP_ARBITRARY) {
-            this.functions = null;
-            this.algorithm = "EC";
-        } else {
-            throw new RuntimeException("Unexpected Named Group Type");
+        AlgorithmParameters algParams = null;
+        boolean mediator = (keAlgParamSpec != null);
+        if (mediator) {
+            try {
+                algParams =
+                    AlgorithmParameters.getInstance(namedGroupSpec.algorithm);
+                algParams.init(keAlgParamSpec);
+            } catch (InvalidParameterSpecException
+                    | NoSuchAlgorithmException exp) {
+                if (namedGroupSpec != NamedGroupSpec.NAMED_GROUP_XDH) {
+                    mediator = false;
+                    if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+                        SSLLogger.warning(
+                            "No AlgorithmParameters for " + name, exp);
+                    }
+                } else {
+                    // HACK CODE
+                    //
+                    // Please remove the following code if the XDH/X25519/X448
+                    // AlgorithmParameters algorithms are supported in JDK.
+                    algParams = null;
+                    try {
+                        KeyAgreement.getInstance(name);
+
+                        // The following service is also needed.  But for
+                        // performance, check the KeyAgreement impl only.
+                        //
+                        // KeyFactory.getInstance(name);
+                        // KeyPairGenerator.getInstance(name);
+                        // AlgorithmParameters.getInstance(name);
+                    } catch (NoSuchAlgorithmException nsae) {
+                        mediator = false;
+                        if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+                            SSLLogger.warning(
+                                "No AlgorithmParameters for " + name, nsae);
+                        }
+                    }
+                }
+            }
         }
+
+        this.isAvailable = mediator;
+        this.keAlgParams = mediator ? algParams : null;
     }
 
-    private Optional<NamedGroupFunctions> getFunctions() {
-        return Optional.ofNullable(functions);
-    }
-
+    //
     // The next set of methods search & retrieve NamedGroups.
-
+    //
     static NamedGroup valueOf(int id) {
         for (NamedGroup group : NamedGroup.values()) {
             if (group.id == id) {
@@ -243,12 +309,11 @@
     }
 
     static NamedGroup valueOf(ECParameterSpec params) {
-        String oid = ECUtil.getCurveName(null, params);
-        if ((oid != null) && (!oid.isEmpty())) {
-            for (NamedGroup group : NamedGroup.values()) {
-                if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE)
-                        && oid.equals(group.oid)) {
-                    return group;
+        for (NamedGroup ng : NamedGroup.values()) {
+            if (ng.spec == NamedGroupSpec.NAMED_GROUP_ECDHE) {
+                if ((params == ng.keAlgParamSpec) ||
+                        (ng.keAlgParamSpec == CurveDB.lookup(params))) {
+                    return ng;
                 }
             }
         }
@@ -258,23 +323,11 @@
 
     static NamedGroup valueOf(DHParameterSpec params) {
         for (NamedGroup ng : NamedGroup.values()) {
-            if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
+            if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
                 continue;
             }
 
-            DHParameterSpec ngParams = null;
-            // functions is non-null for FFDHE type
-            AlgorithmParameters aps = ng.functions.getParameters(ng);
-            try {
-                ngParams = aps.getParameterSpec(DHParameterSpec.class);
-            } catch (InvalidParameterSpecException ipse) {
-                // should be unlikely
-            }
-
-            if (ngParams == null) {
-                continue;
-            }
-
+            DHParameterSpec ngParams = (DHParameterSpec)ng.keAlgParamSpec;
             if (ngParams.getP().equals(params.getP())
                     && ngParams.getG().equals(params.getG())) {
                 return ng;
@@ -304,118 +357,128 @@
         return "UNDEFINED-NAMED-GROUP(" + id + ")";
     }
 
-    // Are the NamedGroups available for the protocol desired?
-
+    // Is the NamedGroup available for the protocols desired?
     boolean isAvailable(List<ProtocolVersion> protocolVersions) {
-        for (ProtocolVersion pv : supportedProtocols) {
-            if (protocolVersions.contains(pv)) {
-                return true;
+        if (this.isAvailable) {
+            for (ProtocolVersion pv : supportedProtocols) {
+                if (protocolVersions.contains(pv)) {
+                    return true;
+                }
             }
         }
+
         return false;
     }
 
     boolean isAvailable(ProtocolVersion protocolVersion) {
-        for (ProtocolVersion pv : supportedProtocols) {
-            if (protocolVersion == pv) {
-                return true;
+        if (this.isAvailable) {
+            for (ProtocolVersion pv : supportedProtocols) {
+                if (protocolVersion == pv) {
+                    return true;
+                }
             }
         }
+
         return false;
     }
 
     // Are the NamedGroups available for the ciphersuites desired?
-
     boolean isSupported(List<CipherSuite> cipherSuites) {
         for (CipherSuite cs : cipherSuites) {
             boolean isMatch = isAvailable(cs.supportedProtocols);
             if (isMatch && ((cs.keyExchange == null)
-                    || (NamedGroupType.arrayContains(
-                        cs.keyExchange.groupTypes, type)))) {
+                    || (NamedGroupSpec.arrayContains(
+                            cs.keyExchange.groupTypes, spec)))) {
                 return true;
             }
         }
+
         return false;
     }
 
-    // lazy loading of parameters
-    AlgorithmParameters getParameters() {
-        Optional<NamedGroupFunctions> ngf = getFunctions();
-        if (ngf.isEmpty()) {
-            return null;
-        }
-        return ngf.get().getParameters(this);
-    }
-
-    // The next set of methods use the NamedGroupFunctions table
-    // to do various operations in a consistent way.
-
-    AlgorithmParameterSpec getParameterSpec() {
-        Optional<NamedGroupFunctions> ngf = getFunctions();
-        if (ngf.isEmpty()) {
-            return null;
-        }
-        return ngf.get().getParameterSpec(this);
+    boolean isPermitted(AlgorithmConstraints constraints) {
+        return constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
+                        this.name, null) &&
+                constraints.permits(KEY_AGREEMENT_PRIMITIVE_SET,
+                        this.algorithm, this.keAlgParams);
     }
 
     byte[] encodePossessionPublicKey(
             NamedGroupPossession namedGroupPossession) {
-
-        Optional<NamedGroupFunctions> ngf = getFunctions();
-        if (ngf.isEmpty()) {
-            return null;
-        }
-        return ngf.get().encodePossessionPublicKey(namedGroupPossession);
+        return spec.encodePossessionPublicKey(namedGroupPossession);
     }
 
     SSLCredentials decodeCredentials(byte[] encoded,
             AlgorithmConstraints constraints,
             ExceptionSupplier onConstraintFail)
             throws IOException, GeneralSecurityException {
-
-        Optional<NamedGroupFunctions> ngf = getFunctions();
-        if (ngf.isEmpty()) {
-            return null;
-        }
-        return ngf.get().decodeCredentials(this, encoded, constraints,
-                onConstraintFail);
+        return spec.decodeCredentials(
+                this, encoded, constraints, onConstraintFail);
     }
 
     SSLPossession createPossession(SecureRandom random) {
+        return spec.createPossession(this, random);
+    }
 
-        Optional<NamedGroupFunctions> ngf = getFunctions();
-        if (ngf.isEmpty()) {
-            return null;
-        }
-        return ngf.get().createPossession(this, random);
+    SSLKeyDerivation createKeyDerivation(
+            HandshakeContext hc) throws IOException {
+        return spec.createKeyDerivation(hc);
+    }
+
+    interface ExceptionSupplier {
+        void apply(String s) throws SSLException;
     }
 
-    SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
-            throws IOException {
+    // A list of operations related to named groups.
+    private interface NamedGroupScheme {
+        default void checkConstraints(PublicKey publicKey,
+                AlgorithmConstraints constraints,
+                ExceptionSupplier onConstraintFail) throws SSLException {
+            if (!constraints.permits(
+                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
+                onConstraintFail.apply("key share entry does not "
+                        + "comply with algorithm constraints");
+            }
+        }
 
-        Optional<NamedGroupFunctions> ngf = getFunctions();
-        if (ngf.isEmpty()) {
-            return null;
-        }
-        return ngf.get().createKeyDerivation(hc);
+        byte[] encodePossessionPublicKey(
+                NamedGroupPossession namedGroupPossession);
 
+        SSLCredentials decodeCredentials(
+                NamedGroup ng, byte[] encoded,
+                AlgorithmConstraints constraints,
+                ExceptionSupplier onConstraintFail
+            ) throws IOException, GeneralSecurityException;
+
+        SSLPossession createPossession(NamedGroup ng, SecureRandom random);
+
+        SSLKeyDerivation createKeyDerivation(
+                HandshakeContext hc) throws IOException;
     }
 
-    boolean isAvailableGroup() {
-        Optional<NamedGroupFunctions> ngfOpt = getFunctions();
-        if (ngfOpt.isEmpty()) {
-            return false;
+    enum NamedGroupSpec implements NamedGroupScheme {
+        // Elliptic Curve Groups (ECDHE)
+        NAMED_GROUP_ECDHE("EC", ECDHEScheme.instance),
+
+        // Finite Field Groups (DHE)
+        NAMED_GROUP_FFDHE("DiffieHellman", FFDHEScheme.instance),
+
+        // Finite Field Groups (XDH)
+        NAMED_GROUP_XDH("XDH", XDHScheme.instance),
+
+        // arbitrary prime and curves (ECDHE)
+        NAMED_GROUP_ARBITRARY("EC", null),
+
+        // Not predefined named group
+        NAMED_GROUP_NONE("", null);
+
+        private final String algorithm;     // key exchange name
+        private final NamedGroupScheme scheme;  // named group operations
+
+        private NamedGroupSpec(String algorithm, NamedGroupScheme scheme) {
+            this.algorithm = algorithm;
+            this.scheme = scheme;
         }
-        NamedGroupFunctions ngf = ngfOpt.get();
-        return ngf.isAvailable(this);
-    }
-
-    enum NamedGroupType {
-        NAMED_GROUP_ECDHE,      // Elliptic Curve Groups (ECDHE)
-        NAMED_GROUP_FFDHE,      // Finite Field Groups (DHE)
-        NAMED_GROUP_XDH,        // Finite Field Groups (XDH)
-        NAMED_GROUP_ARBITRARY,  // arbitrary prime and curves (ECDHE)
-        NAMED_GROUP_NONE;       // Not predefined named group
 
         boolean isSupported(List<CipherSuite> cipherSuites) {
             for (CipherSuite cs : cipherSuites) {
@@ -428,92 +491,63 @@
             return false;
         }
 
-        static boolean arrayContains(NamedGroupType[] namedGroupTypes,
-                NamedGroupType namedGroupType) {
-            for (NamedGroupType ng : namedGroupTypes) {
+        static boolean arrayContains(NamedGroupSpec[] namedGroupTypes,
+                NamedGroupSpec namedGroupType) {
+            for (NamedGroupSpec ng : namedGroupTypes) {
                 if (ng == namedGroupType) {
                     return true;
                 }
             }
+
             return false;
         }
+
+        @Override
+        public byte[] encodePossessionPublicKey(
+                NamedGroupPossession namedGroupPossession) {
+            if (scheme != null) {
+                return scheme.encodePossessionPublicKey(namedGroupPossession);
+            }
+
+            return null;
+        }
+
+        @Override
+        public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
+                    AlgorithmConstraints constraints,
+                    ExceptionSupplier onConstraintFail
+                ) throws IOException, GeneralSecurityException {
+            if (scheme != null) {
+                return scheme.decodeCredentials(
+                        ng, encoded, constraints, onConstraintFail);
+            }
+
+            return null;
+        }
+
+        @Override
+        public SSLPossession createPossession(
+                NamedGroup ng, SecureRandom random) {
+            if (scheme != null) {
+                return scheme.createPossession(ng, random);
+            }
+
+            return null;
+        }
+
+        @Override
+        public SSLKeyDerivation createKeyDerivation(
+                HandshakeContext hc) throws IOException {
+            if (scheme != null) {
+                return scheme.createKeyDerivation(hc);
+            }
+
+            return null;
+        }
     }
 
-    interface ExceptionSupplier {
-        void apply(String s) throws SSLException;
-    }
-
-    /*
-     * A list of functions to do NamedGroup operations in a
-     * algorithm-independent and consistent way.
-     */
-    private static abstract class NamedGroupFunctions {
-
-        // cache to speed up the parameters construction
-        protected static final Map<NamedGroup, AlgorithmParameters>
-                namedGroupParams = new ConcurrentHashMap<>();
-
-        protected void checkConstraints(PublicKey publicKey,
-                AlgorithmConstraints constraints,
-                ExceptionSupplier onConstraintFail)
-                throws SSLException {
-
-            if (!constraints.permits(
-                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                    publicKey)) {
-
-                onConstraintFail.apply("key share entry does not "
-                        + "comply with algorithm constraints");
-            }
-        }
-
-        public AlgorithmParameters getParameters(NamedGroup ng) {
-
-            AlgorithmParameters result = namedGroupParams.get(ng);
-            if (result == null) {
-                Optional<AlgorithmParameters> paramsOpt = getParametersImpl(ng);
-                if (paramsOpt.isPresent()) {
-                    result = paramsOpt.get();
-                    namedGroupParams.put(ng, result);
-                }
-            }
-
-            return result;
-        }
-
-        public abstract byte[] encodePossessionPublicKey(
-                NamedGroupPossession namedGroupPossession);
-
-        public abstract SSLCredentials decodeCredentials(
-                NamedGroup ng, byte[] encoded,
-                AlgorithmConstraints constraints,
-                ExceptionSupplier onConstraintFail)
-                throws IOException, GeneralSecurityException;
-
-        public abstract SSLPossession createPossession(NamedGroup ng,
-                SecureRandom random);
-
-        public abstract SSLKeyDerivation createKeyDerivation(
-                HandshakeContext hc) throws IOException;
-
-        protected abstract Optional<AlgorithmParameters> getParametersImpl(
-                NamedGroup ng);
-
-        public abstract AlgorithmParameterSpec getParameterSpec(NamedGroup ng);
-
-        public abstract boolean isAvailable(NamedGroup ng);
-    }
-
-    private static class FFDHFunctions extends NamedGroupFunctions {
-
-        // lazy initialization
-        private static class FunctionsHolder {
-            private static final FFDHFunctions instance = new FFDHFunctions();
-        }
-
-        private static FFDHFunctions getInstance() {
-            return FunctionsHolder.instance;
-        }
+    private static class FFDHEScheme implements NamedGroupScheme {
+        private static final FFDHEScheme instance = new FFDHEScheme();
 
         @Override
         public byte[] encodePossessionPublicKey(
@@ -524,8 +558,8 @@
         @Override
         public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
                 AlgorithmConstraints constraints,
-                ExceptionSupplier onConstraintFail)
-                throws IOException, GeneralSecurityException {
+                ExceptionSupplier onConstraintFail
+            ) throws IOException, GeneralSecurityException {
 
             DHKeyExchange.DHECredentials result
                     = DHKeyExchange.DHECredentials.valueOf(ng, encoded);
@@ -543,111 +577,15 @@
         }
 
         @Override
-        public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
-                throws IOException {
+        public SSLKeyDerivation createKeyDerivation(
+                HandshakeContext hc) throws IOException {
 
             return DHKeyExchange.kaGenerator.createKeyDerivation(hc);
         }
-
-        @Override
-        public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
-            return getDHParameterSpec(ng);
-        }
-
-        DHParameterSpec getDHParameterSpec(NamedGroup ng) {
-
-            AlgorithmParameters params = getParameters(ng);
-            try {
-                return params.getParameterSpec(DHParameterSpec.class);
-            } catch (InvalidParameterSpecException ipse) {
-                // should be unlikely
-                return getPredefinedDHParameterSpec(ng);
-            }
-        }
-
-        private static DHParameterSpec getFFDHEDHParameterSpec(
-                NamedGroup namedGroup) {
-
-            DHParameterSpec spec = null;
-            switch (namedGroup) {
-                case FFDHE_2048:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
-                    break;
-                case FFDHE_3072:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
-                    break;
-                case FFDHE_4096:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
-                    break;
-                case FFDHE_6144:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
-                    break;
-                case FFDHE_8192:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
-            }
-
-            return spec;
-        }
-
-        private static DHParameterSpec getPredefinedDHParameterSpec(
-                NamedGroup namedGroup) {
-
-            DHParameterSpec spec = null;
-            switch (namedGroup) {
-                case FFDHE_2048:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(2048);
-                    break;
-                case FFDHE_3072:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(3072);
-                    break;
-                case FFDHE_4096:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(4096);
-                    break;
-                case FFDHE_6144:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(6144);
-                    break;
-                case FFDHE_8192:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(8192);
-            }
-
-            return spec;
-        }
-
-        @Override
-        public boolean isAvailable(NamedGroup ng) {
-
-            AlgorithmParameters params = getParameters(ng);
-            return params != null;
-        }
-
-        @Override
-        protected Optional<AlgorithmParameters> getParametersImpl(
-                NamedGroup ng) {
-            try {
-                AlgorithmParameters params
-                        = AlgorithmParameters.getInstance("DiffieHellman");
-                AlgorithmParameterSpec spec
-                        = getFFDHEDHParameterSpec(ng);
-                params.init(spec);
-                return Optional.of(params);
-            } catch (InvalidParameterSpecException
-                    | NoSuchAlgorithmException ex) {
-                return Optional.empty();
-            }
-        }
-
     }
 
-    private static class ECDHFunctions extends NamedGroupFunctions {
-
-        // lazy initialization
-        private static class FunctionsHolder {
-            private static final ECDHFunctions instance = new ECDHFunctions();
-        }
-
-        private static ECDHFunctions getInstance() {
-            return FunctionsHolder.instance;
-        }
+    private static class ECDHEScheme implements NamedGroupScheme {
+        private static final ECDHEScheme instance = new ECDHEScheme();
 
         @Override
         public byte[] encodePossessionPublicKey(
@@ -658,8 +596,8 @@
         @Override
         public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
                 AlgorithmConstraints constraints,
-                ExceptionSupplier onConstraintFail)
-                throws IOException, GeneralSecurityException {
+                ExceptionSupplier onConstraintFail
+            ) throws IOException, GeneralSecurityException {
 
             ECDHKeyExchange.ECDHECredentials result
                     = ECDHKeyExchange.ECDHECredentials.valueOf(ng, encoded);
@@ -677,52 +615,14 @@
         }
 
         @Override
-        public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
-                throws IOException {
-
+        public SSLKeyDerivation createKeyDerivation(
+                HandshakeContext hc) throws IOException {
             return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc);
         }
-
-        @Override
-        public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
-            return SupportedGroupsExtension.SupportedGroups
-                    .getECGenParamSpec(ng);
-        }
-
-        @Override
-        public boolean isAvailable(NamedGroup ng) {
-
-            AlgorithmParameters params = getParameters(ng);
-            return params != null;
-        }
-
-        @Override
-        protected Optional<AlgorithmParameters> getParametersImpl(
-                NamedGroup ng) {
-            try {
-                AlgorithmParameters params
-                        = AlgorithmParameters.getInstance("EC");
-                AlgorithmParameterSpec spec
-                        = new ECGenParameterSpec(ng.oid);
-                params.init(spec);
-                return Optional.of(params);
-            } catch (InvalidParameterSpecException
-                    | NoSuchAlgorithmException ex) {
-                return Optional.empty();
-            }
-        }
     }
 
-    private static class XDHFunctions extends NamedGroupFunctions {
-
-        // lazy initialization
-        private static class FunctionsHolder {
-            private static final XDHFunctions instance = new XDHFunctions();
-        }
-
-        private static XDHFunctions getInstance() {
-            return FunctionsHolder.instance;
-        }
+    private static class XDHScheme implements NamedGroupScheme {
+        private static final XDHScheme instance = new XDHScheme();
 
         @Override
         public byte[] encodePossessionPublicKey(NamedGroupPossession poss) {
@@ -732,8 +632,8 @@
         @Override
         public SSLCredentials decodeCredentials(NamedGroup ng, byte[] encoded,
                 AlgorithmConstraints constraints,
-                ExceptionSupplier onConstraintFail)
-                throws IOException, GeneralSecurityException {
+                ExceptionSupplier onConstraintFail
+            ) throws IOException, GeneralSecurityException {
 
             XDHKeyExchange.XDHECredentials result
                     = XDHKeyExchange.XDHECredentials.valueOf(ng, encoded);
@@ -751,31 +651,9 @@
         }
 
         @Override
-        public SSLKeyDerivation createKeyDerivation(HandshakeContext hc)
-                throws IOException {
+        public SSLKeyDerivation createKeyDerivation(
+                HandshakeContext hc) throws IOException {
             return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
         }
-
-        @Override
-        public AlgorithmParameterSpec getParameterSpec(NamedGroup ng) {
-            return new NamedParameterSpec(ng.name);
-        }
-
-        @Override
-        public boolean isAvailable(NamedGroup ng) {
-
-            try {
-                KeyAgreement.getInstance(ng.algorithm);
-                return true;
-            } catch (NoSuchAlgorithmException ex) {
-                return false;
-            }
-        }
-
-        @Override
-        protected Optional<AlgorithmParameters> getParametersImpl(
-                NamedGroup ng) {
-            return Optional.empty();
-        }
     }
 }
--- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java	Wed Aug 14 08:23:16 2019 -0400
@@ -38,7 +38,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 import sun.security.ssl.X509Authentication.X509Possession;
 import sun.security.util.KeyUtil;
@@ -149,7 +149,7 @@
     final String name;                  // literal name
     private final String algorithm;     // signature algorithm
     final String keyAlgorithm;          // signature key algorithm
-    private final AlgorithmParameterSpec signAlgParameter;
+    private final SigAlgParamSpec signAlgParams;    // signature parameters
     private final NamedGroup namedGroup;    // associated named group
 
     // The minimal required key size in bits.
@@ -184,21 +184,25 @@
         RSA_PSS_SHA384 ("SHA-384", 48),
         RSA_PSS_SHA512 ("SHA-512", 64);
 
-        final private AlgorithmParameterSpec parameterSpec;
-        final boolean isAvailable;
+        private final AlgorithmParameterSpec parameterSpec;
+        private final AlgorithmParameters parameters;
+        private final boolean isAvailable;
 
         SigAlgParamSpec(String hash, int saltLength) {
             // See RFC 8017
             PSSParameterSpec pssParamSpec =
                     new PSSParameterSpec(hash, "MGF1",
                             new MGF1ParameterSpec(hash), saltLength, 1);
+            AlgorithmParameters pssParams = null;
 
             boolean mediator = true;
             try {
                 Signature signer = Signature.getInstance("RSASSA-PSS");
                 signer.setParameter(pssParamSpec);
+                pssParams = signer.getParameters();
             } catch (InvalidAlgorithmParameterException |
-                    NoSuchAlgorithmException exp) {
+                    NoSuchAlgorithmException | RuntimeException exp) {
+                // Signature.getParameters() may throw RuntimeException.
                 mediator = false;
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.warning(
@@ -209,10 +213,7 @@
 
             this.isAvailable = mediator;
             this.parameterSpec = mediator ? pssParamSpec : null;
-        }
-
-        AlgorithmParameterSpec getParameterSpec() {
-            return parameterSpec;
+            this.parameters = mediator ? pssParams : null;
         }
     }
 
@@ -255,7 +256,7 @@
 
     private SignatureScheme(int id, String name,
             String algorithm, String keyAlgorithm,
-            SigAlgParamSpec signAlgParamSpec,
+            SigAlgParamSpec signAlgParams,
             NamedGroup namedGroup, int minimalKeySize,
             ProtocolVersion[] supportedProtocols,
             ProtocolVersion[] handshakeSupportedProtocols) {
@@ -263,8 +264,7 @@
         this.name = name;
         this.algorithm = algorithm;
         this.keyAlgorithm = keyAlgorithm;
-        this.signAlgParameter =
-            signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
+        this.signAlgParams = signAlgParams;
         this.namedGroup = namedGroup;
         this.minimalKeySize = minimalKeySize;
         this.supportedProtocols = Arrays.asList(supportedProtocols);
@@ -272,8 +272,8 @@
                 Arrays.asList(handshakeSupportedProtocols);
 
         boolean mediator = true;
-        if (signAlgParamSpec != null) {
-            mediator = signAlgParamSpec.isAvailable;
+        if (signAlgParams != null) {
+            mediator = signAlgParams.isAvailable;
         } else {
             try {
                 Signature.getInstance(algorithm);
@@ -331,6 +331,18 @@
         return 2;
     }
 
+    private boolean isPermitted(AlgorithmConstraints constraints) {
+        return constraints.permits(SIGNATURE_PRIMITIVE_SET,
+                        this.name, null) &&
+               constraints.permits(SIGNATURE_PRIMITIVE_SET,
+                        this.keyAlgorithm, null) &&
+               constraints.permits(SIGNATURE_PRIMITIVE_SET,
+                        this.algorithm, (signAlgParams != null ?
+                                signAlgParams.parameters : null)) &&
+               (namedGroup != null ?
+                        namedGroup.isPermitted(constraints) : true);
+    }
+
     // Get local supported algorithm collection complying to algorithm
     // constraints.
     static List<SignatureScheme> getSupportedAlgorithms(
@@ -351,8 +363,7 @@
             }
 
             if (isMatch) {
-                if (constraints.permits(
-                        SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
+                if (ss.isPermitted(constraints)) {
                     supported.add(ss);
                 } else if (SSLLogger.isOn &&
                         SSLLogger.isOn("ssl,handshake,verbose")) {
@@ -383,8 +394,7 @@
                 }
             } else if (ss.isAvailable &&
                     ss.supportedProtocols.contains(protocolVersion) &&
-                    constraints.permits(SIGNATURE_PRIMITIVE_SET,
-                           ss.algorithm, null)) {
+                    ss.isPermitted(constraints)) {
                 supported.add(ss);
             } else {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@@ -398,6 +408,7 @@
     }
 
     static SignatureScheme getPreferableAlgorithm(
+            AlgorithmConstraints constraints,
             List<SignatureScheme> schemes,
             SignatureScheme certScheme,
             ProtocolVersion version) {
@@ -405,8 +416,8 @@
         for (SignatureScheme ss : schemes) {
             if (ss.isAvailable &&
                     ss.handshakeSupportedProtocols.contains(version) &&
-                    certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
-
+                    certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
+                    ss.isPermitted(constraints)) {
                 return ss;
             }
         }
@@ -415,6 +426,7 @@
     }
 
     static SignatureScheme getPreferableAlgorithm(
+            AlgorithmConstraints constraints,
             List<SignatureScheme> schemes,
             X509Possession x509Possession,
             ProtocolVersion version) {
@@ -432,9 +444,10 @@
         for (SignatureScheme ss : schemes) {
             if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
                     ss.handshakeSupportedProtocols.contains(version) &&
-                    keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
-                if ((ss.namedGroup != null) && (ss.namedGroup.type ==
-                        NamedGroupType.NAMED_GROUP_ECDHE)) {
+                    keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
+                    ss.isPermitted(constraints)) {
+                if ((ss.namedGroup != null) && (ss.namedGroup.spec ==
+                        NamedGroupSpec.NAMED_GROUP_ECDHE)) {
                     ECParameterSpec params =
                             x509Possession.getECParameterSpec();
                     if (params != null &&
@@ -505,10 +518,13 @@
         Signature signer = Signature.getInstance(algorithm);
         if (key instanceof PublicKey) {
             SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
-                    signAlgParameter);
+                    (signAlgParams != null ?
+                            signAlgParams.parameterSpec : null));
         } else {
             SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
-                    signAlgParameter, null);
+                    (signAlgParams != null ?
+                            signAlgParams.parameterSpec : null),
+                    null);
         }
 
         return signer;
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Wed Aug 14 08:23:16 2019 -0400
@@ -28,20 +28,15 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.security.AlgorithmConstraints;
-import java.security.AlgorithmParameters;
-import java.security.CryptoPrimitive;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import javax.net.ssl.SSLProtocolException;
 import sun.security.action.GetPropertyAction;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
 import sun.security.ssl.SSLExtension.ExtensionConsumer;
@@ -188,7 +183,7 @@
                     if (!group.isEmpty()) {
                         NamedGroup namedGroup = NamedGroup.nameOf(group);
                         if (namedGroup != null) {
-                            if (isAvailableGroup(namedGroup)) {
+                            if (namedGroup.isAvailable) {
                                 groupList.add(namedGroup);
                             }
                         }   // ignore unknown groups
@@ -235,7 +230,7 @@
 
                 groupList = new ArrayList<>(groups.length);
                 for (NamedGroup group : groups) {
-                    if (isAvailableGroup(group)) {
+                    if (group.isAvailable) {
                         groupList.add(group);
                     }
                 }
@@ -253,48 +248,19 @@
             }
         }
 
-        // check whether the group is supported by the underlying providers
-        private static boolean isAvailableGroup(NamedGroup namedGroup) {
-            return namedGroup.isAvailableGroup();
-        }
-
-        static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) {
-            if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) {
-                 throw new RuntimeException(
-                         "Not a named EC group: " + ng);
-            }
-
-            // parameters are non-null
-            AlgorithmParameters params = ng.getParameters();
-            try {
-                return params.getParameterSpec(ECGenParameterSpec.class);
-            } catch (InvalidParameterSpecException ipse) {
-                // should be unlikely
-                return new ECGenParameterSpec(ng.oid);
-            }
-        }
-
-        static AlgorithmParameters getParameters(NamedGroup ng) {
-            return ng.getParameters();
-        }
-
         // Is there any supported group permitted by the constraints?
         static boolean isActivatable(
-                AlgorithmConstraints constraints, NamedGroupType type) {
+                AlgorithmConstraints constraints, NamedGroupSpec type) {
 
             boolean hasFFDHEGroups = false;
             for (NamedGroup namedGroup : supportedNamedGroups) {
-                if (namedGroup.type == type) {
-                    if (constraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            namedGroup.algorithm,
-                            getParameters(namedGroup))) {
-
+                if (namedGroup.isAvailable && namedGroup.spec == type) {
+                    if (namedGroup.isPermitted(constraints)) {
                         return true;
                     }
 
                     if (!hasFFDHEGroups &&
-                            (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                            (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
                         hasFFDHEGroups = true;
                     }
                 }
@@ -306,20 +272,17 @@
             //
             // Note that the constraints checking on DHE parameters will be
             // performed during key exchanging in a handshake.
-            return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE;
+            return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
         }
 
         // Is the named group permitted by the constraints?
         static boolean isActivatable(
                 AlgorithmConstraints constraints, NamedGroup namedGroup) {
-            if (!isSupported(namedGroup)) {
+            if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
                 return false;
             }
 
-            return constraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            namedGroup.algorithm,
-                            getParameters(namedGroup));
+            return namedGroup.isPermitted(constraints);
         }
 
         // Is the named group supported?
@@ -335,16 +298,13 @@
 
         static NamedGroup getPreferredGroup(
                 ProtocolVersion negotiatedProtocol,
-                AlgorithmConstraints constraints, NamedGroupType[] types,
+                AlgorithmConstraints constraints, NamedGroupSpec[] types,
                 List<NamedGroup> requestedNamedGroups) {
             for (NamedGroup namedGroup : requestedNamedGroups) {
-                if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
+                if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
                         namedGroup.isAvailable(negotiatedProtocol) &&
                         isSupported(namedGroup) &&
-                        constraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                namedGroup.algorithm,
-                                getParameters(namedGroup))) {
+                        namedGroup.isPermitted(constraints)) {
                     return namedGroup;
                 }
             }
@@ -354,14 +314,11 @@
 
         static NamedGroup getPreferredGroup(
                 ProtocolVersion negotiatedProtocol,
-                AlgorithmConstraints constraints, NamedGroupType[] types) {
+                AlgorithmConstraints constraints, NamedGroupSpec[] types) {
             for (NamedGroup namedGroup : supportedNamedGroups) {
-                if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
+                if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
                         namedGroup.isAvailable(negotiatedProtocol) &&
-                        constraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                namedGroup.algorithm,
-                                getParameters(namedGroup))) {
+                        namedGroup.isPermitted(constraints)) {
                     return namedGroup;
                 }
             }
@@ -401,15 +358,13 @@
                 new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
                 if ((!SupportedGroups.enableFFDHE) &&
-                    (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                    (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
                     continue;
                 }
 
                 if (ng.isAvailable(chc.activeProtocols) &&
                         ng.isSupported(chc.activeCipherSuites) &&
-                        chc.algorithmConstraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            ng.algorithm, getParameters(ng))) {
+                        ng.isPermitted(chc.algorithmConstraints)) {
                     namedGroups.add(ng);
                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
@@ -528,15 +483,13 @@
                     SupportedGroups.supportedNamedGroups.length);
             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
                 if ((!SupportedGroups.enableFFDHE) &&
-                    (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                    (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
                     continue;
                 }
 
                 if (ng.isAvailable(shc.activeProtocols) &&
                         ng.isSupported(shc.activeCipherSuites) &&
-                        shc.algorithmConstraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            ng.algorithm, getParameters(ng))) {
+                        ng.isPermitted(shc.algorithmConstraints)) {
                     namedGroups.add(ng);
                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
--- a/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java	Wed Aug 14 08:23:16 2019 -0400
@@ -29,7 +29,7 @@
 import java.security.*;
 import java.security.interfaces.XECPublicKey;
 import java.security.spec.*;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import sun.security.util.*;
 
 /**
@@ -68,7 +68,7 @@
                 byte[] encodedPoint) throws IOException,
                 GeneralSecurityException {
 
-            if (namedGroup.type != NamedGroupType.NAMED_GROUP_XDH) {
+            if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_XDH) {
                 throw new RuntimeException(
                         "Credentials decoding:  Not XDH named group");
             }
@@ -101,8 +101,7 @@
             try {
                 KeyPairGenerator kpg
                         = KeyPairGenerator.getInstance(namedGroup.algorithm);
-                AlgorithmParameterSpec params = namedGroup.getParameterSpec();
-                kpg.initialize(params, random);
+                kpg.initialize(namedGroup.keAlgParamSpec, random);
                 KeyPair kp = kpg.generateKeyPair();
                 privateKey = kp.getPrivate();
                 publicKey = (XECPublicKey) kp.getPublic();
--- a/src/java.base/share/classes/sun/security/util/CurveDB.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/classes/sun/security/util/CurveDB.java	Wed Aug 14 08:23:16 2019 -0400
@@ -62,7 +62,7 @@
     }
 
     // Return a NamedCurve for the specified OID/name or null if unknown.
-    static NamedCurve lookup(String name) {
+    public static NamedCurve lookup(String name) {
         NamedCurve spec = oidMap.get(name);
         if (spec != null) {
             return spec;
@@ -83,7 +83,7 @@
 
     // Convert the given ECParameterSpec object to a NamedCurve object.
     // If params does not represent a known named curve, return null.
-    static NamedCurve lookup(ECParameterSpec params) {
+    public static NamedCurve lookup(ECParameterSpec params) {
         if ((params instanceof NamedCurve) || (params == null)) {
             return (NamedCurve)params;
         }
--- a/src/java.base/share/conf/security/java.security	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.base/share/conf/security/java.security	Wed Aug 14 08:23:16 2019 -0400
@@ -541,9 +541,9 @@
 #       usage [TLSServer] [TLSClient] [SignedJAR]
 #
 # The "AlgorithmName" is the standard algorithm name of the disabled
-# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
-# Documentation" for information about Standard Algorithm Names.  Matching
-# is performed using a case-insensitive sub-element matching rule.  (For
+# algorithm. See the Java Security Standard Algorithm Names Specification
+# for information about Standard Algorithm Names.  Matching is
+# performed using a case-insensitive sub-element matching rule.  (For
 # example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
 # "ECDSA" for signatures.)  If the assertion "AlgorithmName" is a
 # sub-element of the certificate algorithm name, the algorithm will be
@@ -677,8 +677,9 @@
 # In some environments, certain algorithms or key lengths may be undesirable
 # when using SSL/TLS/DTLS.  This section describes the mechanism for disabling
 # algorithms during SSL/TLS/DTLS security parameters negotiation, including
-# protocol version negotiation, cipher suites selection, peer authentication
-# and key exchange mechanisms.
+# protocol version negotiation, cipher suites selection, named groups
+# selection, signature schemes selection, peer authentication and key
+# exchange mechanisms.
 #
 # Disabled algorithms will not be negotiated for SSL/TLS connections, even
 # if they are enabled explicitly in an application.
@@ -699,7 +700,8 @@
 # It is not guaranteed to be examined and used by other implementations.
 #
 # Example:
-#   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
+#   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \
+#       rsa_pkcs1_sha1, secp224r1
 jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
     EC keySize < 224, 3DES_EDE_CBC, anon, NULL
 
@@ -743,8 +745,8 @@
 #     3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC
 #     4. JSSE message digest algorithm name, e.g., SHA
 #
-# See SSL/TLS specifications and "Java Cryptography Architecture Standard
-# Algorithm Name Documentation" for information about the algorithm names.
+# See SSL/TLS specifications and the Java Security Standard Algorithm Names
+# Specification for information about the algorithm names.
 #
 # Note: If a legacy algorithm is also restricted through the
 # jdk.tls.disabledAlgorithms property or the
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -224,7 +224,6 @@
     String hostname = null;             // host name of server (no brackets
                                         //   for IPv6 literals)
     LdapClient clnt = null;             // connection handle
-    private boolean reconnect = false;  // indicates that re-connect requested
     Hashtable<String, java.lang.Object> envprops = null; // environment properties of context
     int handleReferrals = DEFAULT_REFERRAL_MODE; // how referral is handled
     boolean hasLdapsScheme = false;     // true if the context was created
@@ -2668,7 +2667,6 @@
         }
 
         sharable = false;  // can't share with existing contexts
-        reconnect = true;
         ensureOpen();      // open or reauthenticated
     }
 
@@ -2693,7 +2691,8 @@
                 synchronized (clnt) {
                     if (!clnt.isLdapv3
                         || clnt.referenceCount > 1
-                        || clnt.usingSaslStreams()) {
+                        || clnt.usingSaslStreams()
+                        || !clnt.conn.useable) {
                         closeConnection(SOFT_CLOSE);
                     }
                 }
@@ -2745,7 +2744,7 @@
         try {
             boolean initial = (clnt == null);
 
-            if (initial || reconnect) {
+            if (initial) {
                 ldapVersion = (ver != null) ? Integer.parseInt(ver) :
                     DEFAULT_LDAP_VERSION;
 
@@ -2773,8 +2772,6 @@
                     // Required for SASL client identity
                     envprops);
 
-                reconnect = false;
-
                 /**
                  * Pooled connections are preauthenticated;
                  * newly created ones are not.
--- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -124,7 +124,7 @@
  ****************************************************************************/
 
     /**
-     * {@inheritDoc} This implementation returns {@code null}.
+     * {@inheritDoc} This implementation scans the children in left to right order.
      *
      * @param node  {@inheritDoc}
      * @param p  {@inheritDoc}
@@ -132,7 +132,7 @@
      */
     @Override
     public R visitAttribute(AttributeTree node, P p) {
-        return null;
+        return scan(node.getValue(), p);
     }
 
     /**
@@ -311,7 +311,7 @@
     }
 
     /**
-     * {@inheritDoc} This implementation returns {@code null}.
+     * {@inheritDoc} This implementation scans the children in left to right order.
      *
      * @param node  {@inheritDoc}
      * @param p  {@inheritDoc}
@@ -319,7 +319,7 @@
      */
     @Override
     public R visitLiteral(LiteralTree node, P p) {
-        return null;
+        return scan(node.getBody(), p);
     }
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java	Wed Aug 14 08:23:16 2019 -0400
@@ -685,7 +685,7 @@
 
         // TODO: basic check on value
 
-        return super.visitAttribute(tree, ignore);
+        return null;
     }
 
     private void validateHtml4Attrs(AttributeTree tree, Name name, AttrKind k) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Wed Aug 14 08:23:16 2019 -0400
@@ -808,8 +808,11 @@
                            checkType(var, Double.class, v);
                            break;
                        case CLASS:
-                           Assert.check(var.type.tsym == syms.stringType.tsym);
-                           checkType(var, String.class, v);
+                           if (var.type.tsym == syms.stringType.tsym) {
+                               checkType(var, String.class, v);
+                           } else {
+                               throw badClassFile("bad.constant.value.type", var.type);
+                           }
                            break;
                        default:
                            // ignore ConstantValue attribute if type is not primitive or String
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Aug 14 08:23:16 2019 -0400
@@ -3756,23 +3756,59 @@
     List<JCTree> enumBody(Name enumName) {
         accept(LBRACE);
         ListBuffer<JCTree> defs = new ListBuffer<>();
+        boolean wasSemi = false;
+        boolean hasStructuralErrors = false;
+        boolean wasError = false;
         if (token.kind == COMMA) {
             nextToken();
-        } else if (token.kind != RBRACE && token.kind != SEMI) {
-            defs.append(enumeratorDeclaration(enumName));
-            while (token.kind == COMMA) {
+            if (token.kind == SEMI) {
+                wasSemi = true;
                 nextToken();
-                if (token.kind == RBRACE || token.kind == SEMI) break;
-                defs.append(enumeratorDeclaration(enumName));
-            }
-            if (token.kind != SEMI && token.kind != RBRACE) {
-                defs.append(syntaxError(token.pos, Errors.Expected3(COMMA, RBRACE, SEMI)));
-                nextToken();
+            } else if (token.kind != RBRACE) {
+                reportSyntaxError(S.prevToken().endPos,
+                                  Errors.Expected2(RBRACE, SEMI));
+                wasError = true;
             }
         }
-        if (token.kind == SEMI) {
-            nextToken();
-            while (token.kind != RBRACE && token.kind != EOF) {
+        while (token.kind != RBRACE && token.kind != EOF) {
+            if (token.kind == SEMI) {
+                accept(SEMI);
+                wasSemi = true;
+                if (token.kind == RBRACE || token.kind == EOF) break;
+            }
+            EnumeratorEstimate memberType = estimateEnumeratorOrMember(enumName);
+            if (memberType == EnumeratorEstimate.UNKNOWN) {
+                memberType = wasSemi ? EnumeratorEstimate.MEMBER
+                                     : EnumeratorEstimate.ENUMERATOR;
+            }
+            if (memberType == EnumeratorEstimate.ENUMERATOR) {
+                wasError = false;
+                if (wasSemi && !hasStructuralErrors) {
+                    reportSyntaxError(token.pos, Errors.EnumConstantNotExpected);
+                    hasStructuralErrors = true;
+                }
+                defs.append(enumeratorDeclaration(enumName));
+                if (token.pos <= endPosTable.errorEndPos) {
+                    // error recovery
+                   skip(false, true, true, false);
+                } else {
+                    if (token.kind != RBRACE && token.kind != SEMI && token.kind != EOF) {
+                        if (token.kind == COMMA) {
+                            nextToken();
+                        } else {
+                            setErrorEndPos(token.pos);
+                            reportSyntaxError(S.prevToken().endPos,
+                                              Errors.Expected3(COMMA, RBRACE, SEMI));
+                            wasError = true;
+                        }
+                    }
+                }
+            } else {
+                if (!wasSemi && !hasStructuralErrors && !wasError) {
+                    reportSyntaxError(token.pos, Errors.EnumConstantExpected);
+                    hasStructuralErrors = true;
+                }
+                wasError = false;
                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
                                                                 false));
                 if (token.pos <= endPosTable.errorEndPos) {
@@ -3785,6 +3821,28 @@
         return defs.toList();
     }
 
+    private EnumeratorEstimate estimateEnumeratorOrMember(Name enumName) {
+        if (token.kind == TokenKind.IDENTIFIER && token.name() != enumName) {
+            Token next = S.token(1);
+            switch (next.kind) {
+                case LPAREN: case LBRACE: case COMMA: case SEMI:
+                    return EnumeratorEstimate.ENUMERATOR;
+            }
+        }
+        switch (token.kind) {
+            case IDENTIFIER: case MONKEYS_AT: case LT:
+                return EnumeratorEstimate.UNKNOWN;
+            default:
+                return EnumeratorEstimate.MEMBER;
+        }
+    }
+
+    private enum EnumeratorEstimate {
+        ENUMERATOR,
+        MEMBER,
+        UNKNOWN;
+    }
+
     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
      */
     JCTree enumeratorDeclaration(Name enumName) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Aug 14 08:23:16 2019 -0400
@@ -2158,6 +2158,12 @@
 compiler.err.premature.eof=\
     reached end of file while parsing
 
+compiler.err.enum.constant.expected=\
+    enum constant expected here
+
+compiler.err.enum.constant.not.expected=\
+    enum constant not expected here
+
 ## The following are related in form, but do not easily fit the above paradigm.
 compiler.err.expected.module=\
     ''module'' expected
@@ -2275,6 +2281,10 @@
 compiler.misc.bad.constant.value=\
     bad constant value ''{0}'' for {1}, expected {2}
 
+# 0: type (field type)
+compiler.misc.bad.constant.value.type=\
+    variable of type ''{0}'' cannot have a constant value, but has one specified
+
 # 0: string (classfile major version), 1: string (classfile minor version)
 compiler.misc.invalid.default.interface=\
     default method found in version {0}.{1} classfile
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c	Wed Aug 14 08:23:16 2019 -0400
@@ -73,7 +73,7 @@
 
 
 /*
- * converts a pointer to a CK_DATE structure into a Java CK_DATE Object.
+ * converts a CK_DATE pointer into a Java CK_DATE Object.
  *
  * @param env - used to call JNI funktions to create the new Java object
  * @param ckpValue - the pointer to the CK_DATE structure
@@ -119,11 +119,11 @@
 }
 
 /*
- * converts a pointer to a CK_VERSION structure into a Java CK_VERSION Object.
+ * converts a CK_VERSION pointer into a Java CK_VERSION Object.
  *
  * @param env - used to call JNI funktions to create the new Java object
  * @param ckpVersion - the pointer to the CK_VERSION structure
- * @return - the new Java CK_VERSION object
+ * @return the new Java CK_VERSION object
  */
 jobject ckVersionPtrToJVersion(JNIEnv *env, const CK_VERSION_PTR ckpVersion)
 {
@@ -157,11 +157,11 @@
 }
 
 /*
- * converts a pointer to a CK_SESSION_INFO structure into a Java CK_SESSION_INFO Object.
+ * converts a CK_SESSION_INFO pointer into a Java CK_SESSION_INFO Object.
  *
  * @param env - used to call JNI funktions to create the new Java object
  * @param ckpSessionInfo - the pointer to the CK_SESSION_INFO structure
- * @return - the new Java CK_SESSION_INFO object
+ * @return the new Java CK_SESSION_INFO object
  */
 jobject ckSessionInfoPtrToJSessionInfo(JNIEnv *env, const CK_SESSION_INFO_PTR ckpSessionInfo)
 {
@@ -200,11 +200,11 @@
 }
 
 /*
- * converts a pointer to a CK_ATTRIBUTE structure into a Java CK_ATTRIBUTE Object.
+ * converts a CK_ATTRIBUTE pointer into a Java CK_ATTRIBUTE Object.
  *
  * @param env - used to call JNI funktions to create the new Java object
  * @param ckpAttribute - the pointer to the CK_ATTRIBUTE structure
- * @return - the new Java CK_ATTRIBUTE object
+ * @return the new Java CK_ATTRIBUTE object
  */
 jobject ckAttributePtrToJAttribute(JNIEnv *env, const CK_ATTRIBUTE_PTR ckpAttribute)
 {
@@ -240,13 +240,14 @@
 
 
 /*
- * converts a Java CK_VERSION object into a pointer to a CK_VERSION structure
+ * converts a Java CK_VERSION object into a CK_VERSION pointer
  *
  * @param env - used to call JNI funktions to get the values out of the Java object
  * @param jVersion - the Java CK_VERSION object to convert
- * @return - the pointer to the new CK_VERSION structure
+ * @return pointer to the new CK_VERSION structure
  */
-CK_VERSION_PTR jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion)
+CK_VERSION_PTR
+jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion)
 {
     CK_VERSION_PTR ckpVersion;
     jclass jVersionClass;
@@ -257,80 +258,73 @@
         return NULL;
     }
 
-    /* get CK_VERSION class */
+    // retrieve java values
     jVersionClass = (*env)->GetObjectClass(env, jVersion);
     if (jVersionClass == NULL) { return NULL; }
-
-    /* get Major */
     jFieldID = (*env)->GetFieldID(env, jVersionClass, "major", "B");
     if (jFieldID == NULL) { return NULL; }
     jMajor = (*env)->GetByteField(env, jVersion, jFieldID);
-
-    /* get Minor */
     jFieldID = (*env)->GetFieldID(env, jVersionClass, "minor", "B");
     if (jFieldID == NULL) { return NULL; }
     jMinor = (*env)->GetByteField(env, jVersion, jFieldID);
 
-    /* allocate memory for CK_VERSION pointer */
-    ckpVersion = (CK_VERSION_PTR) malloc(sizeof(CK_VERSION));
+    // allocate memory for CK_VERSION pointer
+    ckpVersion = (CK_VERSION_PTR) calloc(1, sizeof(CK_VERSION));
     if (ckpVersion == NULL) {
         throwOutOfMemoryError(env, 0);
         return NULL;
     }
+
+    // populate using java values
     ckpVersion->major = jByteToCKByte(jMajor);
     ckpVersion->minor = jByteToCKByte(jMinor);
 
-    return ckpVersion ;
+    return ckpVersion;
 }
 
 
 /*
- * converts a Java CK_DATE object into a pointer to a CK_DATE structure
+ * converts a Java CK_DATE object into a CK_DATE pointer
  *
- * @param env - used to call JNI funktions to get the values out of the Java object
- * @param jVersion - the Java CK_DATE object to convert
- * @return - the pointer to the new CK_DATE structure
+ * @param env - used to call JNI functions to get the values out of the Java object
+ * @param jDate - the Java CK_DATE object to convert
+ * @return pointer to the new CK_DATE structure
  */
-CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate)
+CK_DATE * jDateObjectToCKDatePtr(JNIEnv *env, jobject jDate)
 {
-    CK_DATE * ckpDate;
+    CK_DATE * ckpDate = NULL;
     CK_ULONG ckLength;
     jclass jDateClass;
     jfieldID jFieldID;
     jobject jYear, jMonth, jDay;
-    jchar *jTempChars;
+    jchar *jTempChars = NULL;
     CK_ULONG i;
 
     if (jDate == NULL) {
         return NULL;
     }
 
-    /* get CK_DATE class */
+    // retrieve java values
     jDateClass = (*env)->FindClass(env, CLASS_DATE);
     if (jDateClass == NULL) { return NULL; }
-
-    /* get Year */
     jFieldID = (*env)->GetFieldID(env, jDateClass, "year", "[C");
     if (jFieldID == NULL) { return NULL; }
     jYear = (*env)->GetObjectField(env, jDate, jFieldID);
-
-    /* get Month */
     jFieldID = (*env)->GetFieldID(env, jDateClass, "month", "[C");
     if (jFieldID == NULL) { return NULL; }
     jMonth = (*env)->GetObjectField(env, jDate, jFieldID);
-
-    /* get Day */
     jFieldID = (*env)->GetFieldID(env, jDateClass, "day", "[C");
     if (jFieldID == NULL) { return NULL; }
     jDay = (*env)->GetObjectField(env, jDate, jFieldID);
 
-    /* allocate memory for CK_DATE pointer */
-    ckpDate = (CK_DATE *) malloc(sizeof(CK_DATE));
+    // allocate memory for CK_DATE pointer
+    ckpDate = (CK_DATE *) calloc(1, sizeof(CK_DATE));
     if (ckpDate == NULL) {
         throwOutOfMemoryError(env, 0);
         return NULL;
     }
 
+    // populate using java values
     if (jYear == NULL) {
         ckpDate->year[0] = 0;
         ckpDate->year[1] = 0;
@@ -338,17 +332,14 @@
         ckpDate->year[3] = 0;
     } else {
         ckLength = (*env)->GetArrayLength(env, jYear);
-        jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
+        jTempChars = (jchar*) calloc(ckLength, sizeof(jchar));
         if (jTempChars == NULL) {
-            free(ckpDate);
             throwOutOfMemoryError(env, 0);
-            return NULL;
+            goto cleanup;
         }
         (*env)->GetCharArrayRegion(env, jYear, 0, ckLength, jTempChars);
         if ((*env)->ExceptionCheck(env)) {
-            free(ckpDate);
-            free(jTempChars);
-            return NULL;
+            goto cleanup;
         }
 
         for (i = 0; (i < ckLength) && (i < 4) ; i++) {
@@ -362,17 +353,14 @@
         ckpDate->month[1] = 0;
     } else {
         ckLength = (*env)->GetArrayLength(env, jMonth);
-        jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
+        jTempChars = (jchar*) calloc(ckLength, sizeof(jchar));
         if (jTempChars == NULL) {
-            free(ckpDate);
             throwOutOfMemoryError(env, 0);
-            return NULL;
+            goto cleanup;
         }
         (*env)->GetCharArrayRegion(env, jMonth, 0, ckLength, jTempChars);
         if ((*env)->ExceptionCheck(env)) {
-            free(ckpDate);
-            free(jTempChars);
-            return NULL;
+            goto cleanup;
         }
 
         for (i = 0; (i < ckLength) && (i < 2) ; i++) {
@@ -386,17 +374,14 @@
         ckpDate->day[1] = 0;
     } else {
         ckLength = (*env)->GetArrayLength(env, jDay);
-        jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar));
+        jTempChars = (jchar*) calloc(ckLength, sizeof(jchar));
         if (jTempChars == NULL) {
-            free(ckpDate);
             throwOutOfMemoryError(env, 0);
-            return NULL;
+            goto cleanup;
         }
         (*env)->GetCharArrayRegion(env, jDay, 0, ckLength, jTempChars);
         if ((*env)->ExceptionCheck(env)) {
-            free(ckpDate);
-            free(jTempChars);
-            return NULL;
+            goto cleanup;
         }
 
         for (i = 0; (i < ckLength) && (i < 2) ; i++) {
@@ -405,7 +390,11 @@
         free(jTempChars);
     }
 
-    return ckpDate ;
+    return ckpDate;
+cleanup:
+    free(jTempChars);
+    free(ckpDate);
+    return NULL;
 }
 
 
@@ -414,7 +403,7 @@
  *
  * @param env - used to call JNI funktions to get the values out of the Java object
  * @param jAttribute - the Java CK_ATTRIBUTE object to convert
- * @return - the new CK_ATTRIBUTE structure
+ * @return the new CK_ATTRIBUTE structure
  */
 CK_ATTRIBUTE jAttributeToCKAttribute(JNIEnv *env, jobject jAttribute)
 {
@@ -423,6 +412,7 @@
     jfieldID jFieldID;
     jlong jType;
     jobject jPValue;
+
     memset(&ckAttribute, 0, sizeof(CK_ATTRIBUTE));
 
     // TBD: what if jAttribute == NULL?!
@@ -466,187 +456,279 @@
     jclass jSsl3RandomDataClass;
     jobject jRandomInfo, jRIClientRandom, jRIServerRandom, jVersion;
 
-    /* get RandomInfo */
+    // retrieve java values
     fieldID = (*env)->GetFieldID(env, masterKeyDeriveParamClass, "RandomInfo",
             "Lsun/security/pkcs11/wrapper/CK_SSL3_RANDOM_DATA;");
     if (fieldID == NULL) { return; }
     jRandomInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pClientRandom and ulClientRandomLength out of RandomInfo */
     jSsl3RandomDataClass = (*env)->FindClass(env, CLASS_SSL3_RANDOM_DATA);
     if (jSsl3RandomDataClass == NULL) { return; }
     fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pClientRandom", "[B");
     if (fieldID == NULL) { return; }
     jRIClientRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
-    /* get pServerRandom and ulServerRandomLength out of RandomInfo */
     fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pServerRandom", "[B");
     if (fieldID == NULL) { return; }
     jRIServerRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
-    /* get pVersion */
     fieldID = (*env)->GetFieldID(env, masterKeyDeriveParamClass, "pVersion",
             "Lsun/security/pkcs11/wrapper/CK_VERSION;");
     if (fieldID == NULL) { return; }
     jVersion = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // populate using java values
     *cKMasterKeyDeriveParamVersion = jVersionToCKVersionPtr(env, jVersion);
     if ((*env)->ExceptionCheck(env)) { return; }
     jByteArrayToCKByteArray(env, jRIClientRandom,
             &(cKMasterKeyDeriveParamRandomInfo->pClientRandom),
             &(cKMasterKeyDeriveParamRandomInfo->ulClientRandomLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(*cKMasterKeyDeriveParamVersion);
-        return;
+        goto cleanup;
     }
     jByteArrayToCKByteArray(env, jRIServerRandom,
             &(cKMasterKeyDeriveParamRandomInfo->pServerRandom),
             &(cKMasterKeyDeriveParamRandomInfo->ulServerRandomLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(*cKMasterKeyDeriveParamVersion);
-        free(cKMasterKeyDeriveParamRandomInfo->pClientRandom);
-        return;
+        goto cleanup;
     }
+    return;
+cleanup:
+    free(*cKMasterKeyDeriveParamVersion);
+    free(cKMasterKeyDeriveParamRandomInfo->pClientRandom);
+    cKMasterKeyDeriveParamRandomInfo->ulClientRandomLen = 0L;
+    free(cKMasterKeyDeriveParamRandomInfo->pServerRandom);
+    cKMasterKeyDeriveParamRandomInfo->ulServerRandomLen = 0L;
+    // explicitly set to NULL to ensure no double free possible
+    *cKMasterKeyDeriveParamVersion = NULL;
+    cKMasterKeyDeriveParamRandomInfo->pClientRandom = NULL;
+    cKMasterKeyDeriveParamRandomInfo->pServerRandom = NULL;
 }
 
 /*
  * converts the Java CK_SSL3_MASTER_KEY_DERIVE_PARAMS object to a
- * CK_SSL3_MASTER_KEY_DERIVE_PARAMS structure
+ * CK_SSL3_MASTER_KEY_DERIVE_PARAMS pointer
  *
  * @param env - used to call JNI functions to get the Java classes and objects
  * @param jParam - the Java CK_SSL3_MASTER_KEY_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_SSL3_MASTER_KEY_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_SSL3_MASTER_KEY_DERIVE_PARAMS structure
  */
-void jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParam(JNIEnv *env,
-        jobject jParam, CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr)
+CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR
+jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(JNIEnv *env,
+        jobject jParam, CK_ULONG *pLength)
 {
+    CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr;
     jclass jSsl3MasterKeyDeriveParamsClass;
-    memset(ckParamPtr, 0, sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
+
+    if (pLength != NULL) {
+        *pLength = 0L;
+    }
+
+    // allocate memory for CK_SSL3_MASTER_KEY_DERIVE_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // retrieve and populate using java values
     jSsl3MasterKeyDeriveParamsClass =
             (*env)->FindClass(env, CLASS_SSL3_MASTER_KEY_DERIVE_PARAMS);
-    if (jSsl3MasterKeyDeriveParamsClass == NULL) { return; }
+    if (jSsl3MasterKeyDeriveParamsClass == NULL) {
+        goto cleanup;
+    }
     masterKeyDeriveParamToCKMasterKeyDeriveParam(env, jParam,
             jSsl3MasterKeyDeriveParamsClass,
             &(ckParamPtr->pVersion), &(ckParamPtr->RandomInfo));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
+    }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
  * converts the Java CK_TLS12_MASTER_KEY_DERIVE_PARAMS object to a
- * CK_TLS12_MASTER_KEY_DERIVE_PARAMS structure
+ * CK_TLS12_MASTER_KEY_DERIVE_PARAMS pointer
  *
  * @param env - used to call JNI functions to get the Java classes and objects
  * @param jParam - the Java CK_TLS12_MASTER_KEY_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_TLS12_MASTER_KEY_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS12_MASTER_KEY_DERIVE_PARAMS structure
  */
-void jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParam(JNIEnv *env,
-        jobject jParam, CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr)
+CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR
+jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParamPtr(JNIEnv *env,
+        jobject jParam, CK_ULONG *pLength)
 {
+    CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr;
     jclass jTls12MasterKeyDeriveParamsClass;
     jfieldID fieldID;
-    memset(ckParamPtr, 0, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS));
+    jlong prfHashMechanism;
+
+    if (pLength != NULL) {
+        *pLength = 0L;
+    }
+
+    // retrieve java values
     jTls12MasterKeyDeriveParamsClass =
-            (*env)->FindClass(env, CLASS_TLS12_MASTER_KEY_DERIVE_PARAMS);
-    if (jTls12MasterKeyDeriveParamsClass == NULL) { return; }
+        (*env)->FindClass(env, CLASS_TLS12_MASTER_KEY_DERIVE_PARAMS);
+    if (jTls12MasterKeyDeriveParamsClass == NULL) { return NULL; }
+    fieldID = (*env)->GetFieldID(env,
+            jTls12MasterKeyDeriveParamsClass, "prfHashMechanism", "J");
+    if (fieldID == NULL) { return NULL; }
+    prfHashMechanism = (*env)->GetLongField(env, jParam, fieldID);
+
+    // allocate memory for CK_TLS12_MASTER_KEY_DERIVE_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     masterKeyDeriveParamToCKMasterKeyDeriveParam(env, jParam,
             jTls12MasterKeyDeriveParamsClass, &ckParamPtr->pVersion,
             &ckParamPtr->RandomInfo);
-    fieldID = (*env)->GetFieldID(env,
-            jTls12MasterKeyDeriveParamsClass, "prfHashMechanism", "J");
-    if (fieldID != NULL) {
-        jlong prfHashMechanism =
-                (*env)->GetLongField(env, jParam, fieldID);
-        ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE)prfHashMechanism;
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
     }
+
+    ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE) prfHashMechanism;
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
+    }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_TLS_PRF_PARAMS object to a CK_TLS_PRF_PARAMS structure
+ * converts the Java CK_TLS_PRF_PARAMS object to a CK_TLS_PRF_PARAMS pointer
+ *
+ * @param env - used to call JNI functions to get the Java classes and objects
+ * @param jParam - the Java CK_TLS_PRF_PARAMS object to convert
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS_PRF_PARAMS structure
  */
-void jTlsPrfParamsToCKTlsPrfParam(JNIEnv *env, jobject jParam,
-CK_TLS_PRF_PARAMS_PTR ckParamPtr)
+CK_TLS_PRF_PARAMS_PTR
+jTlsPrfParamsToCKTlsPrfParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_TLS_PRF_PARAMS_PTR ckParamPtr;
     jclass jTlsPrfParamsClass;
     jfieldID fieldID;
     jobject jSeed, jLabel, jOutput;
-    memset(ckParamPtr, 0, sizeof(CK_TLS_PRF_PARAMS));
 
-    // TBD: what if jParam == NULL?!
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
 
-    /* get pSeed */
+    // retrieve java values
     jTlsPrfParamsClass = (*env)->FindClass(env, CLASS_TLS_PRF_PARAMS);
-    if (jTlsPrfParamsClass == NULL) { return; }
+    if (jTlsPrfParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jTlsPrfParamsClass, "pSeed", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSeed = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pLabel */
     fieldID = (*env)->GetFieldID(env, jTlsPrfParamsClass, "pLabel", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jLabel = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pOutput */
     fieldID = (*env)->GetFieldID(env, jTlsPrfParamsClass, "pOutput", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jOutput = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_TLS_PRF_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_TLS_PRF_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     jByteArrayToCKByteArray(env, jSeed, &(ckParamPtr->pSeed), &(ckParamPtr->ulSeedLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
     jByteArrayToCKByteArray(env, jLabel, &(ckParamPtr->pLabel), &(ckParamPtr->ulLabelLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pSeed);
-        return;
+        goto cleanup;
     }
-    ckParamPtr->pulOutputLen = malloc(sizeof(CK_ULONG));
+    ckParamPtr->pulOutputLen = calloc(1, sizeof(CK_ULONG));
     if (ckParamPtr->pulOutputLen == NULL) {
-        free(ckParamPtr->pSeed);
-        free(ckParamPtr->pLabel);
-        throwOutOfMemoryError(env, 0);
-        return;
+        goto cleanup;
     }
     jByteArrayToCKByteArray(env, jOutput, &(ckParamPtr->pOutput), ckParamPtr->pulOutputLen);
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pSeed);
-        free(ckParamPtr->pLabel);
-        free(ckParamPtr->pOutput);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_TLS_PRF_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pSeed);
+    free(ckParamPtr->pLabel);
+    free(ckParamPtr->pOutput);
+    free(ckParamPtr->pulOutputLen);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_TLS_MAC_PARAMS object to a CK_TLS_MAC_PARAMS structure
+ * converts the Java CK_TLS_MAC_PARAMS object to a CK_TLS_MAC_PARAMS pointer
+ *
+ * @param env - used to call JNI functions to get the Java classes and objects
+ * @param jParam - the Java CK_TLS_MAC_PARAMS object to convert
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS_MAC_PARAMS structure
  */
-void jTlsMacParamsToCKTlsMacParam(JNIEnv *env, jobject jParam,
-        CK_TLS_MAC_PARAMS_PTR ckParamPtr)
+
+CK_TLS_MAC_PARAMS_PTR
+jTlsMacParamsToCKTlsMacParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_TLS_MAC_PARAMS_PTR ckParamPtr;
     jclass jTlsMacParamsClass;
     jfieldID fieldID;
     jlong jPrfMechanism, jUlMacLength, jUlServerOrClient;
-    memset(ckParamPtr, 0, sizeof(CK_TLS_MAC_PARAMS));
 
+    if (pLength != NULL) {
+        *pLength = 0L;
+    }
+
+    // retrieve java values
     jTlsMacParamsClass = (*env)->FindClass(env, CLASS_TLS_MAC_PARAMS);
-    if (jTlsMacParamsClass == NULL) { return; }
-
-    /* get prfMechanism */
+    if (jTlsMacParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jTlsMacParamsClass, "prfMechanism", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrfMechanism = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get ulMacLength */
     fieldID = (*env)->GetFieldID(env, jTlsMacParamsClass, "ulMacLength", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jUlMacLength = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get ulServerOrClient */
     fieldID = (*env)->GetFieldID(env, jTlsMacParamsClass, "ulServerOrClient", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jUlServerOrClient = (*env)->GetLongField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_TLS_MAC_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_TLS_MAC_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->prfMechanism = jLongToCKULong(jPrfMechanism);
     ckParamPtr->ulMacLength = jLongToCKULong(jUlMacLength);
     ckParamPtr->ulServerOrClient = jLongToCKULong(jUlServerOrClient);
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_TLS_MAC_PARAMS);
+    }
+    return ckParamPtr;
 }
 
 void keyMatParamToCKKeyMatParam(JNIEnv *env, jobject jParam,
@@ -666,63 +748,47 @@
     jobject jReturnedKeyMaterial, jRMIvClient, jRMIvServer;
     CK_ULONG ckTemp;
 
-    /* get ulMacSizeInBits */
+    // the pointer arguments should already be initialized by caller
+
+    // retrieve java values
     fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "ulMacSizeInBits", "J");
     if (fieldID == NULL) { return; }
     jMacSizeInBits = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get ulKeySizeInBits */
     fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "ulKeySizeInBits", "J");
     if (fieldID == NULL) { return; }
     jKeySizeInBits = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get ulIVSizeInBits */
     fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "ulIVSizeInBits", "J");
     if (fieldID == NULL) { return; }
     jIVSizeInBits = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get bIsExport */
     fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "bIsExport", "Z");
     if (fieldID == NULL) { return; }
     jIsExport = (*env)->GetBooleanField(env, jParam, fieldID);
-
-    /* get RandomInfo */
     jSsl3RandomDataClass = (*env)->FindClass(env, CLASS_SSL3_RANDOM_DATA);
     if (jSsl3RandomDataClass == NULL) { return; }
     fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "RandomInfo",
             "Lsun/security/pkcs11/wrapper/CK_SSL3_RANDOM_DATA;");
     if (fieldID == NULL) { return; }
     jRandomInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pClientRandom and ulClientRandomLength out of RandomInfo */
     fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pClientRandom", "[B");
     if (fieldID == NULL) { return; }
     jRIClientRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
-    /* get pServerRandom and ulServerRandomLength out of RandomInfo */
     fieldID = (*env)->GetFieldID(env, jSsl3RandomDataClass, "pServerRandom", "[B");
     if (fieldID == NULL) { return; }
     jRIServerRandom = (*env)->GetObjectField(env, jRandomInfo, fieldID);
-
-    /* get pReturnedKeyMaterial */
     jSsl3KeyMatOutClass = (*env)->FindClass(env, CLASS_SSL3_KEY_MAT_OUT);
     if (jSsl3KeyMatOutClass == NULL) { return; }
     fieldID = (*env)->GetFieldID(env, jKeyMatParamClass, "pReturnedKeyMaterial",
             "Lsun/security/pkcs11/wrapper/CK_SSL3_KEY_MAT_OUT;");
     if (fieldID == NULL) { return; }
     jReturnedKeyMaterial = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pIVClient out of pReturnedKeyMaterial */
     fieldID = (*env)->GetFieldID(env, jSsl3KeyMatOutClass, "pIVClient", "[B");
     if (fieldID == NULL) { return; }
     jRMIvClient = (*env)->GetObjectField(env, jReturnedKeyMaterial, fieldID);
-
-    /* get pIVServer out of pReturnedKeyMaterial */
     fieldID = (*env)->GetFieldID(env, jSsl3KeyMatOutClass, "pIVServer", "[B");
     if (fieldID == NULL) { return; }
     jRMIvServer = (*env)->GetObjectField(env, jReturnedKeyMaterial, fieldID);
 
-    /* populate java values */
+    // populate the specified pointers using java values
     *cKKeyMatParamUlMacSizeInBits = jLongToCKULong(jMacSizeInBits);
     *cKKeyMatParamUlKeySizeInBits = jLongToCKULong(jKeySizeInBits);
     *cKKeyMatParamUlIVSizeInBits = jLongToCKULong(jIVSizeInBits);
@@ -730,22 +796,22 @@
     jByteArrayToCKByteArray(env, jRIClientRandom,
             &(cKKeyMatParamRandomInfo->pClientRandom),
             &(cKKeyMatParamRandomInfo->ulClientRandomLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
+    if ((*env)->ExceptionCheck(env)) {
+        // just return as no memory allocation yet
+        return;
+    }
     jByteArrayToCKByteArray(env, jRIServerRandom,
             &(cKKeyMatParamRandomInfo->pServerRandom),
             &(cKKeyMatParamRandomInfo->ulServerRandomLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(cKKeyMatParamRandomInfo->pClientRandom);
-        return;
+        goto cleanup;
     }
     /* allocate memory for pReturnedKeyMaterial */
     *cKKeyMatParamPReturnedKeyMaterial =
-            (CK_SSL3_KEY_MAT_OUT_PTR)malloc(sizeof(CK_SSL3_KEY_MAT_OUT));
+            (CK_SSL3_KEY_MAT_OUT_PTR) calloc(1, sizeof(CK_SSL3_KEY_MAT_OUT));
     if (*cKKeyMatParamPReturnedKeyMaterial == NULL) {
-        free(cKKeyMatParamRandomInfo->pClientRandom);
-        free(cKKeyMatParamRandomInfo->pServerRandom);
         throwOutOfMemoryError(env, 0);
-        return;
+        goto cleanup;
     }
 
     // the handles are output params only, no need to fetch them from Java
@@ -757,219 +823,349 @@
     jByteArrayToCKByteArray(env, jRMIvClient,
             &((*cKKeyMatParamPReturnedKeyMaterial)->pIVClient), &ckTemp);
     if ((*env)->ExceptionCheck(env)) {
-        free(cKKeyMatParamRandomInfo->pClientRandom);
-        free(cKKeyMatParamRandomInfo->pServerRandom);
-        free((*cKKeyMatParamPReturnedKeyMaterial));
-        return;
+        goto cleanup;
     }
     jByteArrayToCKByteArray(env, jRMIvServer,
             &((*cKKeyMatParamPReturnedKeyMaterial)->pIVServer), &ckTemp);
     if ((*env)->ExceptionCheck(env)) {
-        free(cKKeyMatParamRandomInfo->pClientRandom);
-        free(cKKeyMatParamRandomInfo->pServerRandom);
-        free((*cKKeyMatParamPReturnedKeyMaterial)->pIVClient);
-        free((*cKKeyMatParamPReturnedKeyMaterial));
-        return;
+        goto cleanup;
     }
 
     return;
+cleanup:
+    free(cKKeyMatParamRandomInfo->pClientRandom);
+    free(cKKeyMatParamRandomInfo->pServerRandom);
+    if ((*cKKeyMatParamPReturnedKeyMaterial) != NULL) {
+        free((*cKKeyMatParamPReturnedKeyMaterial)->pIVClient);
+        free(*cKKeyMatParamPReturnedKeyMaterial);
+    }
+    // explicitly set to NULL to ensure no double free possible
+    cKKeyMatParamRandomInfo->pClientRandom = NULL;
+    cKKeyMatParamRandomInfo->pServerRandom = NULL;
+    *cKKeyMatParamPReturnedKeyMaterial = NULL;
+    return;
 }
 /*
  * converts the Java CK_SSL3_KEY_MAT_PARAMS object to a
- * CK_SSL3_KEY_MAT_PARAMS structure
+ * CK_SSL3_KEY_MAT_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_SSL3_KEY_MAT_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_SSL3_KEY_MAT_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_SSL3_KEY_MAT_PARAMS structure
  */
-void jSsl3KeyMatParamToCKSsl3KeyMatParam(JNIEnv *env, jobject jParam,
-        CK_SSL3_KEY_MAT_PARAMS_PTR ckParamPtr)
+CK_SSL3_KEY_MAT_PARAMS_PTR
+jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_SSL3_KEY_MAT_PARAMS_PTR ckParamPtr;
     jclass jSsl3KeyMatParamsClass;
-    memset(ckParamPtr, 0, sizeof(CK_SSL3_KEY_MAT_PARAMS));
+
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
+
+    // allocate memory for CK_SSL3_KEY_MAT_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_SSL3_KEY_MAT_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // retrieve and  populate using java values
     jSsl3KeyMatParamsClass = (*env)->FindClass(env,
             CLASS_SSL3_KEY_MAT_PARAMS);
-    if (jSsl3KeyMatParamsClass == NULL) { return; }
+    if (jSsl3KeyMatParamsClass == NULL) {
+        goto cleanup;
+    }
     keyMatParamToCKKeyMatParam(env, jParam, jSsl3KeyMatParamsClass,
             &(ckParamPtr->ulMacSizeInBits), &(ckParamPtr->ulKeySizeInBits),
             &(ckParamPtr->ulIVSizeInBits), &(ckParamPtr->bIsExport),
             &(ckParamPtr->RandomInfo), &(ckParamPtr->pReturnedKeyMaterial));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+    }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
  * converts the Java CK_TLS12_KEY_MAT_PARAMS object to a
- * CK_TLS12_KEY_MAT_PARAMS structure
+ * CK_TLS12_KEY_MAT_PARAMS pointer
  *
  * @param env - used to call JNI functions to get the Java classes and objects
  * @param jParam - the Java CK_TLS12_KEY_MAT_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_TLS12_KEY_MAT_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_TLS12_KEY_MAT_PARAMS structure
  */
-void jTls12KeyMatParamToCKTls12KeyMatParam(JNIEnv *env,
-        jobject jParam, CK_TLS12_KEY_MAT_PARAMS_PTR ckParamPtr)
+CK_TLS12_KEY_MAT_PARAMS_PTR jTls12KeyMatParamToCKTls12KeyMatParamPtr(JNIEnv *env,
+        jobject jParam, CK_ULONG *pLength)
 {
+    CK_TLS12_KEY_MAT_PARAMS_PTR ckParamPtr;
     jclass jTls12KeyMatParamsClass;
     jfieldID fieldID;
-    memset(ckParamPtr, 0, sizeof(CK_TLS12_KEY_MAT_PARAMS));
+    jlong prfHashMechanism;
+
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
+
+    // retrieve java values
     jTls12KeyMatParamsClass = (*env)->FindClass(env,
             CLASS_TLS12_KEY_MAT_PARAMS);
-    if (jTls12KeyMatParamsClass == NULL) { return; }
+    if (jTls12KeyMatParamsClass == NULL) { return NULL; }
+    fieldID = (*env)->GetFieldID(env, jTls12KeyMatParamsClass,
+            "prfHashMechanism", "J");
+    if (fieldID == NULL) { return NULL; }
+    prfHashMechanism = (*env)->GetLongField(env, jParam, fieldID);
+
+    // allocate memory for CK_TLS12_KEY_MAT_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_TLS12_KEY_MAT_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     keyMatParamToCKKeyMatParam(env, jParam, jTls12KeyMatParamsClass,
             &(ckParamPtr->ulMacSizeInBits), &(ckParamPtr->ulKeySizeInBits),
             &(ckParamPtr->ulIVSizeInBits), &(ckParamPtr->bIsExport),
             &(ckParamPtr->RandomInfo), &(ckParamPtr->pReturnedKeyMaterial));
-    fieldID = (*env)->GetFieldID(env, jTls12KeyMatParamsClass,
-            "prfHashMechanism", "J");
-    if (fieldID != NULL) {
-        jlong prfHashMechanism = (*env)->GetLongField(env, jParam, fieldID);
-        ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE)prfHashMechanism;
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
     }
+    ckParamPtr->prfHashMechanism = (CK_MECHANISM_TYPE)prfHashMechanism;
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_TLS12_KEY_MAT_PARAMS);
+    }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_AES_CTR_PARAMS object to a CK_AES_CTR_PARAMS structure
+ * converts the Java CK_AES_CTR_PARAMS object to a CK_AES_CTR_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_AES_CTR_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_AES_CTR_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_AES_CTR_PARAMS structure
  */
-void jAesCtrParamsToCKAesCtrParam(JNIEnv *env, jobject jParam,
-                                  CK_AES_CTR_PARAMS_PTR ckParamPtr) {
+CK_AES_CTR_PARAMS_PTR
+jAesCtrParamsToCKAesCtrParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+{
+    CK_AES_CTR_PARAMS_PTR ckParamPtr;
     jclass jAesCtrParamsClass;
     jfieldID fieldID;
     jlong jCounterBits;
     jobject jCb;
-    CK_BYTE_PTR ckBytes;
+    CK_BYTE_PTR ckBytes = NULL;
     CK_ULONG ckTemp;
 
-    /* get ulCounterBits */
+    if (pLength != NULL) {
+        *pLength = 0L;
+    }
+
+    // retrieve java values
     jAesCtrParamsClass = (*env)->FindClass(env, CLASS_AES_CTR_PARAMS);
-    if (jAesCtrParamsClass == NULL) { return; }
+    if (jAesCtrParamsClass == NULL) { return NULL; }
     if (!(*env)->IsInstanceOf(env, jParam, jAesCtrParamsClass)) {
-        return;
+        return NULL;
     }
     fieldID = (*env)->GetFieldID(env, jAesCtrParamsClass, "ulCounterBits", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jCounterBits = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get cb */
     fieldID = (*env)->GetFieldID(env, jAesCtrParamsClass, "cb", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jCb = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
-    ckParamPtr->ulCounterBits = jLongToCKULong(jCounterBits);
+    // allocate memory for CK_AES_CTR_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_AES_CTR_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     jByteArrayToCKByteArray(env, jCb, &ckBytes, &ckTemp);
-    if ((*env)->ExceptionCheck(env)) { return; }
-    if (ckTemp != 16) {
-        TRACE1("\nERROR: WRONG CTR IV LENGTH %lu", ckTemp);
-    } else {
-        memcpy(ckParamPtr->cb, ckBytes, ckTemp);
-        free(ckBytes);
+    if ((*env)->ExceptionCheck(env) || ckTemp != 16) {
+        goto cleanup;
     }
+    memcpy(ckParamPtr->cb, ckBytes, ckTemp);
+    free(ckBytes);
+
+    ckParamPtr->ulCounterBits = jLongToCKULong(jCounterBits);
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_AES_CTR_PARAMS);
+    }
+    return ckParamPtr;
+cleanup:
+    free(ckBytes);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_GCM_PARAMS object to a CK_GCM_PARAMS structure
+ * converts the Java CK_GCM_PARAMS object to a CK_GCM_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_GCM_PARAMS object to convert
- * @param ckpParam - pointer to the new CK_GCM_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_GCM_PARAMS structure
  */
-void jGCMParamsToCKGCMParam(JNIEnv *env, jobject jParam,
-                            CK_GCM_PARAMS_PTR ckpParam) {
+CK_GCM_PARAMS_PTR
+jGCMParamsToCKGCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+{
+    CK_GCM_PARAMS_PTR ckParamPtr;
     jclass jGcmParamsClass;
     jfieldID fieldID;
     jobject jIv, jAad;
     jlong jTagLen;
 
-    /* get iv */
-    jGcmParamsClass = (*env)->FindClass(env, CLASS_GCM_PARAMS);
-    if (jGcmParamsClass == NULL) { return; }
-    if (!(*env)->IsInstanceOf(env, jParam, jGcmParamsClass)) {
-        return;
+    TRACE0("DEBUG jGCMParamsToCKGCMParam is called\n");
+
+    if (pLength != NULL) {
+        *pLength = 0L;
     }
 
+    // retrieve java values
+    jGcmParamsClass = (*env)->FindClass(env, CLASS_GCM_PARAMS);
+    if (jGcmParamsClass == NULL) { return NULL; }
+    if (!(*env)->IsInstanceOf(env, jParam, jGcmParamsClass)) {
+        return NULL;
+    }
     fieldID = (*env)->GetFieldID(env, jGcmParamsClass, "iv", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jIv = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get aad */
     fieldID = (*env)->GetFieldID(env, jGcmParamsClass, "aad", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jAad = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get tagLength */
     fieldID = (*env)->GetFieldID(env, jGcmParamsClass, "tagBits", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jTagLen = (*env)->GetLongField(env, jParam, fieldID);
 
+    // allocate memory for CK_GCM_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_GCM_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
 
-    /* populate java values */
-    jByteArrayToCKByteArray(env, jIv, &(ckpParam->pIv), &(ckpParam->ulIvLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
+    // populate using java values
+    jByteArrayToCKByteArray(env, jIv, &(ckParamPtr->pIv), &(ckParamPtr->ulIvLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
 
-    jByteArrayToCKByteArray(env, jAad, &(ckpParam->pAAD), &(ckpParam->ulAADLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
+    jByteArrayToCKByteArray(env, jAad, &(ckParamPtr->pAAD), &(ckParamPtr->ulAADLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+
+    ckParamPtr->ulTagBits = jLongToCKULong(jTagLen);
 
-    ckpParam->ulTagBits = jLongToCKULong(jTagLen);
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_GCM_PARAMS);
+    }
+    TRACE1("Created inner GCM_PARAMS PTR %lX\n", ptr_to_jlong(ckParamPtr));
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pIv);
+    free(ckParamPtr->pAAD);
+    free(ckParamPtr);
+    return NULL;
+
 }
 
 /*
- * converts the Java CK_CCM_PARAMS object to a CK_CCM_PARAMS structure
+ * converts the Java CK_CCM_PARAMS object to a CK_CCM_PARAMS pointer
  *
  * @param env - used to call JNI functions to get the Java classes and objects
  * @param jParam - the Java CK_CCM_PARAMS object to convert
- * @param ckpParam - pointer to the new CK_CCM_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_CCM_PARAMS structure
  */
-void jCCMParamsToCKCCMParam(JNIEnv *env, jobject jParam,
-                            CK_CCM_PARAMS_PTR ckpParam) {
+CK_CCM_PARAMS_PTR
+jCCMParamsToCKCCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
+{
+    CK_CCM_PARAMS_PTR ckParamPtr;
     jclass jCcmParamsClass;
     jfieldID fieldID;
     jobject jNonce, jAad;
     jlong jDataLen, jMacLen;
 
-    /* get iv */
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
+
+    // retrieve java values
     jCcmParamsClass = (*env)->FindClass(env, CLASS_CCM_PARAMS);
-    if (jCcmParamsClass == NULL) { return; }
-
+    if (jCcmParamsClass == NULL) { return NULL; }
     if (!(*env)->IsInstanceOf(env, jParam, jCcmParamsClass)) {
-        return;
+        return NULL;
     }
     fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "dataLen", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jDataLen = (*env)->GetLongField(env, jParam, fieldID);
-
     fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "nonce", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jNonce = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get aad */
     fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "aad", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jAad = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get macLen */
     fieldID = (*env)->GetFieldID(env, jCcmParamsClass, "macLen", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jMacLen = (*env)->GetLongField(env, jParam, fieldID);
 
-    /* populate java values */
-    ckpParam->ulDataLen = jLongToCKULong(jDataLen);
-    jByteArrayToCKByteArray(env, jNonce, &(ckpParam->pNonce),
-            &(ckpParam->ulNonceLen));
-    jByteArrayToCKByteArray(env, jAad, &(ckpParam->pAAD),
-            &(ckpParam->ulAADLen));
-    ckpParam->ulMACLen = jLongToCKULong(jMacLen);
-    if ((*env)->ExceptionCheck(env)) { return; }
+    // allocate memory for CK_CCM_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_CCM_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
+    ckParamPtr->ulDataLen = jLongToCKULong(jDataLen);
+    jByteArrayToCKByteArray(env, jNonce, &(ckParamPtr->pNonce),
+            &(ckParamPtr->ulNonceLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+
+    jByteArrayToCKByteArray(env, jAad, &(ckParamPtr->pAAD),
+            &(ckParamPtr->ulAADLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+
+    ckParamPtr->ulMACLen = jLongToCKULong(jMacLen);
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_CCM_PARAMS);
+    }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pNonce);
+    free(ckParamPtr->pAAD);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts a Java CK_MECHANISM object into a pointer to a CK_MECHANISM
- * structure. NOTE: CALLER IS RESPONSIBLE FOR FREEING THE RETURNED POINTER
+ * converts a Java CK_MECHANISM object into a CK_MECHANISM pointer
+ * pointer.
  *
  * @param env - used to call JNI funktions to get the values out of the Java object
- * @param jMechanism - the Java CK_MECHANISM object to convert
- * @return - pointer to the new CK_MECHANISM structure
+ * @param jMech - the Java CK_MECHANISM object to convert
+ * @return pointer to the new CK_MECHANISM structure
  */
 CK_MECHANISM_PTR jMechanismToCKMechanismPtr(JNIEnv *env, jobject jMech)
 {
@@ -978,7 +1174,7 @@
     jobject jParam = (*env)->GetObjectField(env, jMech, mech_pParameterID);
 
     /* allocate memory for CK_MECHANISM_PTR */
-    ckpMech =  (CK_MECHANISM_PTR) malloc(sizeof(CK_MECHANISM));
+    ckpMech =  (CK_MECHANISM_PTR) calloc(1, sizeof(CK_MECHANISM));
     if (ckpMech == NULL) {
         throwOutOfMemoryError(env, 0);
         return NULL;
@@ -1001,48 +1197,15 @@
 }
 
 /*
- * the following functions convert Attribute and Mechanism value pointers
- *
- * jobject ckAttributeValueToJObject(JNIEnv *env,
- *                                   const CK_ATTRIBUTE_PTR ckpAttribute);
- *
- * CK_VOID_PTR jObjectToPrimitiveCKObjectPtr(JNIEnv *env,
- *                                       jobject jObject,
- *                                       CK_ULONG *pLength);
- *
- * CK_VOID_PTR jMechParamToCKMechParamPtr(JNIEnv *env,
- *                              jobject jParam,
- *                              CK_MECHANISM_TYPE ckMech,
- *                              CK_ULONG *ckpLength);
- *
- * These functions are used if a PKCS#11 mechanism or attribute structure gets
- * convertet to a Java attribute or mechanism object or vice versa.
- *
- * ckAttributeValueToJObject converts a PKCS#11 attribute value pointer to a Java
- * object depending on the type of the Attribute. A PKCS#11 attribute value can
+ * converts the pValue of a CK_ATTRIBUTE structure into a Java Object by
+ * checking the type of the attribute. A PKCS#11 attribute value can
  * be a CK_ULONG, CK_BYTE[], CK_CHAR[], big integer, CK_BBOOL, CK_UTF8CHAR[],
  * CK_DATE or CK_FLAGS that gets converted to a corresponding Java object.
  *
- * jObjectToPrimitiveCKObjectPtr is used by jAttributeToCKAttributePtr for
- * converting the Java attribute value to a PKCS#11 attribute value pointer.
- * For now only primitive datatypes and arrays of primitive datatypes can get
- * converted. Otherwise this function throws a PKCS#11Exception with the
- * errorcode CKR_VENDOR_DEFINED.
- *
- * jMechParamToCKMechParamPtr converts a Java mechanism parameter to a PKCS#11
- * mechanism parameter. Based on the specified PKCS#11 mechanism type, this
- * function will allocate memory for a PKCS#11 parameter structure and
- * populate its field using the Java object.
- */
-
-/*
- * converts the pValue of a CK_ATTRIBUTE structure into a Java Object by
- * checking the type of the attribute.
- *
- * @param env - used to call JNI funktions to create the new Java object
+ * @param env - used to call JNI functions to create the new Java object
  * @param ckpAttribute - the pointer to the CK_ATTRIBUTE structure that contains the type
  *                       and the pValue to convert
- * @return - the new Java object of the CK-type pValue
+ * @return the new Java object of the CK-type pValue
  */
 jobject ckAttributeValueToJObject(JNIEnv *env, const CK_ATTRIBUTE_PTR ckpAttribute)
 {
@@ -1185,9 +1348,8 @@
  */
 
 /*
- * converts the given Java mechanism parameter to a CK mechanism parameter structure
- * and store the length in bytes in the length variable.
- * The memory of *ckpParamPtr has to be freed after use!
+ * converts the given Java mechanism parameter to a CK mechanism parameter
+ * pointer and store the length in bytes in the length variable.
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java mechanism parameter object to convert
@@ -1223,156 +1385,68 @@
      * Most common cases, i.e. NULL/byte[]/long, are already handled by
      * jMechParamToCKMechParam before calling this method.
      */
-    TRACE1("\nDEBUG: jMechParamToCKMechParamPtrSlow, mech=0x%lX", ckMech);
+    TRACE1("\nDEBUG: jMechParamToCKMechParamPtrSlow, mech=0x%lX\n", ckMech);
 
     switch (ckMech) {
         case CKM_SSL3_PRE_MASTER_KEY_GEN:
         case CKM_TLS_PRE_MASTER_KEY_GEN:
-            *ckpLength = sizeof(CK_VERSION);
             ckpParamPtr = jVersionToCKVersionPtr(env, jParam);
+            if (ckpParamPtr != NULL) {
+                *ckpLength = sizeof(CK_VERSION);
+            } else {
+                *ckpLength = 0;
+            }
             break;
         case CKM_SSL3_MASTER_KEY_DERIVE:
         case CKM_TLS_MASTER_KEY_DERIVE:
         case CKM_SSL3_MASTER_KEY_DERIVE_DH:
         case CKM_TLS_MASTER_KEY_DERIVE_DH:
-            ckpParamPtr =
-                    malloc(sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
-
-            jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParam(env, jParam,
-                    (CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_SSL3_KEY_AND_MAC_DERIVE:
         case CKM_TLS_KEY_AND_MAC_DERIVE:
-            ckpParamPtr =
-                    malloc(sizeof(CK_SSL3_KEY_MAT_PARAMS));
-            if (ckpParamPtr == NULL) {
-                 throwOutOfMemoryError(env, 0);
-                 return NULL;
-            }
-            *ckpLength = sizeof(CK_SSL3_KEY_MAT_PARAMS);
-
-            jSsl3KeyMatParamToCKSsl3KeyMatParam(env, jParam,
-                    (CK_SSL3_KEY_MAT_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_TLS12_KEY_AND_MAC_DERIVE:
-            ckpParamPtr =
-                    malloc(sizeof(CK_TLS12_KEY_MAT_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_TLS12_KEY_MAT_PARAMS);
-
-            jTls12KeyMatParamToCKTls12KeyMatParam(env, jParam,
-                    (CK_TLS12_KEY_MAT_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jTls12KeyMatParamToCKTls12KeyMatParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_TLS12_MASTER_KEY_DERIVE:
         case CKM_TLS12_MASTER_KEY_DERIVE_DH:
-            ckpParamPtr =
-                    malloc(sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
-
-            jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParam(env, jParam,
-                    (CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jTls12MasterKeyDeriveParamToCKTls12MasterKeyDeriveParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_TLS_PRF:
         case CKM_NSS_TLS_PRF_GENERAL:
-            ckpParamPtr = malloc(sizeof(CK_TLS_PRF_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_TLS_PRF_PARAMS);
-
-            jTlsPrfParamsToCKTlsPrfParam(env, jParam,
-                    (CK_TLS_PRF_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jTlsPrfParamsToCKTlsPrfParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_TLS_MAC:
-            ckpParamPtr = malloc(sizeof(CK_TLS_MAC_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_TLS_MAC_PARAMS);
-
-            jTlsMacParamsToCKTlsMacParam(env, jParam,
-                    (CK_TLS_MAC_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jTlsMacParamsToCKTlsMacParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_AES_CTR:
-            ckpParamPtr = malloc(sizeof(CK_AES_CTR_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_AES_CTR_PARAMS);
-
-            jAesCtrParamsToCKAesCtrParam(env, jParam,
-                    (CK_AES_CTR_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jAesCtrParamsToCKAesCtrParamPtr(env, jParam,
+                    ckpLength);
             break;
         case CKM_AES_GCM:
-            ckpParamPtr = malloc(sizeof(CK_GCM_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_GCM_PARAMS);
-
-            jGCMParamsToCKGCMParam(env, jParam, (CK_GCM_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jGCMParamsToCKGCMParamPtr(env, jParam, ckpLength);
             break;
         case CKM_AES_CCM:
-            ckpParamPtr = malloc(sizeof(CK_CCM_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_CCM_PARAMS);
-
-            jCCMParamsToCKCCMParam(env, jParam,
-                    (CK_CCM_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jCCMParamsToCKCCMParamPtr(env, jParam, ckpLength);
             break;
         case CKM_RSA_PKCS_OAEP:
-            ckpParamPtr = malloc(sizeof(CK_RSA_PKCS_OAEP_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_RSA_PKCS_OAEP_PARAMS);
-
-            jRsaPkcsOaepParamToCKRsaPkcsOaepParam(env, jParam,
-                    (CK_RSA_PKCS_OAEP_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(env, jParam, ckpLength);
             break;
         case CKM_PBE_SHA1_DES3_EDE_CBC:
         case CKM_PBE_SHA1_DES2_EDE_CBC:
         case CKM_PBA_SHA1_WITH_SHA1_HMAC:
-            ckpParamPtr = malloc(sizeof(CK_PBE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-
-            *ckpLength = sizeof(CK_PBE_PARAMS);
-
-            jPbeParamToCKPbeParam(env, jParam, (CK_PBE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jPbeParamToCKPbeParamPtr(env, jParam, ckpLength);
             break;
         case CKM_PKCS5_PBKD2:
-            ckpParamPtr = malloc(sizeof(CK_PKCS5_PBKD2_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_PKCS5_PBKD2_PARAMS);
-
-            jPkcs5Pbkd2ParamToCKPkcs5Pbkd2Param(env, jParam,
-                     (CK_PKCS5_PBKD2_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(env, jParam, ckpLength);
             break;
         case CKM_RSA_PKCS_PSS:
         case CKM_SHA1_RSA_PKCS_PSS:
@@ -1380,62 +1454,21 @@
         case CKM_SHA384_RSA_PKCS_PSS:
         case CKM_SHA512_RSA_PKCS_PSS:
         case CKM_SHA224_RSA_PKCS_PSS:
-            ckpParamPtr = malloc(sizeof(CK_RSA_PKCS_PSS_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_RSA_PKCS_PSS_PARAMS);
-
-            jRsaPkcsPssParamToCKRsaPkcsPssParam(env, jParam,
-                    (CK_RSA_PKCS_PSS_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jRsaPkcsPssParamToCKRsaPkcsPssParamPtr(env, jParam, ckpLength);
             break;
         case CKM_ECDH1_DERIVE:
         case CKM_ECDH1_COFACTOR_DERIVE:
-            ckpParamPtr = malloc(sizeof(CK_ECDH1_DERIVE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_ECDH1_DERIVE_PARAMS);
-
-            jEcdh1DeriveParamToCKEcdh1DeriveParam(env, jParam,
-                    (CK_ECDH1_DERIVE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jEcdh1DeriveParamToCKEcdh1DeriveParamPtr(env, jParam, ckpLength);
             break;
         case CKM_ECMQV_DERIVE:
-            ckpParamPtr = malloc(sizeof(CK_ECDH2_DERIVE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_ECDH2_DERIVE_PARAMS);
-
-            jEcdh2DeriveParamToCKEcdh2DeriveParam(env, jParam,
-                    (CK_ECDH2_DERIVE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(env, jParam, ckpLength);
             break;
         case CKM_X9_42_DH_DERIVE:
-            ckpParamPtr = malloc(sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_X9_42_DH1_DERIVE_PARAMS);
-
-            /* convert jParameter to CKParameter */
-            jX942Dh1DeriveParamToCKX942Dh1DeriveParam(env, jParam,
-                (CK_X9_42_DH1_DERIVE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(env, jParam, ckpLength);
             break;
         case CKM_X9_42_DH_HYBRID_DERIVE:
         case CKM_X9_42_MQV_DERIVE:
-            ckpParamPtr = malloc(sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
-            if (ckpParamPtr == NULL) {
-                throwOutOfMemoryError(env, 0);
-                return NULL;
-            }
-            *ckpLength = sizeof(CK_X9_42_DH2_DERIVE_PARAMS);
-
-            jX942Dh2DeriveParamToCKX942Dh2DeriveParam(env, jParam,
-                    (CK_X9_42_DH2_DERIVE_PARAMS_PTR) ckpParamPtr);
+            ckpParamPtr = jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(env, jParam, ckpLength);
             break;
         // defined by pkcs11.h but we don't support
         case CKM_KEA_DERIVE: // CK_KEA_DERIVE_PARAMS
@@ -1460,118 +1493,144 @@
     TRACE0("\nDEBUG: jMechParamToCKMechParamPtrSlow FINISHED\n");
 
     if ((*env)->ExceptionCheck(env)) {
-        free(ckpParamPtr);
-        *ckpLength = 0;
         return NULL;
     }
 
     return ckpParamPtr;
 }
 
-/* the mechanism parameter convertion functions: */
-
 /*
- * converts the Java CK_RSA_PKCS_OAEP_PARAMS object to a CK_RSA_PKCS_OAEP_PARAMS structure
+ * converts the Java CK_RSA_PKCS_OAEP_PARAMS object to a
+ * CK_RSA_PKCS_OAEP_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_RSA_PKCS_OAEP_PARAMS object to convert
- * @return - the new CK_RSA_PKCS_OAEP_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_RSA_PKCS_OAEP_PARAMS structure
  */
-void jRsaPkcsOaepParamToCKRsaPkcsOaepParam(JNIEnv *env, jobject jParam,
-CK_RSA_PKCS_OAEP_PARAMS_PTR ckParamPtr)
+CK_RSA_PKCS_OAEP_PARAMS_PTR
+jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_RSA_PKCS_OAEP_PARAMS_PTR ckParamPtr;
     jclass jRsaPkcsOaepParamsClass;
     jfieldID fieldID;
     jlong jHashAlg, jMgf, jSource;
     jobject jSourceData;
-    CK_BYTE_PTR ckpByte;
-    memset(ckParamPtr, 0, sizeof(CK_RSA_PKCS_OAEP_PARAMS));
 
-    /* get hashAlg */
+    if (pLength!= NULL) {
+        *pLength = 0L;
+    }
+
+    // retrieve java values
     jRsaPkcsOaepParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_OAEP_PARAMS);
-    if (jRsaPkcsOaepParamsClass == NULL) { return; }
+    if (jRsaPkcsOaepParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "hashAlg", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jHashAlg = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get mgf */
     fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "mgf", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jMgf = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get source */
     fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "source", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSource = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get sourceData and sourceDataLength */
     fieldID = (*env)->GetFieldID(env, jRsaPkcsOaepParamsClass, "pSourceData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSourceData = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_RSA_PKCS_OAEP_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_RSA_PKCS_OAEP_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->hashAlg = jLongToCKULong(jHashAlg);
     ckParamPtr->mgf = jLongToCKULong(jMgf);
     ckParamPtr->source = jLongToCKULong(jSource);
-    jByteArrayToCKByteArray(env, jSourceData, & ckpByte, &(ckParamPtr->ulSourceDataLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
-    ckParamPtr->pSourceData = (CK_VOID_PTR) ckpByte;
+    jByteArrayToCKByteArray(env, jSourceData, (CK_BYTE_PTR*) &(ckParamPtr->pSourceData),
+            &(ckParamPtr->ulSourceDataLen));
+    if ((*env)->ExceptionCheck(env)) {
+        free(ckParamPtr);
+        return NULL;
+    }
+
+    if (pLength!= NULL) {
+        *pLength = sizeof(CK_RSA_PKCS_OAEP_PARAMS);
+    }
+    return ckParamPtr;
 }
 
 /*
- * converts the Java CK_PBE_PARAMS object to a CK_PBE_PARAMS structure
+ * converts the Java CK_PBE_PARAMS object to a CK_PBE_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_PBE_PARAMS object to convert
- * @param ckParamPtr pointer to the new CK_PBE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_PBE_PARAMS structure
  */
-void jPbeParamToCKPbeParam(JNIEnv *env, jobject jParam,
-CK_PBE_PARAMS_PTR ckParamPtr)
+CK_PBE_PARAMS_PTR
+jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_PBE_PARAMS_PTR ckParamPtr;
     jclass jPbeParamsClass;
     jfieldID fieldID;
     jlong jIteration;
     jobject jInitVector, jPassword, jSalt;
     CK_ULONG ckTemp;
-    memset(ckParamPtr, 0, sizeof(CK_PBE_PARAMS));
 
-    /* get pInitVector */
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
+
+    // retrieve java values
     jPbeParamsClass = (*env)->FindClass(env, CLASS_PBE_PARAMS);
-    if (jPbeParamsClass == NULL) { return; }
+    if (jPbeParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pInitVector", "[C");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jInitVector = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pPassword and ulPasswordLength */
     fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pPassword", "[C");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPassword = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pSalt and ulSaltLength */
     fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "pSalt", "[C");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSalt = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get ulIteration */
     fieldID = (*env)->GetFieldID(env, jPbeParamsClass, "ulIteration", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jIteration = (*env)->GetLongField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_PBE_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_PBE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->ulIteration = jLongToCKULong(jIteration);
     jCharArrayToCKCharArray(env, jInitVector, &(ckParamPtr->pInitVector), &ckTemp);
-    if ((*env)->ExceptionCheck(env)) { return; }
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
     jCharArrayToCKCharArray(env, jPassword, &(ckParamPtr->pPassword), &(ckParamPtr->ulPasswordLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pInitVector);
-        return;
+        goto cleanup;
     }
     jCharArrayToCKCharArray(env, jSalt, &(ckParamPtr->pSalt), &(ckParamPtr->ulSaltLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pInitVector);
-        free(ckParamPtr->pPassword);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_PBE_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pInitVector);
+    free(ckParamPtr->pPassword);
+    free(ckParamPtr->pSalt);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
@@ -1602,7 +1661,7 @@
     jMechanismType = (*env)->GetLongField(env, jMechanism, fieldID);
     ckMechanismType = jLongToCKULong(jMechanismType);
     if (ckMechanismType != ckMechanism->mechanism) {
-        /* we do not have maching types, this should not occur */
+        /* we do not have matching types, this should not occur */
         return;
     }
 
@@ -1637,321 +1696,426 @@
 }
 
 /*
- * converts the Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS structure
+ * converts the Java CK_PKCS5_PBKD2_PARAMS object to a CK_PKCS5_PBKD2_PARAMS
+ * pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_PKCS5_PBKD2_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_PKCS5_PBKD2_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_PKCS5_PBKD2_PARAMS structure
  */
-void jPkcs5Pbkd2ParamToCKPkcs5Pbkd2Param(JNIEnv *env, jobject jParam,
-CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr)
+CK_PKCS5_PBKD2_PARAMS_PTR
+jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr;
     jclass jPkcs5Pbkd2ParamsClass;
     jfieldID fieldID;
     jlong jSaltSource, jIteration, jPrf;
     jobject jSaltSourceData, jPrfData;
-    memset(ckParamPtr, 0, sizeof(CK_PKCS5_PBKD2_PARAMS));
 
-    /* get saltSource */
-    jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
-    if (jPkcs5Pbkd2ParamsClass == NULL) { return; }
-    fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "saltSource", "J");
-    if (fieldID == NULL) { return; }
-    jSaltSource = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get pSaltSourceData */
-    fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pSaltSourceData", "[B");
-    if (fieldID == NULL) { return; }
-    jSaltSourceData = (*env)->GetObjectField(env, jParam, fieldID);
+    if (pLength != NULL) {
+        *pLength = 0L;
+    }
 
-    /* get iterations */
+    // retrieve java values
+    jPkcs5Pbkd2ParamsClass = (*env)->FindClass(env, CLASS_PKCS5_PBKD2_PARAMS);
+    if (jPkcs5Pbkd2ParamsClass == NULL) { return NULL; }
+    fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "saltSource", "J");
+    if (fieldID == NULL) { return NULL; }
+    jSaltSource = (*env)->GetLongField(env, jParam, fieldID);
+    fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pSaltSourceData", "[B");
+    if (fieldID == NULL) { return NULL; }
+    jSaltSourceData = (*env)->GetObjectField(env, jParam, fieldID);
     fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "iterations", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jIteration = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get prf */
     fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "prf", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrf = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get pPrfData and ulPrfDataLength in byte */
     fieldID = (*env)->GetFieldID(env, jPkcs5Pbkd2ParamsClass, "pPrfData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrfData = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_PKCS5_PBKD2_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_PKCS5_PBKD2_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->saltSource = jLongToCKULong(jSaltSource);
-    jByteArrayToCKByteArray(env, jSaltSourceData, (CK_BYTE_PTR *) &(ckParamPtr->pSaltSourceData), &(ckParamPtr->ulSaltSourceDataLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
+    jByteArrayToCKByteArray(env, jSaltSourceData, (CK_BYTE_PTR *)
+            &(ckParamPtr->pSaltSourceData), &(ckParamPtr->ulSaltSourceDataLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
     ckParamPtr->iterations = jLongToCKULong(jIteration);
     ckParamPtr->prf = jLongToCKULong(jPrf);
-    jByteArrayToCKByteArray(env, jPrfData, (CK_BYTE_PTR *) &(ckParamPtr->pPrfData), &(ckParamPtr->ulPrfDataLen));
+    jByteArrayToCKByteArray(env, jPrfData, (CK_BYTE_PTR *)
+            &(ckParamPtr->pPrfData), &(ckParamPtr->ulPrfDataLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pSaltSourceData);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_PKCS5_PBKD2_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pSaltSourceData);
+    free(ckParamPtr->pPrfData);
+    free(ckParamPtr);
+    return NULL;
+
 }
 
 /*
- * converts the Java CK_RSA_PKCS_PSS_PARAMS object to a CK_RSA_PKCS_PSS_PARAMS structure
+ * converts the Java CK_RSA_PKCS_PSS_PARAMS object to a CK_RSA_PKCS_PSS_PARAMS
+ * pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_RSA_PKCS_PSS_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_RSA_PKCS_PSS_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_RSA_PKCS_PSS_PARAMS structure
  */
-void jRsaPkcsPssParamToCKRsaPkcsPssParam(JNIEnv *env, jobject jParam,
-CK_RSA_PKCS_PSS_PARAMS_PTR ckParamPtr)
+CK_RSA_PKCS_PSS_PARAMS_PTR
+jRsaPkcsPssParamToCKRsaPkcsPssParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_RSA_PKCS_PSS_PARAMS_PTR ckParamPtr;
     jclass jRsaPkcsPssParamsClass;
     jfieldID fieldID;
     jlong jHashAlg, jMgf, jSLen;
-    memset(ckParamPtr, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS));
 
-    /* get hashAlg */
-    jRsaPkcsPssParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_PSS_PARAMS);
-    if (jRsaPkcsPssParamsClass == NULL) { return; }
-    fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "hashAlg", "J");
-    if (fieldID == NULL) { return; }
-    jHashAlg = (*env)->GetLongField(env, jParam, fieldID);
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
 
-    /* get mgf */
+    // retrieve java values
+    jRsaPkcsPssParamsClass = (*env)->FindClass(env, CLASS_RSA_PKCS_PSS_PARAMS);
+    if (jRsaPkcsPssParamsClass == NULL) { return NULL; }
+    fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "hashAlg", "J");
+    if (fieldID == NULL) { return NULL; }
+    jHashAlg = (*env)->GetLongField(env, jParam, fieldID);
     fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "mgf", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jMgf = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get sLen */
     fieldID = (*env)->GetFieldID(env, jRsaPkcsPssParamsClass, "sLen", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSLen = (*env)->GetLongField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_RSA_PKCS_PSS_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_RSA_PKCS_PSS_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->hashAlg = jLongToCKULong(jHashAlg);
     ckParamPtr->mgf = jLongToCKULong(jMgf);
     ckParamPtr->sLen = jLongToCKULong(jSLen);
     TRACE1("DEBUG: jRsaPkcsPssParamToCKRsaPkcsPssParam, hashAlg=0x%lX\n", ckParamPtr->hashAlg);
     TRACE1("DEBUG: jRsaPkcsPssParamToCKRsaPkcsPssParam, mgf=0x%lX\n", ckParamPtr->mgf);
     TRACE1("DEBUG: jRsaPkcsPssParamToCKRsaPkcsPssParam, sLen=%lu\n", ckParamPtr->sLen);
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_RSA_PKCS_PSS_PARAMS);
+    }
+    return ckParamPtr;
+
 }
 
 /*
- * converts the Java CK_ECDH1_DERIVE_PARAMS object to a CK_ECDH1_DERIVE_PARAMS structure
+ * converts the Java CK_ECDH1_DERIVE_PARAMS object to a CK_ECDH1_DERIVE_PARAMS
+ * pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_ECDH1_DERIVE_PARAMS object to convert
- * @param ckParamPtr - the new CK_ECDH1_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @retur pointer to nthe new CK_ECDH1_DERIVE_PARAMS structure
  */
-void jEcdh1DeriveParamToCKEcdh1DeriveParam(JNIEnv *env, jobject jParam,
-CK_ECDH1_DERIVE_PARAMS_PTR ckParamPtr)
+CK_ECDH1_DERIVE_PARAMS_PTR
+jEcdh1DeriveParamToCKEcdh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_ECDH1_DERIVE_PARAMS_PTR ckParamPtr;
     jclass jEcdh1DeriveParamsClass;
     jfieldID fieldID;
     jlong jLong;
     jobject jSharedData, jPublicData;
-    memset(ckParamPtr, 0, sizeof(CK_ECDH1_DERIVE_PARAMS));
 
-    /* get kdf */
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
+
+    // retrieve java values
     jEcdh1DeriveParamsClass = (*env)->FindClass(env, CLASS_ECDH1_DERIVE_PARAMS);
-    if (jEcdh1DeriveParamsClass == NULL) { return; }
+    if (jEcdh1DeriveParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jEcdh1DeriveParamsClass, "kdf", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jLong = (*env)->GetLongField(env, jParam, fieldID);
-    ckParamPtr->kdf = jLongToCKULong(jLong);
-
-    /* get pSharedData and ulSharedDataLen */
     fieldID = (*env)->GetFieldID(env, jEcdh1DeriveParamsClass, "pSharedData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSharedData = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pPublicData and ulPublicDataLen */
     fieldID = (*env)->GetFieldID(env, jEcdh1DeriveParamsClass, "pPublicData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_ECDH1_DERIVE_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_ECDH1_DERIVE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->kdf = jLongToCKULong(jLong);
-    jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData), &(ckParamPtr->ulSharedDataLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
-    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+    jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData),
+            &(ckParamPtr->ulSharedDataLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+            &(ckParamPtr->ulPublicDataLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pSharedData);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_ECDH1_DERIVE_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pSharedData);
+    free(ckParamPtr->pPublicData);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_ECDH2_DERIVE_PARAMS object to a CK_ECDH2_DERIVE_PARAMS structure
+ * converts the Java CK_ECDH2_DERIVE_PARAMS object to a CK_ECDH2_DERIVE_PARAMS
+ * pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_ECDH2_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_ECDH2_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_ECDH2_DERIVE_PARAMS structure
  */
-void jEcdh2DeriveParamToCKEcdh2DeriveParam(JNIEnv *env, jobject jParam,
-CK_ECDH2_DERIVE_PARAMS_PTR ckParamPtr)
+CK_ECDH2_DERIVE_PARAMS_PTR
+jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_ECDH2_DERIVE_PARAMS_PTR ckParamPtr;
     jclass jEcdh2DeriveParamsClass;
     jfieldID fieldID;
     jlong jKdf, jPrivateDataLen, jPrivateData;
     jobject jSharedData, jPublicData, jPublicData2;
-    memset(ckParamPtr, 0, sizeof(CK_ECDH2_DERIVE_PARAMS));
 
-    /* get kdf */
+    // retrieve java values
     jEcdh2DeriveParamsClass = (*env)->FindClass(env, CLASS_ECDH2_DERIVE_PARAMS);
-    if (jEcdh2DeriveParamsClass == NULL) { return; }
+    if (jEcdh2DeriveParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "kdf", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jKdf = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get pSharedData and ulSharedDataLen */
     fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "pSharedData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jSharedData = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pPublicData and ulPublicDataLen */
     fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "pPublicData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get ulPrivateDataLen */
     fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "ulPrivateDataLen", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrivateDataLen = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get hPrivateData */
     fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "hPrivateData", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrivateData = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get pPublicData2 and ulPublicDataLen2 */
     fieldID = (*env)->GetFieldID(env, jEcdh2DeriveParamsClass, "pPublicData2", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPublicData2 = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_ECDH2_DERIVE_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_ECDH2_DERIVE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->kdf = jLongToCKULong(jKdf);
-    jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData), &(ckParamPtr->ulSharedDataLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
-    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+    jByteArrayToCKByteArray(env, jSharedData, &(ckParamPtr->pSharedData),
+            &(ckParamPtr->ulSharedDataLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pSharedData);
-        return;
+        goto cleanup;
+    }
+    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+            &(ckParamPtr->ulPublicDataLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
     }
     ckParamPtr->ulPrivateDataLen = jLongToCKULong(jPrivateDataLen);
     ckParamPtr->hPrivateData = jLongToCKULong(jPrivateData);
-    jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2), &(ckParamPtr->ulPublicDataLen2));
+    jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2),
+            &(ckParamPtr->ulPublicDataLen2));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pSharedData);
-        free(ckParamPtr->pPublicData);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_ECDH2_DERIVE_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pSharedData);
+    free(ckParamPtr->pPublicData);
+    free(ckParamPtr->pPublicData2);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_X9_42_DH1_DERIVE_PARAMS object to a CK_X9_42_DH1_DERIVE_PARAMS structure
+ * converts the Java CK_X9_42_DH1_DERIVE_PARAMS object to a
+ * CK_X9_42_DH1_DERIVE_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_X9_42_DH1_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_X9_42_DH1_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_X9_42_DH1_DERIVE_PARAMS structure
  */
-void jX942Dh1DeriveParamToCKX942Dh1DeriveParam(JNIEnv *env, jobject jParam,
-        CK_X9_42_DH1_DERIVE_PARAMS_PTR ckParamPtr)
+CK_X9_42_DH1_DERIVE_PARAMS_PTR
+jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_X9_42_DH1_DERIVE_PARAMS_PTR ckParamPtr;
     jclass jX942Dh1DeriveParamsClass;
     jfieldID fieldID;
     jlong jKdf;
     jobject jOtherInfo, jPublicData;
-    memset(ckParamPtr, 0, sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
 
-    /* get kdf */
-    jX942Dh1DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH1_DERIVE_PARAMS);
-    if (jX942Dh1DeriveParamsClass == NULL) { return; }
-    fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "kdf", "J");
-    if (fieldID == NULL) { return; }
-    jKdf = (*env)->GetLongField(env, jParam, fieldID);
+    if (pLength != NULL) {
+        *pLength = 0;
+    }
 
-    /* get pOtherInfo and ulOtherInfoLen */
+    // retrieve java values
+    jX942Dh1DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH1_DERIVE_PARAMS);
+    if (jX942Dh1DeriveParamsClass == NULL) { return NULL; }
+    fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "kdf", "J");
+    if (fieldID == NULL) { return NULL; }
+    jKdf = (*env)->GetLongField(env, jParam, fieldID);
     fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "pOtherInfo", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jOtherInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pPublicData and ulPublicDataLen */
     fieldID = (*env)->GetFieldID(env, jX942Dh1DeriveParamsClass, "pPublicData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_X9_42_DH1_DERIVE_PARAMS pointer
+    ckParamPtr = calloc(1, sizeof(CK_X9_42_DH1_DERIVE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->kdf = jLongToCKULong(jKdf);
-    jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo), &(ckParamPtr->ulOtherInfoLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
-    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+    jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo),
+            &(ckParamPtr->ulOtherInfoLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
+    }
+    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+            &(ckParamPtr->ulPublicDataLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pOtherInfo);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_X9_42_DH1_DERIVE_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pOtherInfo);
+    free(ckParamPtr->pPublicData);
+    free(ckParamPtr);
+    return NULL;
 }
 
 /*
- * converts the Java CK_X9_42_DH2_DERIVE_PARAMS object to a CK_X9_42_DH2_DERIVE_PARAMS structure
+ * converts the Java CK_X9_42_DH2_DERIVE_PARAMS object to a
+ * CK_X9_42_DH2_DERIVE_PARAMS pointer
  *
  * @param env - used to call JNI funktions to get the Java classes and objects
  * @param jParam - the Java CK_X9_42_DH2_DERIVE_PARAMS object to convert
- * @param ckParamPtr - pointer to the new CK_X9_42_DH2_DERIVE_PARAMS structure
+ * @param pLength - length of the allocated memory of the returned pointer
+ * @return pointer to the new CK_X9_42_DH2_DERIVE_PARAMS structure
  */
-void jX942Dh2DeriveParamToCKX942Dh2DeriveParam(JNIEnv *env, jobject jParam,
-        CK_X9_42_DH2_DERIVE_PARAMS_PTR ckParamPtr)
+CK_X9_42_DH2_DERIVE_PARAMS_PTR
+jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength)
 {
+    CK_X9_42_DH2_DERIVE_PARAMS_PTR ckParamPtr;
     jclass jX942Dh2DeriveParamsClass;
     jfieldID fieldID;
     jlong jKdf, jPrivateDataLen, jPrivateData;
     jobject jOtherInfo, jPublicData, jPublicData2;
-    memset(ckParamPtr, 0, sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
 
-    /* get kdf */
+    if (pLength != NULL) {
+        *pLength = 0L;
+    }
+
+    // retrieve java values
     jX942Dh2DeriveParamsClass = (*env)->FindClass(env, CLASS_X9_42_DH2_DERIVE_PARAMS);
-    if (jX942Dh2DeriveParamsClass == NULL) { return; }
+    if (jX942Dh2DeriveParamsClass == NULL) { return NULL; }
     fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "kdf", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jKdf = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get pOtherInfo and ulOtherInfoLen */
     fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "pOtherInfo", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jOtherInfo = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get pPublicData and ulPublicDataLen */
     fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "pPublicData", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPublicData = (*env)->GetObjectField(env, jParam, fieldID);
-
-    /* get ulPrivateDataLen */
     fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "ulPrivateDataLen", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrivateDataLen = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get hPrivateData */
     fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "hPrivateData", "J");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPrivateData = (*env)->GetLongField(env, jParam, fieldID);
-
-    /* get pPublicData2 and ulPublicDataLen2 */
     fieldID = (*env)->GetFieldID(env, jX942Dh2DeriveParamsClass, "pPublicData2", "[B");
-    if (fieldID == NULL) { return; }
+    if (fieldID == NULL) { return NULL; }
     jPublicData2 = (*env)->GetObjectField(env, jParam, fieldID);
 
-    /* populate java values */
+    // allocate memory for CK_DATE pointer
+    ckParamPtr = calloc(1, sizeof(CK_X9_42_DH2_DERIVE_PARAMS));
+    if (ckParamPtr == NULL) {
+        throwOutOfMemoryError(env, 0);
+        return NULL;
+    }
+
+    // populate using java values
     ckParamPtr->kdf = jLongToCKULong(jKdf);
-    jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo), &(ckParamPtr->ulOtherInfoLen));
-    if ((*env)->ExceptionCheck(env)) { return; }
-    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData), &(ckParamPtr->ulPublicDataLen));
+    jByteArrayToCKByteArray(env, jOtherInfo, &(ckParamPtr->pOtherInfo),
+            &(ckParamPtr->ulOtherInfoLen));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pOtherInfo);
-        return;
+        goto cleanup;
+    }
+    jByteArrayToCKByteArray(env, jPublicData, &(ckParamPtr->pPublicData),
+            &(ckParamPtr->ulPublicDataLen));
+    if ((*env)->ExceptionCheck(env)) {
+        goto cleanup;
     }
     ckParamPtr->ulPrivateDataLen = jLongToCKULong(jPrivateDataLen);
     ckParamPtr->hPrivateData = jLongToCKULong(jPrivateData);
-    jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2), &(ckParamPtr->ulPublicDataLen2));
+    jByteArrayToCKByteArray(env, jPublicData2, &(ckParamPtr->pPublicData2),
+            &(ckParamPtr->ulPublicDataLen2));
     if ((*env)->ExceptionCheck(env)) {
-        free(ckParamPtr->pOtherInfo);
-        free(ckParamPtr->pPublicData);
-        return;
+        goto cleanup;
+    }
+
+    if (pLength != NULL) {
+        *pLength = sizeof(CK_X9_42_DH2_DERIVE_PARAMS);
     }
+    return ckParamPtr;
+cleanup:
+    free(ckParamPtr->pOtherInfo);
+    free(ckParamPtr->pPublicData);
+    free(ckParamPtr->pPublicData2);
+    free(ckParamPtr);
+    return NULL;
 }
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c	Wed Aug 14 08:23:16 2019 -0400
@@ -198,8 +198,8 @@
         TRACE0("DEBUG: override CKA_NETSCAPE_DB attr value to TRUE\n");
     }
 
-    ckpAttributes = (CK_ATTRIBUTE_PTR)malloc(
-            CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
+    ckpAttributes = (CK_ATTRIBUTE_PTR) calloc(
+            CK_ATTRIBUTES_TEMPLATE_LENGTH, sizeof(CK_ATTRIBUTE));
     if (ckpAttributes == NULL) {
         throwOutOfMemoryError(env, 0);
         goto cleanup;
@@ -599,7 +599,7 @@
     ckpMechanism = jMechanismToCKMechanismPtr(env, jMechanism);
     if ((*env)->ExceptionCheck(env)) { return NULL; }
 
-    ckpKeyHandles = (CK_OBJECT_HANDLE_PTR) malloc(2 * sizeof(CK_OBJECT_HANDLE));
+    ckpKeyHandles = (CK_OBJECT_HANDLE_PTR) calloc(2, sizeof(CK_OBJECT_HANDLE));
     if (ckpKeyHandles == NULL) {
         throwOutOfMemoryError(env, 0);
         goto cleanup;
@@ -698,7 +698,8 @@
 
     rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, ckpMechanism, ckWrappingKeyHandle, ckKeyHandle, ckpWrappedKey, &ckWrappedKeyLength);
     if (rv == CKR_BUFFER_TOO_SMALL) {
-        ckpWrappedKey = (CK_BYTE_PTR) malloc(ckWrappedKeyLength);
+        ckpWrappedKey = (CK_BYTE_PTR)
+                calloc(ckWrappedKeyLength, sizeof(CK_BYTE));
         if (ckpWrappedKey == NULL) {
             throwOutOfMemoryError(env, 0);
             goto cleanup;
@@ -793,51 +794,6 @@
 
 #ifdef P11_ENABLE_C_DERIVEKEY
 
-static void freeMasterKeyDeriveParams(CK_SSL3_RANDOM_DATA *RandomInfo, CK_VERSION_PTR pVersion) {
-    if (RandomInfo->pClientRandom != NULL) {
-        free(RandomInfo->pClientRandom);
-    }
-    if (RandomInfo->pServerRandom != NULL) {
-        free(RandomInfo->pServerRandom);
-    }
-    if (pVersion != NULL) {
-        free(pVersion);
-    }
-}
-
-void ssl3FreeMasterKeyDeriveParams(CK_MECHANISM_PTR ckpMechanism) {
-    CK_SSL3_MASTER_KEY_DERIVE_PARAMS *params =
-            (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) ckpMechanism->pParameter;
-    if (params == NULL) {
-        return;
-    }
-    freeMasterKeyDeriveParams(&(params->RandomInfo), params->pVersion);
-}
-
-void tls12FreeMasterKeyDeriveParams(CK_MECHANISM_PTR ckpMechanism) {
-    CK_TLS12_MASTER_KEY_DERIVE_PARAMS *params =
-            (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)ckpMechanism->pParameter;
-    if (params == NULL) {
-        return;
-    }
-    freeMasterKeyDeriveParams(&(params->RandomInfo), params->pVersion);
-}
-
-void freeEcdh1DeriveParams(CK_MECHANISM_PTR ckpMechanism) {
-    CK_ECDH1_DERIVE_PARAMS *params =
-            (CK_ECDH1_DERIVE_PARAMS *)ckpMechanism->pParameter;
-    if (params == NULL) {
-        return;
-    }
-
-    if (params->pSharedData != NULL) {
-        free(params->pSharedData);
-    }
-    if (params->pPublicData != NULL) {
-        free(params->pPublicData);
-    }
-}
-
 /*
  * Copy back the PRF output to Java.
  */
@@ -897,12 +853,6 @@
             /* copy back the Java buffer to the object */
             (*env)->ReleaseByteArrayElements(env, jOutput, jBytes, 0);
         }
-
-        // free malloc'd data
-        free(ckTLSPrfParams->pSeed);
-        free(ckTLSPrfParams->pLabel);
-        free(ckTLSPrfParams->pulOutputLen);
-        free(ckTLSPrfParams->pOutput);
     }
 }
 
@@ -968,18 +918,9 @@
     case CKM_TLS_MASTER_KEY_DERIVE:
         /* we must copy back the client version */
         ssl3CopyBackClientVersion(env, ckpMechanism, jMechanism);
-        ssl3FreeMasterKeyDeriveParams(ckpMechanism);
         break;
     case CKM_TLS12_MASTER_KEY_DERIVE:
         tls12CopyBackClientVersion(env, ckpMechanism, jMechanism);
-        tls12FreeMasterKeyDeriveParams(ckpMechanism);
-        break;
-    case CKM_SSL3_MASTER_KEY_DERIVE_DH:
-    case CKM_TLS_MASTER_KEY_DERIVE_DH:
-        ssl3FreeMasterKeyDeriveParams(ckpMechanism);
-        break;
-    case CKM_TLS12_MASTER_KEY_DERIVE_DH:
-        tls12FreeMasterKeyDeriveParams(ckpMechanism);
         break;
     case CKM_SSL3_KEY_AND_MAC_DERIVE:
     case CKM_TLS_KEY_AND_MAC_DERIVE:
@@ -993,9 +934,6 @@
     case CKM_TLS_PRF:
         copyBackTLSPrfParams(env, ckpMechanism, jMechanism);
         break;
-    case CKM_ECDH1_DERIVE:
-        freeEcdh1DeriveParams(ckpMechanism);
-        break;
     default:
         // empty
         break;
@@ -1131,14 +1069,6 @@
         return;
     }
 
-    // free malloc'd data
-    if (RandomInfo->pClientRandom != NULL) {
-        free(RandomInfo->pClientRandom);
-    }
-    if (RandomInfo->pServerRandom != NULL) {
-        free(RandomInfo->pServerRandom);
-    }
-
     if (ckSSL3KeyMatOut != NULL_PTR) {
       /* get the Java params object (pParameter) */
       fieldID = (*env)->GetFieldID(env, jMechanismClass, "pParameter",
@@ -1200,8 +1130,6 @@
         /* copy back the Java buffer to the object */
         (*env)->ReleaseByteArrayElements(env, jIV, jBytes, 0);
       }
-      // free malloc'd data
-      free(ckSSL3KeyMatOut->pIVClient);
 
       /* copy back the server IV */
       fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "pIVServer", "[B");
@@ -1220,9 +1148,6 @@
         /* copy back the Java buffer to the object */
         (*env)->ReleaseByteArrayElements(env, jIV, jBytes, 0);
       }
-      // free malloc'd data
-      free(ckSSL3KeyMatOut->pIVServer);
-      free(ckSSL3KeyMatOut);
     }
 }
 
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c	Wed Aug 14 08:23:16 2019 -0400
@@ -290,17 +290,122 @@
 }
 
 /* This function frees the specified CK_MECHANISM_PTR pointer and its
- * pParameter. NOTE: mechanism-specific memory allocations have to be
- * freed before this call as this method only frees the generic
- * memory associated with CK_MECHANISM structure.
+ * pParameter including mechanism-specific memory allocations.
  *
  * @param mechPtr pointer to the to-be-freed CK_MECHANISM structure.
  */
+void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
+     void *tmp;
+     CK_SSL3_MASTER_KEY_DERIVE_PARAMS *sslMkdTmp;
+     CK_SSL3_KEY_MAT_PARAMS* sslKmTmp;
+     CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tlsMkdTmp;
+     CK_TLS12_KEY_MAT_PARAMS* tlsKmTmp;
 
-void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) {
      if (mechPtr != NULL) {
-         TRACE1("DEBUG: free CK_MECHANISM %x", mechPtr);
-         free(mechPtr->pParameter);
+         TRACE2("DEBUG: free mech %lX (mech id = 0x%lX)\n",
+                 ptr_to_jlong(mechPtr),  mechPtr->mechanism);
+         if (mechPtr->pParameter != NULL) {
+             switch (mechPtr->mechanism) {
+                 case CKM_AES_GCM:
+                     tmp = mechPtr->pParameter;
+                     TRACE1("\t=> free GCM_PARAMS %lX\n",
+                             ptr_to_jlong(tmp));
+                     free(((CK_GCM_PARAMS*)tmp)->pIv);
+                     free(((CK_GCM_PARAMS*)tmp)->pAAD);
+                     break;
+                 case CKM_AES_CCM:
+                     tmp = mechPtr->pParameter;
+                     TRACE1("\t=> free CK_CCM_PARAMS %lX\n",
+                             ptr_to_jlong(tmp));
+                     free(((CK_CCM_PARAMS*)tmp)->pNonce);
+                     free(((CK_CCM_PARAMS*)tmp)->pAAD);
+                     break;
+                 case CKM_TLS_PRF:
+                 case CKM_NSS_TLS_PRF_GENERAL:
+                     tmp = mechPtr->pParameter;
+                     TRACE1("\t=> free CK_TLS_PRF_PARAMS %lX\n",
+                         ptr_to_jlong(tmp));
+                     free(((CK_TLS_PRF_PARAMS*)tmp)->pSeed);
+                     free(((CK_TLS_PRF_PARAMS*)tmp)->pLabel);
+                     free(((CK_TLS_PRF_PARAMS*)tmp)->pulOutputLen);
+                     free(((CK_TLS_PRF_PARAMS*)tmp)->pOutput);
+                     break;
+                 case CKM_SSL3_MASTER_KEY_DERIVE:
+                 case CKM_TLS_MASTER_KEY_DERIVE:
+                 case CKM_SSL3_MASTER_KEY_DERIVE_DH:
+                 case CKM_TLS_MASTER_KEY_DERIVE_DH:
+                     sslMkdTmp = mechPtr->pParameter;
+                     TRACE1("\t=> free CK_SSL3_MASTER_KEY_DERIVE_PARAMS %lX\n",
+                         ptr_to_jlong(sslMkdTmp));
+                     free(sslMkdTmp->RandomInfo.pClientRandom);
+                     free(sslMkdTmp->RandomInfo.pServerRandom);
+                     free(sslMkdTmp->pVersion);
+                     break;
+                 case CKM_SSL3_KEY_AND_MAC_DERIVE:
+                 case CKM_TLS_KEY_AND_MAC_DERIVE:
+                     sslKmTmp = mechPtr->pParameter;
+                     TRACE1("\t=> free CK_SSL3_KEY_MAT_PARAMS %lX\n",
+                         ptr_to_jlong(sslKmTmp));
+                     free(sslKmTmp->RandomInfo.pClientRandom);
+                     free(sslKmTmp->RandomInfo.pServerRandom);
+                     if (sslKmTmp->pReturnedKeyMaterial != NULL) {
+                         free(sslKmTmp->pReturnedKeyMaterial->pIVClient);
+                         free(sslKmTmp->pReturnedKeyMaterial->pIVServer);
+                         free(sslKmTmp->pReturnedKeyMaterial);
+                     }
+                     break;
+                 case CKM_TLS12_MASTER_KEY_DERIVE:
+                 case CKM_TLS12_MASTER_KEY_DERIVE_DH:
+                     tlsMkdTmp = mechPtr->pParameter;
+                     TRACE1("\t=> CK_TLS12_MASTER_KEY_DERIVE_PARAMS %lX\n",
+                         ptr_to_jlong(tlsMkdTmp));
+                     free(tlsMkdTmp->RandomInfo.pClientRandom);
+                     free(tlsMkdTmp->RandomInfo.pServerRandom);
+                     free(tlsMkdTmp->pVersion);
+                     break;
+                 case CKM_TLS12_KEY_AND_MAC_DERIVE:
+                     tlsKmTmp = mechPtr->pParameter;
+                     TRACE1("\t=> free CK_TLS12_KEY_MAT_PARAMS %lX\n",
+                         ptr_to_jlong(tlsKmTmp));
+                     free(tlsKmTmp->RandomInfo.pClientRandom);
+                     free(tlsKmTmp->RandomInfo.pServerRandom);
+                     if (tlsKmTmp->pReturnedKeyMaterial != NULL) {
+                         free(tlsKmTmp->pReturnedKeyMaterial->pIVClient);
+                         free(tlsKmTmp->pReturnedKeyMaterial->pIVServer);
+                         free(tlsKmTmp->pReturnedKeyMaterial);
+                     }
+                     break;
+                 case CKM_ECDH1_DERIVE:
+                 case CKM_ECDH1_COFACTOR_DERIVE:
+                     tmp = mechPtr->pParameter;
+                     TRACE1("\t=> free CK_ECDH1_DERIVE_PARAMS %lX\n",
+                         ptr_to_jlong(tmp));
+                     free(((CK_ECDH1_DERIVE_PARAMS *)tmp)->pSharedData);
+                     free(((CK_ECDH1_DERIVE_PARAMS *)tmp)->pPublicData);
+                     break;
+                 case CKM_TLS_MAC:
+                 case CKM_AES_CTR:
+                 case CKM_RSA_PKCS_PSS:
+                 case CKM_CAMELLIA_CTR:
+                     TRACE0("\t=> NO OP\n");
+                     // params do not contain pointers
+                     break;
+                 default:
+                     // currently unsupported mechs by SunPKCS11 provider
+                     // CKM_RSA_PKCS_OAEP, CKM_ECMQV_DERIVE,
+                     // CKM_X9_42_*, CKM_KEA_DERIVE, CKM_RC2_*, CKM_RC5_*,
+                     // CKM_SKIPJACK_*, CKM_KEY_WRAP_SET_OAEP, CKM_PKCS5_PBKD2,
+                     // PBE mechs, WTLS mechs, CMS mechs,
+                     // CKM_EXTRACT_KEY_FROM_KEY, CKM_OTP, CKM_KIP,
+                     // CKM_DSA_PARAMETER_GEN?, CKM_GOSTR3410_*
+                     // CK_any_CBC_ENCRYPT_DATA?
+                     TRACE0("\t=> ERROR UNSUPPORTED CK PARAMS\n");
+                     break;
+             }
+             free(mechPtr->pParameter);
+         } else {
+             TRACE0("DEBUG => Parameter NULL\n");
+         }
          free(mechPtr);
      }
 }
@@ -356,7 +461,7 @@
         return;
     }
     *ckpLength = (*env)->GetArrayLength(env, jArray);
-    jpTemp = (jboolean*) malloc((*ckpLength) * sizeof(jboolean));
+    jpTemp = (jboolean*) calloc(*ckpLength, sizeof(jboolean));
     if (jpTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return;
@@ -367,7 +472,7 @@
         return;
     }
 
-    *ckpArray = (CK_BBOOL*) malloc ((*ckpLength) * sizeof(CK_BBOOL));
+    *ckpArray = (CK_BBOOL*) calloc (*ckpLength, sizeof(CK_BBOOL));
     if (*ckpArray == NULL) {
         free(jpTemp);
         throwOutOfMemoryError(env, 0);
@@ -398,7 +503,7 @@
         return;
     }
     *ckpLength = (*env)->GetArrayLength(env, jArray);
-    jpTemp = (jbyte*) malloc((*ckpLength) * sizeof(jbyte));
+    jpTemp = (jbyte*) calloc(*ckpLength, sizeof(jbyte));
     if (jpTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return;
@@ -413,7 +518,7 @@
     if (sizeof(CK_BYTE) == sizeof(jbyte)) {
         *ckpArray = (CK_BYTE_PTR) jpTemp;
     } else {
-        *ckpArray = (CK_BYTE_PTR) malloc ((*ckpLength) * sizeof(CK_BYTE));
+        *ckpArray = (CK_BYTE_PTR) calloc (*ckpLength, sizeof(CK_BYTE));
         if (*ckpArray == NULL) {
             free(jpTemp);
             throwOutOfMemoryError(env, 0);
@@ -445,7 +550,7 @@
         return;
     }
     *ckpLength = (*env)->GetArrayLength(env, jArray);
-    jTemp = (jlong*) malloc((*ckpLength) * sizeof(jlong));
+    jTemp = (jlong*) calloc(*ckpLength, sizeof(jlong));
     if (jTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return;
@@ -456,7 +561,7 @@
         return;
     }
 
-    *ckpArray = (CK_ULONG_PTR) malloc (*ckpLength * sizeof(CK_ULONG));
+    *ckpArray = (CK_ULONG_PTR) calloc(*ckpLength, sizeof(CK_ULONG));
     if (*ckpArray == NULL) {
         free(jTemp);
         throwOutOfMemoryError(env, 0);
@@ -487,7 +592,7 @@
         return;
     }
     *ckpLength = (*env)->GetArrayLength(env, jArray);
-    jpTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
+    jpTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
     if (jpTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return;
@@ -498,7 +603,7 @@
         return;
     }
 
-    *ckpArray = (CK_CHAR_PTR) malloc (*ckpLength * sizeof(CK_CHAR));
+    *ckpArray = (CK_CHAR_PTR) calloc (*ckpLength, sizeof(CK_CHAR));
     if (*ckpArray == NULL) {
         free(jpTemp);
         throwOutOfMemoryError(env, 0);
@@ -529,7 +634,7 @@
         return;
     }
     *ckpLength = (*env)->GetArrayLength(env, jArray);
-    jTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar));
+    jTemp = (jchar*) calloc(*ckpLength, sizeof(jchar));
     if (jTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return;
@@ -540,7 +645,7 @@
         return;
     }
 
-    *ckpArray = (CK_UTF8CHAR_PTR) malloc (*ckpLength * sizeof(CK_UTF8CHAR));
+    *ckpArray = (CK_UTF8CHAR_PTR) calloc(*ckpLength, sizeof(CK_UTF8CHAR));
     if (*ckpArray == NULL) {
         free(jTemp);
         throwOutOfMemoryError(env, 0);
@@ -575,7 +680,7 @@
     if (pCharArray == NULL) { return; }
 
     *ckpLength = (CK_ULONG) strlen(pCharArray);
-    *ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR));
+    *ckpArray = (CK_UTF8CHAR_PTR) calloc(*ckpLength + 1, sizeof(CK_UTF8CHAR));
     if (*ckpArray == NULL) {
         (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray);
         throwOutOfMemoryError(env, 0);
@@ -609,7 +714,7 @@
     }
     jLength = (*env)->GetArrayLength(env, jArray);
     *ckpLength = jLongToCKULong(jLength);
-    *ckpArray = (CK_ATTRIBUTE_PTR) malloc(*ckpLength * sizeof(CK_ATTRIBUTE));
+    *ckpArray = (CK_ATTRIBUTE_PTR) calloc(*ckpLength, sizeof(CK_ATTRIBUTE));
     if (*ckpArray == NULL) {
         throwOutOfMemoryError(env, 0);
         return;
@@ -651,7 +756,7 @@
     if (sizeof(CK_BYTE) == sizeof(jbyte)) {
         jpTemp = (jbyte*) ckpArray;
     } else {
-        jpTemp = (jbyte*) malloc((ckLength) * sizeof(jbyte));
+        jpTemp = (jbyte*) calloc(ckLength, sizeof(jbyte));
         if (jpTemp == NULL) {
             throwOutOfMemoryError(env, 0);
             return NULL;
@@ -685,7 +790,7 @@
     jlong* jpTemp;
     jlongArray jArray;
 
-    jpTemp = (jlong*) malloc((ckLength) * sizeof(jlong));
+    jpTemp = (jlong*) calloc(ckLength, sizeof(jlong));
     if (jpTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return NULL;
@@ -716,7 +821,7 @@
     jchar* jpTemp;
     jcharArray jArray;
 
-    jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
+    jpTemp = (jchar*) calloc(ckLength, sizeof(jchar));
     if (jpTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return NULL;
@@ -747,7 +852,7 @@
     jchar* jpTemp;
     jcharArray jArray;
 
-    jpTemp = (jchar*) malloc(ckLength * sizeof(jchar));
+    jpTemp = (jchar*) calloc(ckLength, sizeof(jchar));
     if (jpTemp == NULL) {
         throwOutOfMemoryError(env, 0);
         return NULL;
@@ -1051,7 +1156,7 @@
     jDateClass = (*env)->FindClass(env, CLASS_DATE);
     if (jDateClass == NULL) { return NULL; }
     if ((*env)->IsInstanceOf(env, jObject, jDateClass)) {
-        ckpObject = jDateObjectPtrToCKDatePtr(env, jObject);
+        ckpObject = jDateObjectToCKDatePtr(env, jObject);
         *ckpLength = sizeof(CK_DATE);
         TRACE3("<converted date value %.4s-%.2s-%.2s>", ((CK_DATE *) ckpObject)->year,
                 ((CK_DATE *) ckpObject)->month, ((CK_DATE *) ckpObject)->day);
@@ -1123,7 +1228,7 @@
     if (classNameString == NULL) { return NULL; }
     exceptionMsgPrefix = "Java object of this class cannot be converted to native PKCS#11 type: ";
     exceptionMsg = (char *)
-        malloc((strlen(exceptionMsgPrefix) + strlen(classNameString) + 1));
+        malloc(strlen(exceptionMsgPrefix) + strlen(classNameString) + 1);
     if (exceptionMsg == NULL) {
         (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString);
         throwOutOfMemoryError(env, 0);
@@ -1143,16 +1248,26 @@
 #ifdef P11_MEMORYDEBUG
 
 #undef malloc
+#undef calloc
 #undef free
 
 void *p11malloc(size_t c, char *file, int line) {
     void *p = malloc(c);
-    printf("malloc\t%08x\t%d\t%s:%d\n", p, c, file, line); fflush(stdout);
+    fprintf(stdout, "malloc\t%08lX\t%lX\t%s:%d\n", ptr_to_jlong(p), c, file, line);
+    fflush(stdout);
+    return p;
+}
+
+void *p11calloc(size_t c, size_t s, char *file, int line) {
+    void *p = calloc(c, s);
+    fprintf(stdout, "calloc\t%08lX\t%lX\t%lX\t%s:%d\n", ptr_to_jlong(p), c, s, file, line);
+    fflush(stdout);
     return p;
 }
 
 void p11free(void *p, char *file, int line) {
-    printf("free\t%08x\t\t%s:%d\n", p, file, line); fflush(stdout);
+    fprintf(stdout, "free\t%08lX\t\t%s:%d\n", ptr_to_jlong(p), file, line);
+    fflush(stdout);
     free(p);
 }
 
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h	Wed Aug 14 08:08:39 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h	Wed Aug 14 08:23:16 2019 -0400
@@ -207,6 +207,10 @@
 #define ckULongToJSize(x)       ((jsize) x)
 #define unsignedIntToCKULong(x) ((CK_ULONG) x)
 
+//#define TRACE0d(s) { printf(s); fflush(stdout); }
+//#define TRACE1d(s, p1) { printf(s, p1); fflush(stdout); }
+//#define TRACE2d(s, p1, p2) { printf(s, p1, p2); fflush(stdout); }
+
 #ifdef P11_DEBUG
 #define TRACE0(s) { printf(s); fflush(stdout); }
 #define TRACE1(s, p1) { printf(s, p1); fflush(stdout); }
@@ -352,7 +356,7 @@
 CK_ULONG* jLongObjectToCKULongPtr(JNIEnv *env, jobject jObject);
 CK_CHAR_PTR jCharObjectToCKCharPtr(JNIEnv *env, jobject jObject);
 CK_VERSION_PTR jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion);
-CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate);
+CK_DATE * jDateObjectToCKDatePtr(JNIEnv *env, jobject jDate);
 CK_ATTRIBUTE jAttributeToCKAttribute(JNIEnv *env, jobject jAttribute);
 CK_MECHANISM_PTR jMechanismToCKMechanismPtr(JNIEnv *env, jobject jMechanism);
 
@@ -363,26 +367,29 @@
 *ckpLength);
 
 
-/* functions to convert a specific Java mechanism parameter object to a CK-mechanism parameter structure */
+/* functions to convert a specific Java mechanism parameter object to a CK-mechanism parameter pointer */
 
-void jRsaPkcsOaepParamToCKRsaPkcsOaepParam(JNIEnv *env, jobject jParam, CK_RSA_PKCS_OAEP_PARAMS_PTR ckParamPtr);
-void jPbeParamToCKPbeParam(JNIEnv *env, jobject jParam, CK_PBE_PARAMS_PTR ckParamPtr);
+CK_RSA_PKCS_OAEP_PARAMS_PTR jRsaPkcsOaepParamToCKRsaPkcsOaepParamPtr(JNIEnv *env,
+    jobject jParam, CK_ULONG* pLength);
+CK_PBE_PARAMS_PTR jPbeParamToCKPbeParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_PKCS5_PBKD2_PARAMS_PTR jPkcs5Pbkd2ParamToCKPkcs5Pbkd2ParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_SSL3_KEY_MAT_PARAMS_PTR jSsl3KeyMatParamToCKSsl3KeyMatParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_KEY_DERIVATION_STRING_DATA jKeyDerivationStringDataToCKKeyDerivationStringData(JNIEnv *env, jobject jParam);
+CK_RSA_PKCS_PSS_PARAMS_PTR jRsaPkcsPssParamToCKRsaPkcsPssParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_ECDH1_DERIVE_PARAMS_PTR jEcdh1DeriveParamToCKEcdh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_ECDH2_DERIVE_PARAMS_PTR jEcdh2DeriveParamToCKEcdh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_X9_42_DH1_DERIVE_PARAMS_PTR jX942Dh1DeriveParamToCKX942Dh1DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+CK_X9_42_DH2_DERIVE_PARAMS_PTR jX942Dh2DeriveParamToCKX942Dh2DeriveParamPtr(JNIEnv *env, jobject jParam, CK_ULONG* pLength);
+
+/* functions to copy the returned values inside CK-mechanism back to Java object */
+
 void copyBackPBEInitializationVector(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-void jPkcs5Pbkd2ParamToCKPkcs5Pbkd2Param(JNIEnv *env, jobject jParam, CK_PKCS5_PBKD2_PARAMS_PTR ckParamPtr);
 void copyBackSetUnwrappedKey(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-void jSsl3MasterKeyDeriveParamToCKSsl3MasterKeyDeriveParam(JNIEnv *env, jobject jParam, CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR ckParamPtr);
 void ssl3CopyBackClientVersion(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
 void tls12CopyBackClientVersion(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-void jSsl3KeyMatParamToCKSsl3KeyMatParam(JNIEnv *env, jobject jParam, CK_SSL3_KEY_MAT_PARAMS_PTR ckParamPtr);
 void ssl3CopyBackKeyMatParams(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
 void tls12CopyBackKeyMatParams(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism);
-CK_KEY_DERIVATION_STRING_DATA jKeyDerivationStringDataToCKKeyDerivationStringData(JNIEnv *env, jobject jParam);
-void jRsaPkcsPssParamToCKRsaPkcsPssParam(JNIEnv *env, jobject jParam, CK_RSA_PKCS_PSS_PARAMS_PTR ckParamPtr);
-void jEcdh1DeriveParamToCKEcdh1DeriveParam(JNIEnv *env, jobject jParam, CK_ECDH1_DERIVE_PARAMS_PTR ckParamPtr);
-void jEcdh2DeriveParamToCKEcdh2DeriveParam(JNIEnv *env, jobject jParam,
-CK_ECDH2_DERIVE_PARAMS_PTR ckParamPtr);
-void jX942Dh1DeriveParamToCKX942Dh1DeriveParam(JNIEnv *env, jobject jParam, CK_X9_42_DH1_DERIVE_PARAMS_PTR ckParamPtr);
-void jX942Dh2DeriveParamToCKX942Dh2DeriveParam(JNIEnv *env, jobject jParam, CK_X9_42_DH2_DERIVE_PARAMS_PTR ckParamPtr);
 
 
 /* functions to convert the InitArgs object for calling the right Java mutex functions */
@@ -462,8 +469,9 @@
 #ifdef P11_MEMORYDEBUG
 #include <stdlib.h>
 
-/* Simple malloc/free dumper */
+/* Simple malloc/calloc/free dumper */
 void *p11malloc(size_t c, char *file, int line);
+void *p11calloc(size_t c, size_t s, char *file, int line);
 void p11free(void *p, char *file, int line);
 
 /* Use THIS_FILE when it is available. */
@@ -472,6 +480,7 @@
 #endif
 
 #define malloc(c)       (p11malloc((c), THIS_FILE, __LINE__))
+#define calloc(c, s)    (p11calloc((c), (s), THIS_FILE, __LINE__))
 #define free(c)         (p11free((c), THIS_FILE, __LINE__))
 
 #endif
--- a/test/hotspot/jtreg/ProblemList.txt	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList.txt	Wed Aug 14 08:23:16 2019 -0400
@@ -49,8 +49,9 @@
 compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all
 compiler/tiered/LevelTransitionTest.java 8067651 generic-all
 
-compiler/types/correctness/CorrectnessTest.java 8225670,8225620 generic-all,solaris-sparcv9
-compiler/types/correctness/OffTest.java         8225670,8225620 generic-all,solaris-sparcv9
+compiler/types/correctness/CorrectnessTest.java 8225620 solaris-sparcv9
+compiler/types/correctness/OffTest.java         8225620 solaris-sparcv9
+compiler/unsafe/UnsafeGetConstantField.java     8229446 solaris-sparcv9
 
 compiler/c2/Test6852078.java 8194310 generic-all
 compiler/c2/Test8004741.java 8214904 generic-all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/controldependency/TestAntiDependentMembar.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,450 @@
+/*
+ * 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 8228772
+ * @summary Test correct insertion of anti-dependencies if load is already control dependent on membar.
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ *                   -XX:CompileCommand=inline,compiler.controldependency.TestAntiDependentMembar::hitSearchLimit
+ *                   compiler.controldependency.TestAntiDependentMembar
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ *                   -XX:CompileCommand=inline,compiler.controldependency.TestAntiDependentMembar::hitSearchLimit
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:DominatorSearchLimit=0
+ *                   compiler.controldependency.TestAntiDependentMembar
+ */
+
+package compiler.controldependency;
+
+public class TestAntiDependentMembar {
+
+    static volatile int step1 = 0;
+    static volatile int step2 = 0;
+
+    public static int test1(int count, int b1, int b2) {
+        int[] result = {0};
+
+        // Complex control flow to generate Region with 4 paths and therefore bail out of Node::dominates
+        if (b1 == 0) {
+            count += 1;
+        } else if (b1 == 1) {
+            if (b2 == 1) {
+                count += 2;
+            }
+        }
+
+        for (int i = 0; i < count; ++i) {
+            // Volatile field write adds a membar
+            step1 = i;
+            // Load that is dependent on the membar
+            result[0] += count;
+        }
+        return result[0];
+    }
+
+    // Same as test1 but bailing out of Node::dominates due to hitting DominatorSearchLimit
+    public static int test2(int count) {
+        int[] result = {0};
+
+        // Large method with regions to hit the DominatorSearchLimit
+        hitSearchLimit();
+
+        for (int i = 0; i < count; ++i) {
+            step1 = i;
+            result[0] += count;
+        }
+        return result[0];
+    }
+
+    // Same as test2 but with multiple membars before the load
+    public static int test3(int count) {
+        int[] result = {0};
+
+        hitSearchLimit();
+
+        for (int i = 0; i < count; ++i) {
+            step1 = i;
+            step2 = i;
+            step1 = i;
+            step2 = i;
+            result[0] += count;
+        }
+        return result[0];
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 50_000; ++i) {
+          test1(10, 0, 0);
+          test1(10, 1, 1);
+          test1(10, 1, 0);
+          test1(10, 0, 1);
+          test2(10);
+          test3(10);
+        }
+    }
+
+    public static void hitSearchLimit() {
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+        step1++;
+        step2++;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/eliminateAutobox/TestSplitThroughPhi.java	Wed Aug 14 08:23:16 2019 -0400
@@ -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.
+ */
+
+/*
+ * @test
+ * @bug 8224957
+ * @summary Test splitting a boxed field load through a loop Phi.
+ * @run main/othervm -XX:-TieredCompilation -XX:-ProfileInterpreter
+ *                   -XX:CompileOnly=compiler.eliminateAutobox.TestSplitThroughPhi::test
+ *                   compiler.eliminateAutobox.TestSplitThroughPhi
+ */
+
+package compiler.eliminateAutobox;
+
+public class TestSplitThroughPhi {
+
+  static volatile boolean loop = true;
+
+  public static void test(Object obj) {
+      for (int i = 0; i == 0; ) {
+          // OSR compilation generates Region with 3 input paths
+          while (true) {
+              // Load from boxed int
+              int val = (Integer)obj;
+              if (val == i++) break;
+              if (!loop) break;
+          }
+      }
+  }
+
+  public static void main(String[] args) {
+      test(100_000);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Monitor/NonOwnerOps.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,83 @@
+/*
+ * 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 8229212
+ * @summary Verify that monitor operations by a non-owner thread throw
+ *          IllegalMonitorStateException.
+ * @run main NonOwnerOps
+ */
+
+public class NonOwnerOps {
+    public static void main(String[] args) {
+        int error_count = 0;
+        Object obj;
+
+        obj = new Object();
+        try {
+            obj.wait();
+            System.err.println("ERROR: wait() by non-owner thread did not " +
+                               "throw IllegalMonitorStateException.");
+            error_count++;
+        } catch (InterruptedException ie) {
+            System.err.println("ERROR: wait() by non-owner thread threw " +
+                               "InterruptedException which is not expected.");
+            error_count++;
+        } catch (IllegalMonitorStateException imse) {
+            System.out.println("wait() by non-owner thread threw the " +
+                               "expected IllegalMonitorStateException:");
+            System.out.println("    " + imse);
+        }
+
+        obj = new Object();
+        try {
+            obj.notify();
+            System.err.println("ERROR: notify() by non-owner thread did not " +
+                               "throw IllegalMonitorStateException.");
+            error_count++;
+        } catch (IllegalMonitorStateException imse) {
+            System.out.println("notify() by non-owner thread threw the " +
+                               "expected IllegalMonitorStateException:");
+            System.out.println("    " + imse);
+        }
+
+        obj = new Object();
+        try {
+            obj.notifyAll();
+            System.err.println("ERROR: notifyAll() by non-owner thread did " +
+                               "not throw IllegalMonitorStateException.");
+            error_count++;
+        } catch (IllegalMonitorStateException imse) {
+            System.out.println("notifyAll() by non-owner thread threw the " +
+                               "expected IllegalMonitorStateException:");
+            System.out.println("    " + imse);
+        }
+
+        if (error_count != 0) {
+            throw new RuntimeException("Test failed with " + error_count +
+                                       " errors.");
+        }
+        System.out.println("Test PASSED.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/LdapCtx/Reconnect.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,117 @@
+/*
+ * 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.naming.Context;
+import javax.naming.ldap.InitialLdapContext;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.Hashtable;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/*
+ * @test
+ * @bug 8217606
+ * @summary The LdapContext.reconnect method allows LDAP clients to initiate an
+ *          LDAP bind operation on the existing connection. Invoking this method
+ *          should not open a new connection under those circumstances.
+ *
+ * @library ../lib/
+ * @run main Reconnect
+ */
+public class Reconnect {
+
+    private static final byte[] BIND_RESPONSE = {
+            0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A,
+            0x01, 0x00, 0x04, 0x00, 0x04, 0x00
+    };
+
+    /*
+     * This test checks that there's only one connection from the client to
+     * the server.
+     *
+     * The mechanics is as follows. The first connection is awaited for some
+     * generous timeout to factor in a possibility of running on a slow system.
+     * Once the connection has been made, the second timeout begins. This
+     * second timeout is smaller. The test then verifies that no further
+     * connections have been made for that amount of time.
+     */
+    public static void main(String[] args) throws Exception {
+
+        final Semaphore s = new Semaphore(0);
+
+        BaseLdapServer server = new BaseLdapServer() {
+
+            @Override
+            protected void beforeConnectionHandled(Socket socket) {
+                // Increment the number of connections from LDAP client
+                s.release(1);
+            }
+
+            @Override
+            protected void handleRequest(Socket socket,
+                                         LdapMessage msg,
+                                         OutputStream out)
+                    throws IOException
+            {
+                switch (msg.getOperation()) {
+                    case BIND_REQUEST:
+                        out.write(BIND_RESPONSE);
+                    default:
+                        break;
+                }
+            }
+        };
+
+        try (var s1 = server.start()) {
+            Hashtable<String, Object> env = new Hashtable<>();
+            env.put(Context.INITIAL_CONTEXT_FACTORY,
+                    "com.sun.jndi.ldap.LdapCtxFactory");
+            env.put(Context.PROVIDER_URL,
+                    "ldap://" + InetAddress.getLoopbackAddress().getHostName()
+                            + ":" + server.getPort());
+            env.put("java.naming.ldap.version", "3");
+
+            // open connection
+            InitialLdapContext context = new InitialLdapContext(env, null);
+
+            // send bind request
+            context.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
+            context.addToEnvironment(Context.SECURITY_PRINCIPAL, "test");
+            context.addToEnvironment(Context.SECURITY_CREDENTIALS, "secret");
+
+            context.reconnect(null);
+        }
+
+        if (!s.tryAcquire(60L, TimeUnit.SECONDS)) {
+            throw new RuntimeException("No connection has been made");
+        }
+
+        if (s.tryAcquire(5L, TimeUnit.SECONDS)) {
+            throw new RuntimeException("Expected 1 connection, but found: "
+                                               + (s.availablePermits() + 2));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/lib/BaseLdapServer.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,268 @@
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+
+import static java.lang.System.Logger.Level.INFO;
+
+/*
+ * A bare-bones (testing aid) server for LDAP scenarios.
+ *
+ * Override the following methods to provide customized behavior
+ *
+ *     * beforeConnectionHandled
+ *     * handleRequest
+ *
+ * Instances of this class are safe for use by multiple threads.
+ */
+public class BaseLdapServer implements Closeable {
+
+    private static final System.Logger logger = System.getLogger("BaseLdapServer");
+
+    private final Thread acceptingThread = new Thread(this::acceptConnections);
+    private final ServerSocket serverSocket;
+    private final List<Socket> socketList = new ArrayList<>();
+    private final ExecutorService connectionsPool;
+
+    private final Object lock = new Object();
+    /*
+     * 3-valued state to detect restarts and other programming errors.
+     */
+    private State state = State.NEW;
+
+    private enum State {
+        NEW,
+        STARTED,
+        STOPPED
+    }
+
+    public BaseLdapServer() throws IOException {
+        this(new ServerSocket(0, 0, InetAddress.getLoopbackAddress()));
+    }
+
+    public BaseLdapServer(ServerSocket serverSocket) {
+        this.serverSocket = Objects.requireNonNull(serverSocket);
+        this.connectionsPool = Executors.newCachedThreadPool();
+    }
+
+    private void acceptConnections() {
+        logger().log(INFO, "Server is accepting connections at port {0}",
+                     getPort());
+        try {
+            while (isRunning()) {
+                Socket socket = serverSocket.accept();
+                logger().log(INFO, "Accepted new connection at {0}", socket);
+                synchronized (lock) {
+                    // Recheck if the server is still running
+                    // as someone has to close the `socket`
+                    if (isRunning()) {
+                        socketList.add(socket);
+                    } else {
+                        closeSilently(socket);
+                    }
+                }
+                connectionsPool.submit(() -> handleConnection(socket));
+            }
+        } catch (IOException | RejectedExecutionException e) {
+            if (isRunning()) {
+                throw new RuntimeException(
+                        "Unexpected exception while accepting connections", e);
+            }
+        } finally {
+            logger().log(INFO, "Server stopped accepting connections at port {0}",
+                                getPort());
+        }
+    }
+
+    /*
+     * A "Template Method" describing how a connection (represented by a socket)
+     * is handled.
+     *
+     * The socket is closed immediately before the method returns (normally or
+     * abruptly).
+     */
+    private void handleConnection(Socket socket) {
+        // No need to close socket's streams separately, they will be closed
+        // automatically when `socket.close()` is called
+        beforeConnectionHandled(socket);
+        try (socket) {
+            OutputStream out = socket.getOutputStream();
+            InputStream in = socket.getInputStream();
+            byte[] inBuffer = new byte[1024];
+            int count;
+            byte[] request;
+
+            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+            int msgLen = -1;
+
+            // As inBuffer.length > 0, at least 1 byte is read
+            while ((count = in.read(inBuffer)) > 0) {
+                buffer.write(inBuffer, 0, count);
+                if (msgLen <= 0) {
+                    msgLen = LdapMessage.getMessageLength(buffer.toByteArray());
+                }
+
+                if (msgLen > 0 && buffer.size() >= msgLen) {
+                    if (buffer.size() > msgLen) {
+                        byte[] tmpBuffer = buffer.toByteArray();
+                        request = Arrays.copyOf(tmpBuffer, msgLen);
+                        buffer.reset();
+                        buffer.write(tmpBuffer, msgLen, tmpBuffer.length - msgLen);
+                    } else {
+                        request = buffer.toByteArray();
+                        buffer.reset();
+                    }
+                    msgLen = -1;
+                } else {
+                    logger.log(INFO, "Request message incomplete, " +
+                            "bytes received {0}, expected {1}", buffer.size(), msgLen);
+                    continue;
+                }
+                handleRequest(socket, new LdapMessage(request), out);
+            }
+        } catch (Throwable t) {
+            if (!isRunning()) {
+                logger.log(INFO, "Connection Handler exit {0}", t.getMessage());
+            } else {
+                t.printStackTrace();
+            }
+        }
+    }
+
+    /*
+     * Called first thing in `handleConnection()`.
+     *
+     * Override to customize the behavior.
+     */
+    protected void beforeConnectionHandled(Socket socket) { /* empty */ }
+
+    /*
+     * Called after an LDAP request has been read in `handleConnection()`.
+     *
+     * Override to customize the behavior.
+     */
+    protected void handleRequest(Socket socket,
+                                 LdapMessage request,
+                                 OutputStream out)
+            throws IOException
+    {
+        logger().log(INFO, "Discarding message {0} from {1}. "
+                             + "Override {2}.handleRequest to change this behavior.",
+                     request, socket, getClass().getName());
+    }
+
+    /*
+     * To be used by subclasses.
+     */
+    protected final System.Logger logger() {
+        return logger;
+    }
+
+    /*
+     * Starts this server. May be called only once.
+     */
+    public BaseLdapServer start() {
+        synchronized (lock) {
+            if (state != State.NEW) {
+                throw new IllegalStateException(state.toString());
+            }
+            state = State.STARTED;
+            logger().log(INFO, "Starting server at port {0}", getPort());
+            acceptingThread.start();
+            return this;
+        }
+    }
+
+    /*
+     * Stops this server.
+     *
+     * May be called at any time, even before a call to `start()`. In the latter
+     * case the subsequent call to `start()` will throw an exception. Repeated
+     * calls to this method have no effect.
+     *
+     * Stops accepting new connections, interrupts the threads serving already
+     * accepted connections and closes all the sockets.
+     */
+    @Override
+    public void close() {
+        synchronized (lock) {
+            if (state == State.STOPPED) {
+                return;
+            }
+            state = State.STOPPED;
+            logger().log(INFO, "Stopping server at port {0}", getPort());
+            acceptingThread.interrupt();
+            closeSilently(serverSocket);
+            // It's important to signal an interruption so that overridden
+            // methods have a chance to return if they use
+            // interruption-sensitive blocking operations. However, blocked I/O
+            // operations on the socket will NOT react on that, hence the socket
+            // also has to be closed to propagate shutting down.
+            connectionsPool.shutdownNow();
+            socketList.forEach(BaseLdapServer.this::closeSilently);
+        }
+    }
+
+    /**
+     * Returns the local port this server is listening at.
+     *
+     * @return the port this server is listening at
+     */
+    public int getPort() {
+        return serverSocket.getLocalPort();
+    }
+
+    /*
+     * Returns a flag to indicate whether this server is running or not.
+     *
+     * @return {@code true} if this server is running, {@code false} otherwise.
+     */
+    public boolean isRunning() {
+        synchronized (lock) {
+            return state == State.STARTED;
+        }
+    }
+
+    /*
+     * To be used by subclasses.
+     */
+    protected final void closeSilently(Closeable resource) {
+        try {
+            resource.close();
+        } catch (IOException ignored) { }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/lib/LdapMessage.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,228 @@
+/*
+ * 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.math.BigInteger;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * An LDAP message.
+ */
+public class LdapMessage {
+
+    private final byte[] message;
+    private int messageID;
+    private Operation operation;
+
+    public enum Operation {
+        BIND_REQUEST(0x60, "BindRequest"),                      // [APPLICATION 0]
+        BIND_RESPONSE(0x61, "BindResponse"),                    // [APPLICATION 1]
+        UNBIND_REQUEST(0x42, "UnbindRequest"),                  // [APPLICATION 2]
+        SEARCH_REQUEST(0x63, "SearchRequest"),                  // [APPLICATION 3]
+        SEARCH_RESULT_ENTRY(0x64, "SearchResultEntry"),         // [APPLICATION 4]
+        SEARCH_RESULT_DONE(0x65, "SearchResultDone"),           // [APPLICATION 5]
+        MODIFY_REQUEST(0x66, "ModifyRequest"),                  // [APPLICATION 6]
+        MODIFY_RESPONSE(0x67, "ModifyResponse"),                // [APPLICATION 7]
+        ADD_REQUEST(0x68, "AddRequest"),                        // [APPLICATION 8]
+        ADD_RESPONSE(0x69, "AddResponse"),                      // [APPLICATION 9]
+        DELETE_REQUEST(0x4A, "DeleteRequest"),                  // [APPLICATION 10]
+        DELETE_RESPONSE(0x6B, "DeleteResponse"),                // [APPLICATION 11]
+        MODIFY_DN_REQUEST(0x6C, "ModifyDNRequest"),             // [APPLICATION 12]
+        MODIFY_DN_RESPONSE(0x6D, "ModifyDNResponse"),           // [APPLICATION 13]
+        COMPARE_REQUEST(0x6E, "CompareRequest"),                // [APPLICATION 14]
+        COMPARE_RESPONSE(0x6F, "CompareResponse"),              // [APPLICATION 15]
+        ABANDON_REQUEST(0x50, "AbandonRequest"),                // [APPLICATION 16]
+        SEARCH_RESULT_REFERENCE(0x73, "SearchResultReference"), // [APPLICATION 19]
+        EXTENDED_REQUEST(0x77, "ExtendedRequest"),              // [APPLICATION 23]
+        EXTENDED_RESPONSE(0x78, "ExtendedResponse"),            // [APPLICATION 24]
+        INTERMEDIATE_RESPONSE(0x79, "IntermediateResponse");    // [APPLICATION 25]
+
+        private final int id;
+        private final String name;
+
+        Operation(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        private static Operation fromId(int id) {
+            Optional<Operation> optional = Stream.of(Operation.values())
+                    .filter(o -> o.id == id).findFirst();
+            if (optional.isPresent()) {
+                return optional.get();
+            } else {
+                throw new RuntimeException(
+                        "Unknown id " + id + " for enum Operation.");
+            }
+        }
+    }
+
+    public LdapMessage(byte[] message) {
+        this.message = message;
+        parse();
+    }
+
+    public LdapMessage(String hexString) {
+        this(parseHexBinary(hexString));
+    }
+
+    // Extracts the message ID and operation ID from an LDAP protocol encoding
+    private void parse() {
+        if (message == null || message.length < 2) {
+            throw new RuntimeException(
+                    "Invalid ldap message: " + Arrays.toString(message));
+        }
+
+        if (message[0] != 0x30) {
+            throw new RuntimeException("Bad LDAP encoding in message, "
+                    + "expected ASN.1 SEQUENCE tag (0x30), encountered "
+                    + message[0]);
+        }
+
+        int index = 2;
+        if ((message[1] & 0x80) == 0x80) {
+            index += (message[1] & 0x0F);
+        }
+
+        if (message[index] != 0x02) {
+            throw new RuntimeException("Bad LDAP encoding in message, "
+                    + "expected ASN.1 INTEGER tag (0x02), encountered "
+                    + message[index]);
+        }
+        int length = message[index + 1];
+        index += 2;
+        messageID = new BigInteger(1,
+                                   Arrays.copyOfRange(message, index, index + length)).intValue();
+        index += length;
+        int operationID = message[index];
+        operation = Operation.fromId(operationID);
+    }
+
+    /**
+     * Return original ldap message in byte array.
+     *
+     * @return original ldap message
+     */
+    public byte[] getMessage() {
+        return Arrays.copyOf(message, message.length);
+    }
+
+    /**
+     * Return ldap message id.
+     *
+     * @return ldap message id.
+     */
+    public int getMessageID() {
+        return messageID;
+    }
+
+    /**
+     * Return ldap message's operation.
+     *
+     * @return ldap message's operation.
+     */
+    public Operation getOperation() {
+        return operation;
+    }
+
+    private static byte[] parseHexBinary(String s) {
+
+        final int len = s.length();
+
+        // "111" is not a valid hex encoding.
+        if (len % 2 != 0) {
+            throw new IllegalArgumentException(
+                    "hexBinary needs to be even-length: " + s);
+        }
+
+        byte[] out = new byte[len / 2];
+
+        for (int i = 0; i < len; i += 2) {
+            int h = Character.digit(s.charAt(i), 16);
+            int l = Character.digit(s.charAt(i + 1), 16);
+            if (h == -1 || l == -1) {
+                throw new IllegalArgumentException(
+                        "contains illegal character for hexBinary: " + s);
+            }
+
+            out[i / 2] = (byte) (h * 16 + l);
+        }
+
+        return out;
+    }
+
+    public static int getMessageLength(byte[] encoding) {
+        if (encoding.length < 2) {
+            // not enough data to extract msg len, just return -1
+            return -1;
+        }
+
+        if (encoding[0] != 0x30) {
+            throw new RuntimeException("Error: bad LDAP encoding message: "
+                                               + "expected ASN.1 SEQUENCE tag (0x30), encountered "
+                                               + encoding[0]);
+        }
+
+        int len;
+        int index = 1;
+        int payloadLen = 0;
+
+        if ((encoding[1] & 0x80) == 0x80) {
+            len = (encoding[1] & 0x0F);
+            index++;
+        } else {
+            len = 1;
+        }
+
+        if (len > 4) {
+            throw new RuntimeException(
+                    "Error: LDAP encoding message payload too large");
+        }
+
+        if (encoding.length < index + len) {
+            // additional data required to extract payload len, return -1
+            return -1;
+        }
+
+        for (byte b : Arrays.copyOfRange(encoding, index, index + len)) {
+            payloadLen = payloadLen << 8 | (b & 0xFF);
+        }
+
+        if (payloadLen <= 0) {
+            throw new RuntimeException(
+                    "Error: invalid LDAP encoding message length or payload too large");
+        }
+
+        return index + len + payloadLen;
+    }
+}
--- a/test/jdk/com/sun/net/httpserver/EchoHandler.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/com/sun/net/httpserver/EchoHandler.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, 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
@@ -21,37 +21,19 @@
  * questions.
  */
 
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.logging.*;
-import java.io.*;
-import java.net.*;
-import java.security.*;
-import javax.net.ssl.*;
-import com.sun.net.httpserver.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
 
 /**
  * Implements a basic static EchoHandler for an HTTP server
  */
 public class EchoHandler implements HttpHandler {
-
-    byte[] read(InputStream is) throws IOException {
-        byte[] buf = new byte[1024];
-        byte[] result = new byte[0];
-
-        while (true) {
-            int n = is.read(buf);
-            if (n > 0) {
-                byte[] b1 = new byte[result.length + n];
-                System.arraycopy(result, 0, b1, 0, result.length);
-                System.arraycopy(buf, 0, b1, result.length, n);
-                result = b1;
-            } else if (n == -1) {
-                return result;
-            }
-        }
-    }
-
     public void handle (HttpExchange t)
         throws IOException
     {
@@ -61,32 +43,20 @@
 
         // return the number of bytes received (no echo)
         String summary = map.getFirst ("XSummary");
-        if (fixedrequest != null && summary == null)  {
-            byte[] in = read(is);
-            t.sendResponseHeaders(200, in.length);
-            OutputStream os = t.getResponseBody();
-            os.write(in);
-            close(t, os);
-            close(t, is);
+        OutputStream os = t.getResponseBody();
+        byte[] in;
+        in = is.readAllBytes();
+        if (summary != null) {
+            in = Integer.toString(in.length).getBytes(StandardCharsets.UTF_8);
+        }
+        if (fixedrequest != null) {
+            t.sendResponseHeaders(200, in.length == 0 ? -1 : in.length);
         } else {
-            OutputStream os = t.getResponseBody();
-            byte[] buf = new byte[64 * 1024];
             t.sendResponseHeaders(200, 0);
-            int n, count=0;;
-
-            while ((n = is.read(buf)) != -1) {
-                if (summary == null) {
-                    os.write(buf, 0, n);
-                }
-                count += n;
-            }
-            if (summary != null) {
-                String s = Integer.toString(count);
-                os.write(s.getBytes());
-            }
-            close(t, os);
-            close(t, is);
         }
+        os.write(in);
+        close(t, os);
+        close(t, is);
     }
 
     protected void close(OutputStream os) throws IOException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/findSpecial/FindSpecialTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -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 8209005 8209078
+ * @library /test/lib
+ * @build m1/* FindSpecialTest
+ * @run testng/othervm FindSpecialTest
+ * @summary Test findSpecial and unreflectSpecial of the declaring class
+ *          of the method and the special caller are not in the same module
+ *          as the lookup class.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+
+import org.testng.annotations.Test;
+
+public class FindSpecialTest {
+    static final String JAVA_LAUNCHER = JDKToolFinder.getJDKTool("java");
+    static final String TEST_CLASSES = System.getProperty("test.classes", ".");
+    static final String TEST_CLASS_PATH = System.getProperty("test.class.path");
+    static final String TEST_MAIN_CLASS = "test.FindSpecial";
+    static final String TEST_MODULE = "m1";
+
+    /*
+     * Run test.FindSpecial in unnamed module
+     */
+    @Test
+    public static void callerInUnnamedModule() throws Throwable {
+        Path m1 = Paths.get(TEST_CLASSES, "modules", TEST_MODULE);
+        if (Files.notExists(m1)) {
+            throw new Error(m1 + " not exist");
+        }
+        String classpath = m1.toString() + File.pathSeparator + TEST_CLASS_PATH;
+        ProcessTools.executeCommand(JAVA_LAUNCHER, "-cp", classpath, TEST_MAIN_CLASS)
+                    .shouldHaveExitValue(0);
+    }
+
+    /*
+     * Run test.FindSpecial in a named module
+     */
+    @Test
+    public static void callerInNamedModule() throws Throwable {
+        Path modules = Paths.get(TEST_CLASSES, "modules");
+        if (Files.notExists(modules)) {
+            throw new Error(modules + " not exist");
+        }
+        ProcessTools.executeCommand(JAVA_LAUNCHER,
+                                    "-cp", TEST_CLASS_PATH,
+                                    "-p", modules.toString(),
+                                    "-m", TEST_MODULE + "/" + TEST_MAIN_CLASS)
+                    .shouldHaveExitValue(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/findSpecial/m1/module-info.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+module m1 {
+    exports test;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/findSpecial/m1/test/FindSpecial.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,101 @@
+/*
+ * 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 test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+/*
+ * java.util.Comparator is in java.base.  MyComparator is a Comparator
+ * subclass and it's in a different module.
+ *
+ * Test findSpecial and unreflectSpecial with Comparator and MyComparator
+ * as the special caller.
+ */
+public class FindSpecial {
+    private static final Lookup LOOKUP = MethodHandles.lookup();
+
+    public static void main(String... args) throws Throwable {
+        findSpecialTest();
+        unreflectSpecialTest();
+        reflectMethodInvoke();
+    }
+
+    static void findSpecialTest() throws Throwable {
+        Method m = Comparator.class.getMethod("reversed");
+        MethodType mt = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
+        // refc and specialCaller are both in java.base
+        MethodHandle mh = LOOKUP.findSpecial(Comparator.class, m.getName(), mt, Comparator.class);
+        // refc in java.base, specialCaller in this module
+        MethodHandle mh1 = LOOKUP.findSpecial(m.getDeclaringClass(), m.getName(), mt,
+                                                MyComparator.class);
+        Comparator<Object> cmp = new MyComparator();
+        // invokespecial to invoke Comparator::reversed.
+        Object o = mh.invoke(cmp);
+        Object o1 = mh1.invoke(cmp);
+    }
+
+    static void unreflectSpecialTest() throws Throwable {
+        Method m = Comparator.class.getMethod("reversed");
+        // refc and specialCaller are both in java.base
+        MethodHandle mh = LOOKUP.unreflectSpecial(m, Comparator.class);
+        // refc in java.base, specialCaller in this module
+        MethodHandle mh1 = LOOKUP.unreflectSpecial(m, MyComparator.class);
+        Comparator<Object> cmp = new MyComparator();
+        // invokespecial to invoke Comparator::reversed.
+        Object o = mh.invoke(cmp);
+        Object o1 = mh1.invoke(cmp);
+    }
+
+    static void reflectMethodInvoke() throws Throwable {
+        Method m = Comparator.class.getMethod("reversed");
+        try {
+            // invokevirtual dispatch
+            Object o = m.invoke(new MyComparator());
+            throw new RuntimeException("should throw an exception");
+        } catch (InvocationTargetException e) {
+            if (!(e.getCause() instanceof Error &&
+                  e.getCause().getMessage().equals("should not reach here"))) {
+                throw e.getCause();
+            }
+        }
+    }
+
+    static class MyComparator implements Comparator<Object> {
+        public int compare(Object o1, Object o2) {
+            return 0;
+        }
+
+        @Override
+        public Comparator<Object> reversed() {
+            throw new Error("should not reach here");
+        }
+    }
+}
+
--- a/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/net/DatagramSocket/UnreferencedDatagramSockets.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, 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
@@ -49,6 +49,7 @@
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountDownLatch;
 
 import com.sun.management.UnixOperatingSystemMXBean;
 
@@ -70,9 +71,10 @@
     static class Server implements Runnable {
 
         DatagramSocket ss;
+        CountDownLatch latch = new CountDownLatch(1);
 
         Server() throws IOException {
-            ss = new DatagramSocket(0);
+            ss = new DatagramSocket(0, getHost());
             System.out.printf("  DatagramServer addr: %s: %d%n",
                     this.getHost(), this.getPort());
             pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverDatagramSocket"));
@@ -80,7 +82,7 @@
         }
 
         InetAddress getHost() throws UnknownHostException {
-            InetAddress localhost = InetAddress.getByName("localhost"); //.getLocalHost();
+            InetAddress localhost = lookupLocalHost();
             return localhost;
         }
 
@@ -96,7 +98,7 @@
                 ss.receive(p);
                 buffer[0] += 1;
                 ss.send(p);         // send back +1
-
+                latch.await();      // wait for the client to receive the packet
                 // do NOT close but 'forget' the datagram socket reference
                 ss = null;
             } catch (Exception ioe) {
@@ -105,11 +107,15 @@
         }
     }
 
+    static InetAddress lookupLocalHost() throws UnknownHostException {
+        return InetAddress.getByName("localhost"); //.getLocalHost();
+    }
+
     public static void main(String args[]) throws Exception {
         IPSupport.throwSkippedExceptionIfNonOperational();
 
         // Create and close a DatagramSocket to warm up the FD count for side effects.
-        try (DatagramSocket s = new DatagramSocket(0)) {
+        try (DatagramSocket s = new DatagramSocket(0, lookupLocalHost())) {
             // no-op; close immediately
             s.getLocalPort();   // no-op
         }
@@ -122,7 +128,7 @@
         Thread thr = new Thread(svr);
         thr.start();
 
-        DatagramSocket client = new DatagramSocket(0);
+        DatagramSocket client = new DatagramSocket(0, lookupLocalHost());
         client.connect(svr.getHost(), svr.getPort());
         pendingSockets.add(new NamedWeak(client, pendingQueue, "clientDatagramSocket"));
         extractRefs(client, "clientDatagramSocket");
@@ -134,6 +140,8 @@
 
         p = new DatagramPacket(msg, msg.length);
         client.receive(p);
+        svr.latch.countDown(); // unblock the server
+
 
         System.out.printf("echo received from: %s%n", p.getSocketAddress());
         if (msg[0] != 2) {
--- a/test/jdk/java/net/httpclient/SmokeTest.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/net/httpclient/SmokeTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -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
@@ -30,7 +30,6 @@
  * @library /test/lib /
  * @build jdk.test.lib.net.SimpleSSLContext ProxyServer
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
- * @compile ../../../com/sun/net/httpserver/EchoHandler.java
  * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
  * @run main/othervm
  *      -Djdk.internal.httpclient.debug=true
@@ -50,7 +49,10 @@
 import java.net.InetAddress;
 import java.net.Proxy;
 import java.net.SocketAddress;
+import java.net.http.HttpHeaders;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.net.InetSocketAddress;
@@ -135,6 +137,22 @@
     static Path smallFile;
     static String fileroot;
 
+    static class HttpEchoHandler implements HttpHandler {
+
+        @Override
+        public void handle(HttpExchange exchange) throws IOException {
+            try (InputStream is = exchange.getRequestBody();
+                 OutputStream os = exchange.getResponseBody()) {
+                byte[] bytes = is.readAllBytes();
+                long responseLength = bytes.length == 0 ? -1 : bytes.length;
+                boolean fixedLength = "yes".equals(exchange.getRequestHeaders()
+                        .getFirst("XFixed"));
+                exchange.sendResponseHeaders(200, fixedLength ? responseLength : 0);
+                os.write(bytes);
+            }
+        }
+    }
+
     static String getFileContent(String path) throws IOException {
         FileInputStream fis = new FileInputStream(path);
         byte[] buf = new byte[2000];
@@ -257,6 +275,8 @@
 
         HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
 
+        checkResponseContentLength(response.headers(), fixedLen);
+
         String body = response.body();
         if (!body.equals("This is foo.txt\r\n")) {
             throw new RuntimeException("Did not get expected body: "
@@ -504,6 +524,8 @@
 
         HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
 
+        checkResponseContentLength(response.headers(), fixedLen);
+
         String body = response.body();
 
         if (!body.equals(requestBody)) {
@@ -529,6 +551,8 @@
 
         HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
 
+        checkResponseContentLength(response.headers(), fixedLen);
+
         if (response.statusCode() != 200) {
             throw new RuntimeException(
                     "Expected 200, got [ " + response.statusCode() + " ]");
@@ -694,7 +718,7 @@
 
         try {
             HttpResponse<String> response = cf.join();
-            throw new RuntimeException("Exepected Completion Exception");
+            throw new RuntimeException("Expected Completion Exception");
         } catch (CompletionException e) {
             //System.out.println(e);
         }
@@ -739,12 +763,12 @@
 
         HttpContext c1 = s1.createContext("/files", h);
         HttpContext c2 = s2.createContext("/files", h);
-        HttpContext c3 = s1.createContext("/echo", new EchoHandler());
+        HttpContext c3 = s1.createContext("/echo", new HttpEchoHandler());
         redirectHandler = new RedirectHandler("/redirect");
         redirectHandlerSecure = new RedirectHandler("/redirect");
         HttpContext c4 = s1.createContext("/redirect", redirectHandler);
         HttpContext c41 = s2.createContext("/redirect", redirectHandlerSecure);
-        HttpContext c5 = s2.createContext("/echo", new EchoHandler());
+        HttpContext c5 = s2.createContext("/echo", new HttpEchoHandler());
         HttpContext c6 = s1.createContext("/keepalive", new KeepAliveHandler());
         redirectErrorHandler = new RedirectErrorHandler("/redirecterror");
         redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror");
@@ -776,6 +800,19 @@
         System.out.println("Proxy port = " + proxyPort);
     }
 
+    static void checkResponseContentLength(HttpHeaders responseHeaders, boolean fixedLen) {
+        Optional<String> transferEncoding = responseHeaders.firstValue("transfer-encoding");
+        Optional<String> contentLength = responseHeaders.firstValue("content-length");
+        if (fixedLen) {
+            assert contentLength.isPresent();
+            assert !transferEncoding.isPresent();
+        } else {
+            assert !contentLength.isPresent();
+            assert transferEncoding.isPresent();
+            assert "chunked".equals(transferEncoding.get());
+        }
+    }
+
     static class RedirectHandler implements HttpHandler {
         private final String root;
         private volatile int count = 0;
@@ -786,9 +823,8 @@
 
         @Override
         public synchronized void handle(HttpExchange t) throws IOException {
-            byte[] buf = new byte[2048];
             try (InputStream is = t.getRequestBody()) {
-                while (is.read(buf) != -1) ;
+                is.readAllBytes();
             }
 
             Headers responseHeaders = t.getResponseHeaders();
@@ -1010,14 +1046,13 @@
                 System.out.println(result);
             }
         }
-        byte[] buf = new byte[2048];
 
         try (InputStream is = t.getRequestBody()) {
-            while (is.read(buf) != -1) ;
+            is.readAllBytes();
         }
         t.sendResponseHeaders(200, result.length());
         OutputStream o = t.getResponseBody();
-        o.write(result.getBytes("US-ASCII"));
+        o.write(result.getBytes(StandardCharsets.UTF_8));
         t.close();
         nparallel.getAndDecrement();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/security/SecureRandom/DefaultAlgo.java	Wed Aug 14 08:23:16 2019 -0400
@@ -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.
+ */
+
+import static java.lang.System.out;
+import java.security.SecureRandom;
+import sun.security.provider.SunEntries;
+
+/**
+ * @test
+ * @bug 8228613
+ * @summary Ensure that the default SecureRandom algo matches
+ *     SunEntries.DEF_SECURE_RANDOM_ALGO when SUN provider is used
+ * @modules java.base/sun.security.provider
+ */
+public class DefaultAlgo {
+
+    public static void main(String[] args) throws Exception {
+        SecureRandom sr = new SecureRandom();
+        String actualAlg = sr.getAlgorithm();
+        out.println("Default SecureRandom algo: " + actualAlg);
+        if (sr.getProvider().getName().equals("SUN")) {
+            // when using Sun provider, compare and check if the algorithm
+            // matches SunEntries.DEF_SECURE_RANDOM_ALGO
+            if (actualAlg.equals(SunEntries.DEF_SECURE_RANDOM_ALGO)) {
+                out.println("Test Passed");
+            } else {
+                throw new RuntimeException("Failed: Expected " +
+                        SunEntries.DEF_SECURE_RANDOM_ALGO);
+            }
+        } else {
+            out.println("Skip test for non-Sun provider: " + sr.getProvider());
+        }
+    }
+}
--- a/test/jdk/java/time/test/java/time/TestOffsetDateTime.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/time/test/java/time/TestOffsetDateTime.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, 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
@@ -60,7 +60,9 @@
 package test.java.time;
 
 import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
 
+import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -73,6 +75,8 @@
 
 /**
  * Test OffsetDateTime.
+ *
+ * @bug 8211990
  */
 @Test
 public class TestOffsetDateTime extends AbstractTest {
@@ -320,4 +324,11 @@
         assertSame(test, base);
     }
 
+    @Test
+    public void test_duration() {
+        OffsetDateTime start = OffsetDateTime.MAX
+                                .withOffsetSameLocal(ZoneOffset.ofHours(-17));
+        OffsetDateTime end = OffsetDateTime.MAX;
+        assertEquals(Duration.between(start, end), Duration.ofHours(1));
+    }
 }
--- a/test/jdk/java/time/test/java/time/TestZonedDateTime.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/java/time/test/java/time/TestZonedDateTime.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, 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
@@ -59,12 +59,19 @@
  */
 package test.java.time;
 
+import static org.testng.Assert.assertEquals;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.time.ZonedDateTime;
+import java.time.ZoneId;
 
 import org.testng.annotations.Test;
 
 /**
  * Test ZonedDateTime.
+ *
+ * @bug 8211990
  */
 @Test
 public class TestZonedDateTime extends AbstractTest {
@@ -74,4 +81,14 @@
         assertImmutable(ZonedDateTime.class);
     }
 
+    @Test
+    public void test_duration() {
+        ZoneId tokyo = ZoneId.of("Asia/Tokyo");
+        ZoneId sanJose = ZoneId.of("America/Los_Angeles");
+
+        ZonedDateTime end = ZonedDateTime.of(LocalDateTime.MAX, sanJose);
+        ZonedDateTime start = end.withZoneSameLocal(tokyo);
+
+        assertEquals(Duration.between(start, end), Duration.ofHours(17));
+    }
 }
--- a/test/jdk/jdk/jfr/event/runtime/TestShutdownEvent.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/jdk/jdk/jfr/event/runtime/TestShutdownEvent.java	Wed Aug 14 08:23:16 2019 -0400
@@ -169,7 +169,10 @@
         @Override
         public void verifyEvents(RecordedEvent event, int exitCode) {
             Events.assertField(event, "reason").equal("VM Error");
-            validateStackTrace(event.getStackTrace());
+            // for now avoid validating the stack trace, in case of compiled code
+            // the vframeStream based solution will not work in this special VMCrash case
+            // see 8219082 for details (running the crashed VM with -Xint would solve the issue too)
+            //validateStackTrace(event.getStackTrace());
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/net/www/B8185898.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,280 @@
+/*
+ * 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 8185898
+ * @modules java.base/sun.net.www
+ * @library /test/lib
+ * @run main/othervm B8185898
+ * @summary setRequestProperty(key, null) results in HTTP header without colon in request
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.net.URIBuilder;
+import sun.net.www.MessageHeader;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/*
+ * Test checks that MessageHeader with key != null and value == null is set correctly
+ * and printed according to HTTP standard in the format <key>: <value>
+ * */
+public class B8185898 {
+
+    static HttpServer server;
+    static final String RESPONSE_BODY = "Test response body";
+    static final String H1 = "X-header1";
+    static final String H2 = "X-header2";
+    static final String VALUE = "This test value should appear";
+    static int port;
+    static URL url;
+    static volatile Map<String, List<String>> headers;
+
+    static class Handler implements HttpHandler {
+
+        public void handle(HttpExchange t) throws IOException {
+            InputStream is = t.getRequestBody();
+            InetSocketAddress rem = t.getRemoteAddress();
+            headers = t.getRequestHeaders();    // Get request headers on the server side
+            is.readAllBytes();
+            is.close();
+
+            OutputStream os = t.getResponseBody();
+            t.sendResponseHeaders(200, RESPONSE_BODY.length());
+            os.write(RESPONSE_BODY.getBytes(UTF_8));
+            t.close();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        ExecutorService exec = Executors.newCachedThreadPool();
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+
+        try {
+            InetSocketAddress addr = new InetSocketAddress(loopback, 0);
+            server = HttpServer.create(addr, 100);
+            HttpHandler handler = new Handler();
+            HttpContext context = server.createContext("/", handler);
+            server.setExecutor(exec);
+            server.start();
+
+            port = server.getAddress().getPort();
+            System.out.println("Server on port: " + port);
+            url = URIBuilder.newBuilder()
+                    .scheme("http")
+                    .loopback()
+                    .port(port)
+                    .path("/foo")
+                    .toURLUnchecked();
+            System.out.println("URL: " + url);
+            testMessageHeader();
+            testMessageHeaderMethods();
+            testURLConnectionMethods();
+        } finally {
+            server.stop(0);
+            System.out.println("After server shutdown");
+            exec.shutdown();
+        }
+    }
+
+    // Test message header with malformed message header and fake request line
+    static void testMessageHeader() {
+        final String badHeader = "This is not a request line for HTTP/1.1";
+        final String fakeRequestLine = "This /is/a/fake/status/line HTTP/2.0";
+        final String expectedHeaders = fakeRequestLine + "\r\n"
+                + H1 + ": " + VALUE + "\r\n"
+                + H2 + ": " + VALUE + "\r\n"
+                + badHeader + ":\r\n\r\n";
+
+        MessageHeader header = new MessageHeader();
+        header.add(H1, VALUE);
+        header.add(H2, VALUE);
+        header.add(badHeader, null);
+        header.prepend(fakeRequestLine, null);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        header.print(new PrintStream(out));
+
+        if (!out.toString().equals(expectedHeaders)) {
+            throw new AssertionError("FAILED: expected: "
+                    + expectedHeaders + "\nReceived: " + out.toString());
+        } else {
+            System.out.println("PASSED: ::print returned correct "
+                    + "status line and headers:\n" + out.toString());
+        }
+    }
+
+    // Test MessageHeader::print, ::toString, implicitly testing that
+    // MessageHeader::mergeHeader formats headers correctly for responses
+    static void testMessageHeaderMethods() throws IOException {
+        // {{inputString1, expectedToString1, expectedPrint1}, {...}}
+        String[][] strings = {
+                {"HTTP/1.1 200 OK\r\n"
+                        + "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+                        + "Connection: keep-alive\r\n"
+                        + "Host: 127.0.0.1:12345\r\n"
+                        + "User-agent: Java/12\r\n\r\nfoooo",
+                "pairs: {null: HTTP/1.1 200 OK}"
+                        + "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}"
+                        + "{Connection: keep-alive}"
+                        + "{Host: 127.0.0.1:12345}"
+                        + "{User-agent: Java/12}",
+                "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+                        + "Connection: keep-alive\r\n"
+                        + "Host: 127.0.0.1:12345\r\n"
+                        + "User-agent: Java/12\r\n\r\n"},
+                {"HTTP/1.1 200 OK\r\n"
+                        + "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+                        + "Connection: keep-alive\r\n"
+                        + "Host: 127.0.0.1:12345\r\n"
+                        + "User-agent: Java/12\r\n"
+                        + "X-Header:\r\n\r\n",
+                "pairs: {null: HTTP/1.1 200 OK}"
+                        + "{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}"
+                        + "{Connection: keep-alive}"
+                        + "{Host: 127.0.0.1:12345}"
+                        + "{User-agent: Java/12}"
+                        + "{X-Header: }",
+                "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n"
+                        + "Connection: keep-alive\r\n"
+                        + "Host: 127.0.0.1:12345\r\n"
+                        + "User-agent: Java/12\r\n"
+                        + "X-Header: \r\n\r\n"},
+        };
+
+        System.out.println("Test custom message headers");
+        for (String[] s : strings) {
+            // Test MessageHeader::toString
+            MessageHeader header = new MessageHeader(
+                    new ByteArrayInputStream(s[0].getBytes(ISO_8859_1)));
+            if (!header.toString().endsWith(s[1])) {
+                throw new AssertionError("FAILED: expected: "
+                        + s[1] + "\nReceived: " + header);
+            } else {
+                System.out.println("PASSED: ::toString returned correct "
+                        + "status line and headers:\n" + header);
+            }
+
+            // Test MessageHeader::print
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            header.print(new PrintStream(out));
+            if (!out.toString().equals(s[2])) {
+                throw new AssertionError("FAILED: expected: "
+                        + s[2] + "\nReceived: " + out.toString());
+            } else {
+                System.out.println("PASSED: ::print returned correct "
+                        + "status line and headers:\n" + out.toString());
+            }
+        }
+    }
+
+    // Test methods URLConnection::getRequestProperties,
+    // ::getHeaderField, ::getHeaderFieldKey
+    static void testURLConnectionMethods() throws IOException {
+        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
+        urlConn.setRequestProperty(H1, "");
+        urlConn.setRequestProperty(H1, VALUE);
+        urlConn.setRequestProperty(H2, null);    // Expected to contain ':' between key and value
+        Map<String, List<String>> props = urlConn.getRequestProperties();
+        Map<String, List<String>> expectedMap = Map.of(
+                H1, List.of(VALUE),
+                H2, Arrays.asList((String) null));
+
+        // Test request properties
+        System.out.println("Client request properties");
+        StringBuilder sb = new StringBuilder();
+        props.forEach((k, v) -> sb.append(k + ": "
+                + v.stream().collect(Collectors.joining()) + "\n"));
+        System.out.println(sb);
+
+        if (!props.equals(expectedMap)) {
+            throw new AssertionError("Unexpected properties returned: "
+                    + props);
+        } else {
+            System.out.println("Properties returned as expected");
+        }
+
+        // Test header fields
+        String headerField = urlConn.getHeaderField(0);
+        if (!headerField.contains("200 OK")) {
+            throw new AssertionError("Expected headerField[0]: status line. "
+                    + "Received: " + headerField);
+        } else {
+            System.out.println("PASSED: headerField[0] contains status line: "
+                    + headerField);
+        }
+
+        String headerFieldKey = urlConn.getHeaderFieldKey(0);
+        if (headerFieldKey != null) {
+            throw new AssertionError("Expected headerFieldKey[0]: null. "
+                    + "Received: " + headerFieldKey);
+        } else {
+            System.out.println("PASSED: headerFieldKey[0] is null");
+        }
+
+        // Check that test request headers are included with correct format
+        try (
+                BufferedReader in = new BufferedReader(
+                        new InputStreamReader(urlConn.getInputStream()))
+        ) {
+            if (!headers.keySet().contains(H1)) {
+                throw new AssertionError("Expected key not found: "
+                        + H1 + ": " + VALUE);
+            } else if (!headers.get(H1).equals(List.of(VALUE))) {
+                throw new AssertionError("Unexpected key-value pair: "
+                        + H1 + ": " + headers.get(H1));
+            } else {
+                System.out.println("PASSED: " + H1 + " included in request headers");
+            }
+
+            if (!headers.keySet().contains(H2)) {
+                throw new AssertionError("Expected key not found: "
+                        + H2 + ": ");
+                // Check that empty list is returned
+            } else if (!headers.get(H2).equals(List.of(""))) {
+                throw new AssertionError("Unexpected key-value pair: "
+                        + H2 + ": " + headers.get(H2));
+            } else {
+                System.out.println("PASSED: " + H2 + " included in request headers");
+            }
+
+            String inputLine;
+            while ((inputLine = in.readLine()) != null) {
+                System.out.println(inputLine);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/RestrictNamedGroup.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,105 @@
+/*
+ * 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 8226374
+ * @library /javax/net/ssl/templates
+ * @summary Restrict signature algorithms and named groups
+ * @run main/othervm RestrictNamedGroup x25519
+ * @run main/othervm RestrictNamedGroup x448
+ * @run main/othervm RestrictNamedGroup secp256r1
+ * @run main/othervm RestrictNamedGroup secp384r1
+ * @run main/othervm RestrictNamedGroup secp521r1
+ * @run main/othervm RestrictNamedGroup ffdhe2048
+ * @run main/othervm RestrictNamedGroup ffdhe3072
+ * @run main/othervm RestrictNamedGroup ffdhe4096
+ * @run main/othervm RestrictNamedGroup ffdhe6144
+ * @run main/othervm RestrictNamedGroup ffdhe8192
+ */
+
+import java.security.Security;
+import java.util.Arrays;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLException;
+
+public class RestrictNamedGroup extends SSLSocketTemplate {
+
+    private static volatile int index;
+    private static final String[][][] protocols = {
+        {{"TLSv1.3"}, {"TLSv1.3"}},
+        {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+        {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+        {{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
+        {{"TLSv1.2"}, {"TLSv1.2"}}
+    };
+
+    // Servers are configured before clients, increment test case after.
+    @Override
+    protected void configureClientSocket(SSLSocket socket) {
+        String[] ps = protocols[index][0];
+
+        System.out.print("Setting client protocol(s): ");
+        Arrays.stream(ps).forEachOrdered(System.out::print);
+        System.out.println();
+
+        socket.setEnabledProtocols(ps);
+        socket.setEnabledCipherSuites(new String[] {
+            "TLS_AES_128_GCM_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+    }
+
+    @Override
+    protected void configureServerSocket(SSLServerSocket serverSocket) {
+        String[] ps = protocols[index][1];
+
+        System.out.print("Setting server protocol(s): ");
+        Arrays.stream(ps).forEachOrdered(System.out::print);
+        System.out.println();
+
+        serverSocket.setEnabledProtocols(ps);
+        serverSocket.setEnabledCipherSuites(new String[] {
+            "TLS_AES_128_GCM_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+    }
+
+    /*
+     * Run the test case.
+     */
+    public static void main(String[] args) throws Exception {
+        Security.setProperty("jdk.tls.disabledAlgorithms", args[0]);
+        System.setProperty("jdk.tls.namedGroups", args[0]);
+
+        for (index = 0; index < protocols.length; index++) {
+            try {
+                (new RestrictNamedGroup()).run();
+            } catch (SSLException | IllegalStateException ssle) {
+                // The named group should be restricted.
+                continue;
+            }
+
+            throw new Exception("The test case should be disabled");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ssl/CipherSuite/RestrictSignatureScheme.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,232 @@
+/*
+ * 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 8226374
+ * @library /javax/net/ssl/templates
+ * @summary Restrict signature algorithms and named groups
+ * @run main/othervm RestrictSignatureScheme
+ */
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
+import java.util.Base64;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.SSLException;
+
+public class RestrictSignatureScheme extends SSLSocketTemplate {
+
+    private static volatile int index;
+    private static final String[][][] protocols = {
+        {{"TLSv1.3"}, {"TLSv1.3"}},
+        {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+        {{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
+        {{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
+        {{"TLSv1.2"}, {"TLSv1.2"}}
+    };
+
+    private final SSLContext context;
+    RestrictSignatureScheme() throws Exception {
+        this.context = createSSLContext();
+    }
+
+    @Override
+    protected SSLContext createClientSSLContext() throws Exception {
+        return context;
+    }
+
+    @Override
+    protected SSLContext createServerSSLContext() throws Exception {
+        return context;
+    }
+
+    // Servers are configured before clients, increment test case after.
+    @Override
+    protected void configureClientSocket(SSLSocket socket) {
+        String[] ps = protocols[index][0];
+
+        System.out.print("Setting client protocol(s): ");
+        Arrays.stream(ps).forEachOrdered(System.out::print);
+        System.out.println();
+
+        socket.setEnabledProtocols(ps);
+        socket.setEnabledCipherSuites(new String[] {
+            "TLS_AES_128_GCM_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+    }
+
+    @Override
+    protected void configureServerSocket(SSLServerSocket serverSocket) {
+        String[] ps = protocols[index][1];
+
+        System.out.print("Setting server protocol(s): ");
+        Arrays.stream(ps).forEachOrdered(System.out::print);
+        System.out.println();
+
+        serverSocket.setEnabledProtocols(ps);
+        serverSocket.setEnabledCipherSuites(new String[] {
+            "TLS_AES_128_GCM_SHA256",
+            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
+    }
+
+    /*
+     * Run the test case.
+     */
+    public static void main(String[] args) throws Exception {
+        Security.setProperty("jdk.tls.disabledAlgorithms", "RSASSA-PSS");
+
+        for (index = 0; index < protocols.length; index++) {
+            try {
+                (new RestrictSignatureScheme()).run();
+            } catch (SSLException | IllegalStateException ssle) {
+                // The named group should be restricted.
+                continue;
+            }
+
+            throw new Exception("The test case should be disabled");
+        }
+    }
+
+
+    private static final String trustedCertStr =
+        /**
+        * Signature Algorithm: rsassaPss
+        * Issuer: CN = localhost
+        * Validity Not Before: Jun 6 07:11:00 2018 GMT
+        * Not After : Jun 1 07:11:00 2038 GMT
+        * Subject: CN = localhost
+        * Public Key Algorithm: rsassaPss
+        */
+       "-----BEGIN CERTIFICATE-----\n"
+       + "MIIDZjCCAh2gAwIBAgIUHxwPs3eAgJ057nJwiLgWZWeNqdgwPgYJKoZIhvcNAQEK\n"
+       + "MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC\n"
+       + "AgDeMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODA2MDYwNzExMDBaFw0zODA2\n"
+       + "MDEwNzExMDBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n"
+       + "A4IBDwAwggEKAoIBAQCl8r4Qrg27BYUO/1Va2Ix8QPGzN/lvzmKvP5Ff26ovNW4v\n"
+       + "RUx68HzAhhiWtcl+PwLSbJqJreEkTlle7PnRAypby3fO7ZAK0Y3YiHquaBg7d+7Y\n"
+       + "FhhHwv8gG0lZcyA0BkXFJHqdq76qar0xHC6DVezXm0K3mcceymGtFR9BzWmAj+7D\n"
+       + "YsSwvtTQ7WNoQmf0cdDMSM71IwaTwIwvT2wzX1vv5hcdDyXdr64WFqWSA9sNJ2K6\n"
+       + "arxaaU1klwKSgDokF6njafWQ4UxdR67d5W1MYoiioDs2Yy3utsMpO2OUzZVBZNdT\n"
+       + "gkr1jsJhIurpz/5K51lwJIRQBezEFSb+60AFVoMJAgMBAAGjUDBOMB0GA1UdDgQW\n"
+       + "BBQfFit5ilWJmZgCX4QY0HsaI9iIDDAfBgNVHSMEGDAWgBQfFit5ilWJmZgCX4QY\n"
+       + "0HsaI9iIDDAMBgNVHRMEBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZIAWUD\n"
+       + "BAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3gOCAQEAa4yUQ3gh\n"
+       + "d1YWPdEa1sv2hdkhtenw6m5yxbmaQl2+nIKSpk4RfpXC7K1EYwBF8TdfFbD8hGGh\n"
+       + "5n81BT0/dn1R9SRGCv7KTxx4lfQt31frlsw/tVciwyXQtcUZ6DqfnLP0/aRVLNgx\n"
+       + "zaP542JUHFYLTC3EGz2zUgv70ZUTlIsPG3/p8YO1iXdnYGQyzOuQPUBpI7nS7UtR\n"
+       + "Ug8VE9ACpBxxI3qChMahFZGHlXCCSjSmxpQa6UO4SQl8q5tPNnqdzWwvAW8qkCy4\n"
+       + "6barRQ4sMcGayhHh/uSTx7bcl0FMJpcI1ygbw7/Pc03zKtw0gMTBMns7q4yXjb/u\n"
+       + "ef47nW0t+LRAAg==\n"
+       + "-----END CERTIFICATE-----\n";
+
+    private static final String keyCertStr = trustedCertStr;
+
+    private static final String privateKey =
+        "MIIEuwIBADALBgkqhkiG9w0BAQoEggSnMIIEowIBAAKCAQEApfK+EK4NuwWFDv9V\n"
+        + "WtiMfEDxszf5b85irz+RX9uqLzVuL0VMevB8wIYYlrXJfj8C0myaia3hJE5ZXuz5\n"
+        + "0QMqW8t3zu2QCtGN2Ih6rmgYO3fu2BYYR8L/IBtJWXMgNAZFxSR6nau+qmq9MRwu\n"
+        + "g1Xs15tCt5nHHsphrRUfQc1pgI/uw2LEsL7U0O1jaEJn9HHQzEjO9SMGk8CML09s\n"
+        + "M19b7+YXHQ8l3a+uFhalkgPbDSdiumq8WmlNZJcCkoA6JBep42n1kOFMXUeu3eVt\n"
+        + "TGKIoqA7NmMt7rbDKTtjlM2VQWTXU4JK9Y7CYSLq6c/+SudZcCSEUAXsxBUm/utA\n"
+        + "BVaDCQIDAQABAoIBAAc4vRS0vlw5LUUtz2UYr2Ro3xvRf8Vh0eGWfpkRUiKjzJu6\n"
+        + "BE4FUSh/rWpBlvcrfs/xcfgz3OxbjIAZB/YUkS9Vd21F4VLXM7kMl2onlYZg/b/h\n"
+        + "lkTpM3kONu7xl6Er9LVTlRJveuinpHwSoeONRbVMSGb9BjFM1VtW4/lVGxZBG05D\n"
+        + "y9i/o4vCZqULn9cAumOwicKuCyTcS58XcMJ+puSPfRA71PYLxqFkASAoJsUwCXpo\n"
+        + "gs39lLsIFgrfO8mBO1ux/SE+QaRc+9XqFSHHKD1XqF/9zSYBgWjE910EcpdYEdZx\n"
+        + "GEkwea7Fn4brO5OpIrHY/45naqbUOBzv6gufMAECgYEAz7PHCdcrQvmOb8EiNbQH\n"
+        + "uvSimwObWJFeN1ykp6mfRbSnkXw7p8+M4Tc8HFi8QLpoq63Ev2AwoaQCQvHbFC2Y\n"
+        + "1Cz0EkC0aOp+tZP7U2AUBdkcDesZAJQTad0zV6KesyIUXdxZXDG8JJ1XSNWfTJV4\n"
+        + "QD+BjLZ0jiAyCIfVYvWQqYkCgYEAzIln1nKTixLMPr5CldSmR7ZarEtPJU+hHwVg\n"
+        + "dV/Lc6d2Yy9JgunOXRo4BXB1TEo8JFbK3HBQH6tS8li4qDr7WK5wyYfh8qb4WZyu\n"
+        + "lc562f2WVYntcN8/Ojb+Vyrt7lk9sq/8KoVHxEAWd6mqL9VTPYuAu1Vw9fTGIZfB\n"
+        + "lDeELYECgYAvdzU4UXzofGGJtohb332YwwlaBZP9xJLUcg6K5l+orWVSASMc8XiP\n"
+        + "i3DoRXsYC8GZ4kdBOPlEJ1gA9oaLcPQpIPDSLwlLpLM6Scw4vI822uvnXl/DWxOo\n"
+        + "sM1n7Jj59QLUhGPDhvYpI+/rjC4wcUQe4qR3hMbUKBVnD6u7RsU9iQKBgQCQ17VK\n"
+        + "7bSCRfuRaxaoGADww7gOTv5rQ6qr1xjpxb7D1hFGR9Rc+smCsPB/GZZXQjK44SWj\n"
+        + "WX3ED4Ubzaxmpe4cbNu+O5XMSmWQwB36RFBHUwdE5/nXdqDFzu/qNqJrqZLBmVKP\n"
+        + "ofaiiWffsaytVvotmT6+atElvAMbAua42V+nAQKBgHtIn3mYMHLriYGhQzpkFEA2\n"
+        + "8YcAMlKppueOMAKVy8nLu2r3MidmLAhMiKJQKG45I3Yg0/t/25tXLiOPJlwrOebh\n"
+        + "xQqUBI/JUOIpGAEnr48jhOXnCS+i+z294G5U/RgjXrlR4bCPvrtCmwzWwe0h79w2\n"
+        + "Q2hO5ZTW6UD9CVA85whf";
+
+    private static SSLContext createSSLContext() throws Exception {
+        // Generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // Create a key store
+        KeyStore ts = KeyStore.getInstance("PKCS12");
+        KeyStore ks = KeyStore.getInstance("PKCS12");
+        ts.load(null, null);
+        ks.load(null, null);
+        char passphrase[] = "passphrase".toCharArray();
+
+        // Import the trusted cert
+        ts.setCertificateEntry("trusted-cert-RSASSA-PSS",
+                cf.generateCertificate(new ByteArrayInputStream(
+                        trustedCertStr.getBytes())));
+
+        boolean hasKeyMaterials = keyCertStr != null && privateKey != null;
+        if (hasKeyMaterials) {
+
+            // Generate the private key.
+            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                    Base64.getMimeDecoder().decode(privateKey));
+            KeyFactory kf = KeyFactory.getInstance("RSASSA-PSS");
+            PrivateKey priKey = kf.generatePrivate(priKeySpec);
+
+            // Generate certificate chain
+            Certificate keyCert = cf.generateCertificate(
+                    new ByteArrayInputStream(keyCertStr.getBytes()));
+            Certificate[] chain = new Certificate[]{keyCert};
+
+            // Import the key entry.
+            ks.setKeyEntry("cert-RSASSA-PSS", priKey, passphrase, chain);
+        }
+
+        // Create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+        tmf.init(ts);
+
+        SSLContext context = SSLContext.getInstance("TLS");
+        if (hasKeyMaterials) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+            kmf.init(ks, passphrase);
+            context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        } else {
+            context.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return context;
+    }
+}
--- a/test/langtools/tools/javac/T4994049/T4994049.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/T4994049/T4994049.java	Wed Aug 14 08:23:16 2019 -0400
@@ -10,5 +10,8 @@
     FOO {
     }
 
-    BAR;
+    BAR1,
+    BAR2(),
+    BAR3 {},
+    BAR4() {};
 }
--- a/test/langtools/tools/javac/T4994049/T4994049.out	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/T4994049/T4994049.out	Wed Aug 14 08:23:16 2019 -0400
@@ -1,2 +1,2 @@
-T4994049.java:13:5: compiler.err.expected3: ',', '}', ';'
+T4994049.java:11:6: compiler.err.expected3: ',', '}', ';'
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/BrokenConstantValue.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,9 @@
+/* @test /nodynamiccopyright/
+ * @compile HasBrokenConstantValue.jcod
+ * @compile/fail/ref=BrokenConstantValue.out -XDrawDiagnostics BrokenConstantValue.java
+ */
+public class BrokenConstantValue {
+     void t() {
+         String s = HasBrokenConstantValue.VALUE;
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/BrokenConstantValue.out	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,2 @@
+BrokenConstantValue.java:7:21: compiler.err.cant.access: HasBrokenConstantValue, (compiler.misc.bad.class.file.header: HasBrokenConstantValue.class, (compiler.misc.bad.constant.value.type: java.lang.Object))
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/HasBrokenConstantValue.jcod	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+// ConstantValue attribute on a field that has wrong type (j.l.Object):
+
+class HasBrokenConstantValue {
+  0xCAFEBABE;
+  0; // minor version
+  55; // version
+  [] { // Constant Pool
+    ; // first element is empty
+    Method #3 #14; // #1
+    class #15; // #2
+    class #16; // #3
+    Utf8 "VALUE"; // #4
+    Utf8 "Ljava/lang/Object;"; // #5
+    Utf8 "ConstantValue"; // #6
+    String #17; // #7
+    Utf8 "<init>"; // #8
+    Utf8 "()V"; // #9
+    Utf8 "Code"; // #10
+    Utf8 "LineNumberTable"; // #11
+    Utf8 "SourceFile"; // #12
+    Utf8 "HasBrokenConstantValue.java"; // #13
+    NameAndType #8 #9; // #14
+    Utf8 "HasBrokenConstantValue"; // #15
+    Utf8 "java/lang/Object"; // #16
+    Utf8 ""; // #17
+  } // Constant Pool
+
+  0x0021; // access
+  #2;// this_cpx
+  #3;// super_cpx
+
+  [] { // Interfaces
+  } // Interfaces
+
+  [] { // fields
+    { // Member
+      0x0019; // access
+      #4; // name_cpx
+      #5; // sig_cpx
+      [] { // Attributes
+        Attr(#6) { // ConstantValue
+          #7;
+        } // end ConstantValue
+      } // Attributes
+    } // Member
+  } // fields
+
+  [] { // methods
+    { // Member
+      0x0001; // access
+      #8; // name_cpx
+      #9; // sig_cpx
+      [] { // Attributes
+        Attr(#10) { // Code
+          1; // max_stack
+          1; // max_locals
+          Bytes[]{
+            0x2AB70001B1;
+          }
+          [] { // Traps
+          } // end Traps
+          [] { // Attributes
+            Attr(#11) { // LineNumberTable
+              [] { // LineNumberTable
+                0  1;
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [] { // Attributes
+    Attr(#12) { // SourceFile
+      #13;
+    } // end SourceFile
+  } // Attributes
+} // end class HasBrokenConstantValue
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/BadConstantValueType/BadConstantValueType.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,36 @@
+/*
+ * 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.misc.bad.constant.value.type
+// key: compiler.misc.bad.class.file.header
+// key: compiler.err.cant.access
+// options: -processor CreateBadClassFile
+// run: exec --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
+
+/* The annotation processor will create an invalid classfile with a static
+ * final field of type java.lang.Object having ConstantValue attribute with
+ * a String value
+ */
+class BadConstantValueType {
+    private static final String C = Test.test;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/BadConstantValueType/processors/CreateBadClassFile.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,92 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+
+/* Create an invalid classfile with a static final field of type object with
+ * ConstantValue of type String.
+ */
+@SupportedAnnotationTypes("*")
+public class CreateBadClassFile extends AbstractProcessor {
+    public boolean process(Set<? extends TypeElement> elems, RoundEnvironment renv) {
+        if (++round == 1) {
+            ConstantPool cp = new ConstantPool(new CPInfo[] {
+                new CONSTANT_Utf8_info(""),                     //0
+                new CONSTANT_Utf8_info("Test"),                 //1
+                new CONSTANT_Class_info(null, 1),               //2
+                new CONSTANT_Utf8_info("java/lang/Object"),     //3
+                new CONSTANT_Class_info(null, 3),               //4
+                new CONSTANT_Utf8_info("test"),                 //5
+                new CONSTANT_Utf8_info("Ljava/lang/Object;"),   //6
+                new CONSTANT_Utf8_info("ConstantValue"),        //7
+            });
+            ClassFile cf = new ClassFile(0xCAFEBABE,
+                          0,
+                          51,
+                          cp,
+                          new AccessFlags(AccessFlags.ACC_ABSTRACT |
+                                          AccessFlags.ACC_INTERFACE |
+                                          AccessFlags.ACC_PUBLIC),
+                          2,
+                          4,
+                          new int[0],
+                          new Field[] {
+                              new Field(new AccessFlags(AccessFlags.ACC_PUBLIC |
+                                                        AccessFlags.ACC_STATIC |
+                                                        AccessFlags.ACC_FINAL),
+                                        5,
+                                      new Descriptor(6),
+                                      new Attributes(cp, new Attribute[] {
+                                          new ConstantValue_attribute(7, 6)
+                                      }))
+                          },
+                          new Method[0],
+                          new Attributes(cp, new Attribute[0]));
+            try {
+                JavaFileObject clazz = processingEnv.getFiler().createClassFile("Test");
+                try (OutputStream out = clazz.openOutputStream()) {
+                    new ClassWriter().write(cf, out);
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        return false;
+    }
+
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    int round = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/EnumConstantExpected.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,30 @@
+/*
+ * 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.enum.constant.expected
+
+enum EnumConstantExpected {
+    A,
+    void test() {}
+    ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/EnumConstantNotExpected.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,29 @@
+/*
+ * 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.enum.constant.not.expected
+
+enum EnumConstantNotExpected {
+    ;
+    A;
+}
--- a/test/langtools/tools/javac/enum/EnumMembersOrder.out	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/enum/EnumMembersOrder.out	Wed Aug 14 08:23:16 2019 -0400
@@ -1,7 +1,4 @@
 EnumMembersOrder.java:11:16: compiler.err.expected: ')'
-EnumMembersOrder.java:11:17: compiler.err.expected3: ',', '}', ';'
-EnumMembersOrder.java:11:18: compiler.err.expected: '}'
-EnumMembersOrder.java:11:31: compiler.err.expected3: class, interface, enum
-EnumMembersOrder.java:17:13: compiler.err.expected3: class, interface, enum
-EnumMembersOrder.java:19:1: compiler.err.expected3: class, interface, enum
-6 errors
+EnumMembersOrder.java:11:18: compiler.err.expected3: ',', '}', ';'
+EnumMembersOrder.java:11:20: compiler.err.enum.constant.expected
+3 errors
--- a/test/langtools/tools/javac/parser/JavacParserTest.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/parser/JavacParserTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1291,6 +1291,179 @@
         assertTrue("testAnalyzeParensWithComma2", found[0]);
     }
 
+    @Test
+    void testBrokenEnum1() throws IOException {
+        assert tool != null;
+
+        String code = "package test; class Test { enum E { A, B, C. D, E, F; } }";
+        StringWriter output = new StringWriter();
+        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+        List<String> actual = List.of(output.toString().split("\r?\n"));
+        List<String> expected = List.of("Test.java:1:44: compiler.err.expected3: ',', '}', ';'");
+
+        assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+                     actual,
+                     expected);
+
+        String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+        String expectedAST = "package test;\n" +
+                             "\n" +
+                             "class Test {\n" +
+                             "    \n" +
+                             "    enum E {\n" +
+                             "        /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ B /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ C /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ D /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ E /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ F /* = new E() */ /*enum*/ ;\n" +
+                             "        (ERROR) <error>;\n" +
+                             "    }\n" +
+                             "}";
+        assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+                     actualAST,
+                     expectedAST);
+    }
+
+    @Test
+    void testBrokenEnum2() throws IOException {
+        assert tool != null;
+
+        String code = "package test; class Test { enum E { A, B, C void t() {} } }";
+        StringWriter output = new StringWriter();
+        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+        List<String> actual = List.of(output.toString().split("\r?\n"));
+        List<String> expected = List.of("Test.java:1:44: compiler.err.expected3: ',', '}', ';'");
+
+        assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+                     actual,
+                     expected);
+
+        String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+        String expectedAST = "package test;\n" +
+                             "\n" +
+                             "class Test {\n" +
+                             "    \n" +
+                             "    enum E {\n" +
+                             "        /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ B /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ C /* = new E() */ /*enum*/ ;\n" +
+                             "        \n" +
+                             "        void t() {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}";
+        assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+                     actualAST,
+                     expectedAST);
+    }
+
+    @Test
+    void testBrokenEnum3() throws IOException {
+        assert tool != null;
+
+        String code = "package test; class Test { enum E { , void t() {} } }";
+        StringWriter output = new StringWriter();
+        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+        List<String> actual = List.of(output.toString().split("\r?\n"));
+        List<String> expected = List.of("Test.java:1:38: compiler.err.expected2: '}', ';'");
+
+        assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+                     actual,
+                     expected);
+
+        String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+        String expectedAST = "package test;\n" +
+                             "\n" +
+                             "class Test {\n" +
+                             "    \n" +
+                             "    enum E {\n" +
+                             ";\n" +
+                             "        \n" +
+                             "        void t() {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}";
+        assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+                     actualAST,
+                     expectedAST);
+    }
+
+    @Test
+    void testBrokenEnum4() throws IOException {
+        assert tool != null;
+
+        String code = "package test; class Test { enum E { A, B, C, void t() {} } }";
+        StringWriter output = new StringWriter();
+        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+        List<String> actual = List.of(output.toString().split("\r?\n"));
+        List<String> expected = List.of("Test.java:1:46: compiler.err.enum.constant.expected");
+
+        assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+                     actual,
+                     expected);
+
+        String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+        String expectedAST = "package test;\n" +
+                             "\n" +
+                             "class Test {\n" +
+                             "    \n" +
+                             "    enum E {\n" +
+                             "        /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ B /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ C /* = new E() */ /*enum*/ ;\n" +
+                             "        \n" +
+                             "        void t() {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}";
+        assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+                     actualAST,
+                     expectedAST);
+    }
+
+    @Test
+    void testBrokenEnum5() throws IOException {
+        assert tool != null;
+
+        String code = "package test; class Test { enum E { A; void t() {} B; } }";
+        StringWriter output = new StringWriter();
+        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(output, fm, null, List.of("-XDrawDiagnostics"),
+                null, Arrays.asList(new MyFileObject(code)));
+        CompilationUnitTree cut = ct.parse().iterator().next();
+        List<String> actual = List.of(output.toString().split("\r?\n"));
+        List<String> expected = List.of("Test.java:1:52: compiler.err.enum.constant.not.expected");
+
+        assertEquals("The expected and actual errors do not match, actual errors: " + actual,
+                     actual,
+                     expected);
+
+        String actualAST = cut.toString().replaceAll("\r*\n", "\n");
+        String expectedAST = "package test;\n" +
+                             "\n" +
+                             "class Test {\n" +
+                             "    \n" +
+                             "    enum E {\n" +
+                             "        /*public static final*/ A /* = new E() */ /*enum*/ ,\n" +
+                             "        /*public static final*/ B /* = new E() */ /*enum*/ ;\n" +
+                             "        \n" +
+                             "        void t() {\n" +
+                             "        }\n" +
+                             "    }\n" +
+                             "}";
+        assertEquals("The expected and actual AST do not match, actual AST: " + actualAST,
+                     actualAST,
+                     expectedAST);
+    }
+
     void run(String[] args) throws Exception {
         int passed = 0, failed = 0;
         final Pattern p = (args != null && args.length > 0)
--- a/test/langtools/tools/javac/tree/AbstractTreeScannerTest.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/tree/AbstractTreeScannerTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,13 +26,17 @@
 import java.util.*;
 import javax.tools.*;
 
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
 import com.sun.source.tree.CompilationUnitTree;
 import com.sun.source.tree.Tree;
 import com.sun.source.util.JavacTask;
 import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.tree.DCTree;
+import com.sun.tools.javac.tree.DCTree.DCDocComment;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
 
 public abstract class AbstractTreeScannerTest {
 
@@ -141,7 +145,7 @@
             error("File " + file + " ignored");
     }
 
-    abstract int test(JCCompilationUnit t);
+    abstract int test(Pair<JavacTask, JCCompilationUnit> taskAndTree);
 
     // See CR:  6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout
     StringWriter sw = new StringWriter();
@@ -157,7 +161,7 @@
      * @throws IOException if any IO errors occur
      * @throws TreePosTest.ParseException if any errors occur while parsing the file
      */
-    JCCompilationUnit read(File file) throws IOException, ParseException {
+    Pair<JavacTask, JCCompilationUnit> read(File file) throws IOException, ParseException {
         JavacTool tool = JavacTool.create();
         r.errors = 0;
         Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
@@ -172,7 +176,7 @@
         JCCompilationUnit t = (JCCompilationUnit) iter.next();
         if (iter.hasNext())
             throw new Error("too many trees found");
-        return t;
+        return Pair.of(task, t);
     }
 
     /**
@@ -203,15 +207,26 @@
      */
     void error(JavaFileObject file, Tree tree, String msg) {
         JCTree t = (JCTree) tree;
-        error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64));
+        error(file.getName() + ":" + getLine(file, t.pos) + ": " + msg + " " + trim(t, 64));
+    }
+
+    /**
+     *  Report an error for a specific tree node.
+     *  @param file the source file for the tree
+     *  @param t    the tree node
+     *  @param label an indication of the error
+     */
+    void error(JavaFileObject file, DocCommentTree comment, DocTree tree, String msg) {
+        DCDocComment dc = (DCDocComment) comment;
+        DCTree t = (DCTree) tree;
+        error(file.getName() + ":" + getLine(file, t.getSourcePosition(dc)) + ": " + msg + " " + trim(t, 64));
     }
 
     /**
      * Get a trimmed string for a tree node, with normalized white space and limited length.
      */
-    String trim(Tree tree, int len) {
-        JCTree t = (JCTree) tree;
-        String s = t.toString().replaceAll("\\s+", " ");
+    String trim(Object tree, int len) {
+        String s = tree.toString().replaceAll("\\s+", " ");
         return (s.length() < len) ? s : s.substring(0, len);
     }
 
@@ -276,17 +291,38 @@
     // where
     Map<JCTree.Tag, Set<Field>> map = new HashMap<JCTree.Tag,Set<Field>>();
 
+    /**
+     * Get the set of fields for a tree node that may contain child tree nodes.
+     * These are the fields that are subtypes of DCTree or List.
+     * The results are cached, based on the tree's tag.
+     */
+    Set<Field> getFields(DCTree tree) {
+        Set<Field> fields = dcMap.get(tree.getKind());
+        if (fields == null) {
+            fields = new HashSet<Field>();
+            for (Field f: tree.getClass().getFields()) {
+                Class<?> fc = f.getType();
+                if (DCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc))
+                    fields.add(f);
+            }
+            dcMap.put(tree.getKind(), fields);
+        }
+        return fields;
+    }
+    // where
+    Map<DCTree.Kind, Set<Field>> dcMap = new HashMap<>();
+
     /** Get the line number for the primary position for a tree.
      * The code is intended to be simple, although not necessarily efficient.
      * However, note that a file manager such as JavacFileManager is likely
      * to cache the results of file.getCharContent, avoiding the need to read
      * the bits from disk each time this method is called.
      */
-    int getLine(JavaFileObject file, JCTree tree) {
+    int getLine(JavaFileObject file, long pos) {
         try {
             CharSequence cs = file.getCharContent(true);
             int line = 1;
-            for (int i = 0; i < tree.pos; i++) {
+            for (int i = 0; i < pos; i++) {
                 if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings
                     line++;
             }
--- a/test/langtools/tools/javac/tree/JavacTreeScannerTest.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/tree/JavacTreeScannerTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -49,10 +49,12 @@
 import java.util.*;
 import javax.tools.*;
 
+import com.sun.source.util.JavacTask;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.TreeScanner;
 import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
 
 public class JavacTreeScannerTest extends AbstractTreeScannerTest {
     /**
@@ -75,8 +77,8 @@
         }
     }
 
-    int test(JCCompilationUnit tree) {
-        return new ScanTester().test(tree);
+    int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+        return new ScanTester().test(taskAndTree.snd);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/tree/SourceDocTreeScannerTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * Utility and test program to check public DocTreeScanner class.
+ * The program can be run standalone, or as a jtreg test.  For info on
+ * command line args, run program with no args.
+ *
+ * <p>
+ * jtreg: Note that by using the -r switch in the test description below, this test
+ * will process all java files in the langtools/test directory, thus implicitly
+ * covering any new language features that may be tested in this test suite.
+ */
+
+/*
+ * @test
+ * @bug 8227922
+ * @summary Verify the behavior of DocTreeScanner
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.tree
+ *          jdk.compiler/com.sun.tools.javac.util
+ * @build AbstractTreeScannerTest SourceDocTreeScannerTest
+ * @run main SourceDocTreeScannerTest -q -r .
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import javax.tools.*;
+
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.DocTreeScanner;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.tools.javac.tree.DCTree;
+import com.sun.tools.javac.tree.DCTree.DCDocComment;
+import com.sun.tools.javac.tree.DCTree.DCReference;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
+
+public class SourceDocTreeScannerTest extends AbstractTreeScannerTest {
+    /**
+     * Main entry point.
+     * If test.src is set, program runs in jtreg mode, and will throw an Error
+     * if any errors arise, otherwise System.exit will be used. In jtreg mode,
+     * the default base directory for file args is the value of ${test.src}.
+     * In jtreg mode, the -r option can be given to change the default base
+     * directory to the root test directory.
+     */
+    public static void main(String... args) {
+        String testSrc = System.getProperty("test.src");
+        File baseDir = (testSrc == null) ? null : new File(testSrc);
+        boolean ok = new SourceDocTreeScannerTest().run(baseDir, args);
+        if (!ok) {
+            if (testSrc != null)  // jtreg mode
+                throw new Error("failed");
+            else
+                System.exit(1);
+        }
+    }
+
+    int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+        return new ScanTester().test(taskAndTree);
+    }
+
+    /**
+     * Main class for testing operation of tree scanner.
+     * The set of nodes found by the scanner are compared
+     * against the set of nodes found by reflection.
+     */
+    private class ScanTester extends DocTreeScanner<Void,Void> {
+        /** Main entry method for the class. */
+        int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+            sourcefile = taskAndTree.snd.sourcefile;
+            int[] count = new int[1];
+            new TreePathScanner<Void, Void>() {
+                @Override
+                public Void scan(Tree tree, Void p) {
+                    if (tree != null) {
+                        DocTrees trees = DocTrees.instance(taskAndTree.fst);
+                        DocCommentTree dcTree = trees.getDocCommentTree(new TreePath(getCurrentPath(), tree));
+                        if (dcTree != null) {
+                            found = new HashSet<>();
+                            ScanTester.this.scan(dcTree, null);
+                            expect = new HashSet<>();
+                            ScanTester.this.reflectiveScan(dcTree);
+
+                            if (found.equals(expect)) {
+                                //System.err.println(sourcefile.getName() + ": trees compared OK");
+                                count[0] += found.size();
+                            } else {
+                                error(sourcefile.getName() + ": differences found");
+
+                                if (found.size() != expect.size())
+                                    error("Size mismatch; found: " + found.size() + ", expected: " + expect.size());
+
+                                Set<DocTree> missing = new HashSet<>();
+                                missing.addAll(expect);
+                                missing.removeAll(found);
+                                for (DocTree t: missing)
+                                    error(sourcefile, dcTree, t, "missing");
+
+                                Set<DocTree> excess = new HashSet<>();
+                                excess.addAll(found);
+                                excess.removeAll(expect);
+                                for (DocTree t: excess)
+                                    error(sourcefile, dcTree, t, "unexpected");
+                            }
+                        }
+                    }
+                    return super.scan(tree, p);
+                }
+            }.scan(taskAndTree.snd, null);
+
+            return 0;
+        }
+
+        /** Record all tree nodes found by scanner. */
+        @Override
+        public Void scan(DocTree tree, Void ignore) {
+            if (tree == null)
+                return null;
+            //System.err.println("FOUND: " + tree.getKind() + " " + trim(tree, 64));
+            found.add(tree);
+            return super.scan(tree, ignore);
+        }
+
+        /** record all tree nodes found by reflection. */
+        public void reflectiveScan(Object o) {
+            if (o == null)
+                return;
+            if (o instanceof DCTree) {
+                DCTree tree = (DCTree) o;
+                //System.err.println("EXPECT: " + tree.getKind() + " " + trim(tree, 64));
+                expect.add(tree);
+                for (Field f: getFields(tree)) {
+                    try {
+                        if (tree instanceof DCReference && f.getName().equals("paramTypes")) {
+                            //ignore - list of JCTrees
+                        } else if (tree instanceof DCDocComment &&
+                                   !f.getName().equals("firstSentence") &&
+                                   !f.getName().equals("body") &&
+                                   !f.getName().equals("tags")) {
+                            //ignore - covered by other fields
+                        } else {
+                            reflectiveScan(f.get(tree));
+                        }
+                    } catch (IllegalAccessException e) {
+                        error(e.toString());
+                    }
+                }
+            } else if (o instanceof List) {
+                List<?> list = (List<?>) o;
+                for (Object item: list)
+                    reflectiveScan(item);
+            } else
+                error("unexpected item: " + o);
+        }
+
+        JavaFileObject sourcefile;
+        Set<DocTree> found;
+        Set<DocTree> expect;
+    }
+}
--- a/test/langtools/tools/javac/tree/SourceTreeScannerTest.java	Wed Aug 14 08:08:39 2019 -0400
+++ b/test/langtools/tools/javac/tree/SourceTreeScannerTest.java	Wed Aug 14 08:23:16 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,6 +52,7 @@
 
 import com.sun.source.tree.CaseTree.CaseKind;
 import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
 import com.sun.source.util.TreeScanner;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCase;
@@ -59,6 +60,7 @@
 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
 import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
 import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Pair;
 
 public class SourceTreeScannerTest extends AbstractTreeScannerTest {
     /**
@@ -81,8 +83,8 @@
         }
     }
 
-    int test(JCCompilationUnit tree) {
-        return new ScanTester().test(tree);
+    int test(Pair<JavacTask, JCCompilationUnit> taskAndTree) {
+        return new ScanTester().test(taskAndTree.snd);
     }
 
     /**