changeset 32255:cc8c8786ef91

Merge
author duke
date Wed, 05 Jul 2017 20:46:35 +0200
parents 8d067af302fd 637b00638ed6
children 3966bd3b8167
files jdk/make/copy/Copy-jdk.hprof.agent.gmk jdk/make/lib/Lib-jdk.hprof.agent.gmk jdk/make/mapfiles/libhprof/mapfile-vers jdk/make/mapfiles/libjava_crw_demo/mapfile-vers jdk/src/jdk.deploy.osx/macosx/classes/apple/security/AppleProvider.java jdk/src/jdk.deploy.osx/macosx/classes/apple/security/KeychainStore.java jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof/Tracker.java jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_md.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.h jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.c jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.h jdk/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt jdk/src/jdk.hprof.agent/share/native/libhprof/manual.html jdk/src/jdk.hprof.agent/unix/native/libhprof/hprof_md.c jdk/src/jdk.hprof.agent/windows/native/libhprof/hprof_md.c nashorn/test/script/nosecurity/JDK-8055034.js nashorn/test/script/nosecurity/JDK-8055034.js.EXPECTED nashorn/test/script/nosecurity/JDK-8130127.js nashorn/test/script/nosecurity/JDK-8130127.js.EXPECTED
diffstat 285 files changed, 6741 insertions(+), 27643 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags-top-repo	Thu Aug 20 11:38:24 2015 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 20:46:35 2017 +0200
@@ -320,3 +320,4 @@
 8fd6eeb878606e39c908f12535f34ebbfd225a4a jdk9-b75
 d82072b699b880a1f647a5e2d7c0f86cec958941 jdk9-b76
 7972dc8f2a47f0c4cd8f02fa5662af41f028aa14 jdk9-b77
+8c40d4143ee13bdf8170c68cc384c36ab1e9fadb jdk9-b78
--- a/common/bin/compare_exceptions.sh.incl	Thu Aug 20 11:38:24 2015 -0700
+++ b/common/bin/compare_exceptions.sh.incl	Wed Jul 05 20:46:35 2017 +0200
@@ -42,7 +42,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -54,7 +53,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -62,9 +60,7 @@
 ./lib/i386/client/libjvm.so
 ./lib/i386/libattach.so
 ./lib/i386/libdt_socket.so
-./lib/i386/libhprof.so
 ./lib/i386/libinstrument.so
-./lib/i386/libjava_crw_demo.so
 ./lib/i386/libjsdt.so
 ./lib/i386/libmanagement.so
 ./lib/i386/libnpt.so
@@ -118,7 +114,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -130,16 +125,13 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
 ./demo/jvmti/waiters/lib/libwaiters.so
 ./lib/amd64/libattach.so
 ./lib/amd64/libdt_socket.so
-./lib/amd64/libhprof.so
 ./lib/amd64/libinstrument.so
-./lib/amd64/libjava_crw_demo.so
 ./lib/amd64/libjsdt.so
 ./lib/amd64/libjsig.so
 ./lib/amd64/libmanagement.so
@@ -197,7 +189,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -217,7 +208,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -232,7 +222,6 @@
 ./lib/amd64/libdcpr.so
 ./lib/amd64/libdt_socket.so
 ./lib/amd64/libfontmanager.so
-./lib/amd64/libhprof.so
 ./lib/amd64/libinstrument.so
 ./lib/amd64/libj2gss.so
 ./lib/amd64/libj2pcsc.so
@@ -240,7 +229,6 @@
 ./lib/amd64/libj2ucrypto.so
 ./lib/amd64/libjaas_unix.so
 ./lib/amd64/libjava.so
-./lib/amd64/libjava_crw_demo.so
 ./lib/amd64/libjawt.so
 ./lib/amd64/libjdwp.so
 ./lib/amd64/libjfr.so
@@ -330,7 +318,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -353,7 +340,6 @@
 ./demo/jvmti/gctest/lib/libgctest.so
 ./demo/jvmti/heapTracker/lib/libheapTracker.so
 ./demo/jvmti/heapViewer/lib/libheapViewer.so
-./demo/jvmti/hprof/lib/libhprof.so
 ./demo/jvmti/minst/lib/libminst.so
 ./demo/jvmti/mtrace/lib/libmtrace.so
 ./demo/jvmti/versionCheck/lib/libversionCheck.so
@@ -369,7 +355,6 @@
 ./lib/sparcv9/libdcpr.so
 ./lib/sparcv9/libdt_socket.so
 ./lib/sparcv9/libfontmanager.so
-./lib/sparcv9/libhprof.so
 ./lib/sparcv9/libinstrument.so
 ./lib/sparcv9/libj2gss.so
 ./lib/sparcv9/libj2pcsc.so
@@ -377,7 +362,6 @@
 ./lib/sparcv9/libj2ucrypto.so
 ./lib/sparcv9/libjaas_unix.so
 ./lib/sparcv9/libjava.so
-./lib/sparcv9/libjava_crw_demo.so
 ./lib/sparcv9/libjawt.so
 ./lib/sparcv9/libjdwp.so
 ./lib/sparcv9/libjfr.so
@@ -473,7 +457,6 @@
 ./demo/jvmti/heapTracker/lib/heapTracker.dll
 ./demo/jvmti/minst/lib/minst.dll
 ./bin/attach.dll
-./bin/java_crw_demo.dll
 ./bin/jsoundds.dll
 ./bin/server/jvm.dll
 ./bin/appletviewer.exe
@@ -611,9 +594,7 @@
 ./Contents/Home/lib/libawt_lwawt.dylib
 ./Contents/Home/lib/libdeploy.dylib
 ./Contents/Home/lib/libdt_socket.dylib
-./Contents/Home/lib/libhprof.dylib
 ./Contents/Home/lib/libinstrument.dylib
-./Contents/Home/lib/libjava_crw_demo.dylib
 ./Contents/Home/lib/libjdwp.dylib
 ./Contents/Home/lib/libjsdt.dylib
 ./Contents/Home/lib/libjsig.dylib
@@ -635,9 +616,7 @@
 ./lib/libawt_lwawt.dylib
 ./lib/libdeploy.dylib
 ./lib/libdt_socket.dylib
-./lib/libhprof.dylib
 ./lib/libinstrument.dylib
-./lib/libjava_crw_demo.dylib
 ./lib/libjdwp.dylib
 ./lib/libjsdt.dylib
 ./lib/libjsig.dylib
--- a/corba/.hgtags	Thu Aug 20 11:38:24 2015 -0700
+++ b/corba/.hgtags	Wed Jul 05 20:46:35 2017 +0200
@@ -320,3 +320,4 @@
 960b56805abd8460598897481820bd6a75f979e7 jdk9-b75
 d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
 8bb2441c0fec8b28f7bf11a0ca3ec1642e7ef457 jdk9-b77
+182bb7accc5253bcfefd8edc1d4997ec8f9f8694 jdk9-b78
--- a/hotspot/.hgtags	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 20:46:35 2017 +0200
@@ -480,3 +480,4 @@
 2f354281e9915275693c4e519a959b8a6f22d3a3 jdk9-b75
 0bc8d1656d6f2b1fdfe803c1305a108bb9939f35 jdk9-b76
 e66c3813789debfc06f206afde1bf7a84cb08451 jdk9-b77
+20dc06b04fe5ec373879414d60ef82ac70faef98 jdk9-b78
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -416,7 +416,8 @@
   int jmp_off = __ offset();
   __ jmp(_patch_site_entry);
   // Add enough nops so deoptimization can overwrite the jmp above with a call
-  // and not destroy the world.
+  // and not destroy the world. We cannot use fat nops here, since the concurrent
+  // code rewrite may transiently create the illegal instruction sequence.
   for (int j = __ offset() ; j < jmp_off + 5 ; j++ ) {
     __ nop();
   }
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -345,9 +345,7 @@
   const bool do_post_padding = VerifyOops || UseCompressedClassPointers;
   if (!do_post_padding) {
     // insert some nops so that the verified entry point is aligned on CodeEntryAlignment
-    while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) {
-      __ nop();
-    }
+    __ align(CodeEntryAlignment, __ offset() + ic_cmp_size);
   }
   int offset = __ offset();
   __ inline_cache_check(receiver, IC_Klass);
@@ -2861,9 +2859,7 @@
       case lir_virtual_call:  // currently, sparc-specific for niagara
       default: ShouldNotReachHere();
     }
-    while (offset++ % BytesPerWord != 0) {
-      __ nop();
-    }
+    __ align(BytesPerWord, offset);
   }
 }
 
@@ -2902,10 +2898,7 @@
   int start = __ offset();
   if (os::is_MP()) {
     // make sure that the displacement word of the call ends up word aligned
-    int offset = __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset;
-    while (offset++ % BytesPerWord != 0) {
-      __ nop();
-    }
+    __ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset);
   }
   __ relocate(static_stub_Relocation::spec(call_pc));
   __ mov_metadata(rbx, (Metadata*)NULL);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -970,8 +970,12 @@
 }
 
 void MacroAssembler::align(int modulus) {
-  if (offset() % modulus != 0) {
-    nop(modulus - (offset() % modulus));
+  align(modulus, offset());
+}
+
+void MacroAssembler::align(int modulus, int target) {
+  if (target % modulus != 0) {
+    nop(modulus - (target % modulus));
   }
 }
 
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -192,6 +192,7 @@
 
   // Alignment
   void align(int modulus);
+  void align(int modulus, int target);
 
   // A 5 byte nop that is safe for patching (see patch_verified_entry)
   void fat_nop();
--- a/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -108,7 +108,7 @@
 #define GEN_SIZE(Type)                                  \
   switch(gen_variant) {                                 \
   case GEN_OFFSET:                                      \
-    printf("#define SIZE_%-35s %ld\n",                   \
+    printf("#define SIZE_%-35s %ld\n",                  \
             #Type, sizeof(Type));                       \
     break;                                              \
   case GEN_INDEX:                                       \
@@ -134,7 +134,7 @@
   }
 
 void gen_prologue(GEN_variant gen_variant) {
-    const char *suffix;
+    const char *suffix = "Undefined-Suffix";
 
     switch(gen_variant) {
       case GEN_OFFSET: suffix = ".h";        break;
@@ -228,10 +228,10 @@
   printf("\n");
 
   GEN_OFFS(Method, _constMethod);
-  GEN_OFFS(Method, _constants);
   GEN_OFFS(Method, _access_flags);
   printf("\n");
 
+  GEN_OFFS(ConstMethod, _constants);
   GEN_OFFS(ConstMethod, _flags);
   GEN_OFFS(ConstMethod, _code_size);
   GEN_OFFS(ConstMethod, _name_index);
@@ -264,7 +264,7 @@
 
   GEN_OFFS(nmethod, _method);
   GEN_OFFS(nmethod, _dependencies_offset);
-  GEN_OFFS(nmethod, _oops_offset);
+  GEN_OFFS(nmethod, _metadata_offset);
   GEN_OFFS(nmethod, _scopes_data_offset);
   GEN_OFFS(nmethod, _scopes_pcs_offset);
   GEN_OFFS(nmethod, _handler_table_offset);
--- a/hotspot/src/os/bsd/dtrace/jhelper.d	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/jhelper.d	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +49,7 @@
 extern pointer __1cIUniverseO_collectedHeap_;
 
 extern pointer __1cHnmethodG__vtbl_;
-extern pointer __1cNMethodG__vtbl_;
+extern pointer __1cGMethodG__vtbl_;
 extern pointer __1cKBufferBlobG__vtbl_;
 
 #define copyin_ptr(ADDR)    *(pointer*)  copyin((pointer) (ADDR), sizeof(pointer))
@@ -164,7 +164,7 @@
   this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len);
 
   this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_;
-  
+ 
   /*
    * Get Java heap bounds
    */
@@ -457,12 +457,15 @@
 
   this->nameSymbol = copyin_ptr(this->constantPool +
       this->nameIndex * sizeof (pointer) + SIZE_ConstantPool);
+  /* The symbol is a CPSlot and has lower bit set to indicate metadata */
+  this->nameSymbol &= (~1); /* remove metadata lsb */
 
   this->nameSymbolLength = copyin_uint16(this->nameSymbol +
       OFFSET_Symbol_length);
 
   this->signatureSymbol = copyin_ptr(this->constantPool +
       this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
+  this->signatureSymbol &= (~1); /* remove metadata lsb */
 
   this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
       OFFSET_Symbol_length);
--- a/hotspot/src/os/bsd/dtrace/jvm_dtrace.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/jvm_dtrace.c	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@
 /* attach to given JVM */
 jvm_t* jvm_attach(pid_t pid) {
     jvm_t* jvm;
-    int door_fd, attach_fd, i;
+    int door_fd, attach_fd, i = 0;
 
     jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
     if (jvm == NULL) {
@@ -292,14 +292,13 @@
 /* detach the givenb JVM */
 int jvm_detach(jvm_t* jvm) {
     if (jvm) {
-        int res;
+        int res = 0;
         if (jvm->door_fd != -1) {
             if (file_close(jvm->door_fd) != 0) {
                 set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
                 res = -1;
             } else {
                 clear_jvm_error();
-                res = 0;
             }
         }
         free(jvm);
--- a/hotspot/src/os/bsd/dtrace/libjvm_db.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/bsd/dtrace/libjvm_db.c	Wed Jul 05 20:46:35 2017 +0200
@@ -882,7 +882,7 @@
 /* Finds a PcDesc with real-pc equal to N->pc */
 static int pc_desc_at(Nmethod_t *N)
 {
-  uint64_t pc_diff;
+  uint64_t pc_diff = 999;
   int32_t offs;
   int32_t err;
 
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -217,9 +217,9 @@
     //
     return false;
   }
-  // See if the uid of the directory matches the effective uid of the process.
-  //
-  if (statp->st_uid != geteuid()) {
+  // If user is not root then see if the uid of the directory matches the effective uid of the process.
+  uid_t euid = geteuid();
+  if ((euid != 0) && (statp->st_uid != euid)) {
     // The directory was not created by this user, declare it insecure.
     //
     return false;
--- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -85,7 +85,7 @@
 #define GEN_OFFS_NAME(Type,Name,OutputType)             \
   switch(gen_variant) {                                 \
   case GEN_OFFSET:                                      \
-    printf("#define OFFSET_%-33s %d\n",                 \
+    printf("#define OFFSET_%-33s %ld\n",                \
             #OutputType #Name, offset_of(Type, Name));  \
     break;                                              \
   case GEN_INDEX:                                       \
@@ -103,7 +103,7 @@
 #define GEN_SIZE(Type)                                  \
   switch(gen_variant) {                                 \
   case GEN_OFFSET:                                      \
-    printf("#define SIZE_%-35s %d\n",                   \
+    printf("#define SIZE_%-35s %ld\n",                  \
             #Type, sizeof(Type));                       \
     break;                                              \
   case GEN_INDEX:                                       \
@@ -129,7 +129,7 @@
   }
 
 void gen_prologue(GEN_variant gen_variant) {
-    const char *suffix;
+    const char *suffix = "Undefined-Suffix";
 
     switch(gen_variant) {
       case GEN_OFFSET: suffix = ".h";        break;
@@ -211,7 +211,7 @@
   GEN_OFFS(ConstantPool, _pool_holder);
   printf("\n");
 
-  GEN_VALUE(OFFSET_HeapBlockHeader_used, offset_of(HeapBlock::Header, _used));
+  GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used));
   GEN_OFFS(oopDesc, _metadata);
   printf("\n");
 
@@ -275,7 +275,7 @@
   GEN_OFFS(NarrowPtrStruct, _shift);
   printf("\n");
 
-  GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header));
+  GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));
   GEN_SIZE(oopDesc);
   GEN_SIZE(ConstantPool);
   printf("\n");
--- a/hotspot/src/os/solaris/dtrace/jvm_dtrace.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/solaris/dtrace/jvm_dtrace.c	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@
 /* attach to given JVM */
 jvm_t* jvm_attach(pid_t pid) {
     jvm_t* jvm;
-    int door_fd, attach_fd, i;
+    int door_fd, attach_fd, i = 0;
 
     jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
     if (jvm == NULL) {
@@ -292,14 +292,13 @@
 /* detach the givenb JVM */
 int jvm_detach(jvm_t* jvm) {
     if (jvm) {
-        int res;
+        int res = 0;
         if (jvm->door_fd != -1) {
             if (file_close(jvm->door_fd) != 0) {
                 set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
                 res = -1;
             } else {
                 clear_jvm_error();
-                res = 0;
             }
         }
         free(jvm);
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c	Wed Jul 05 20:46:35 2017 +0200
@@ -882,7 +882,7 @@
 /* Finds a PcDesc with real-pc equal to N->pc */
 static int pc_desc_at(Nmethod_t *N)
 {
-  uint64_t pc_diff;
+  uint64_t pc_diff = 999;
   int32_t offs;
   int32_t err;
 
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -182,75 +182,6 @@
 
 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
 
-// Thread Local Storage
-// This is common to all Solaris platforms so it is defined here,
-// in this common file.
-// The declarations are in the os_cpu threadLS*.hpp files.
-//
-// Static member initialization for TLS
-Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL};
-
-#ifndef PRODUCT
-  #define _PCT(n,d)       ((100.0*(double)(n))/(double)(d))
-
-int ThreadLocalStorage::_tcacheHit = 0;
-int ThreadLocalStorage::_tcacheMiss = 0;
-
-void ThreadLocalStorage::print_statistics() {
-  int total = _tcacheMiss+_tcacheHit;
-  tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n",
-                _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total));
-}
-  #undef _PCT
-#endif // PRODUCT
-
-Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id,
-                                                        int index) {
-  Thread *thread = get_thread_slow();
-  if (thread != NULL) {
-    address sp = os::current_stack_pointer();
-    guarantee(thread->_stack_base == NULL ||
-              (sp <= thread->_stack_base &&
-              sp >= thread->_stack_base - thread->_stack_size) ||
-              is_error_reported(),
-              "sp must be inside of selected thread stack");
-
-    thread->set_self_raw_id(raw_id);  // mark for quick retrieval
-    _get_thread_cache[index] = thread;
-  }
-  return thread;
-}
-
-
-static const double all_zero[sizeof(Thread) / sizeof(double) + 1] = {0};
-#define NO_CACHED_THREAD ((Thread*)all_zero)
-
-void ThreadLocalStorage::pd_set_thread(Thread* thread) {
-
-  // Store the new value before updating the cache to prevent a race
-  // between get_thread_via_cache_slowly() and this store operation.
-  os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread);
-
-  // Update thread cache with new thread if setting on thread create,
-  // or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit.
-  uintptr_t raw = pd_raw_thread_id();
-  int ix = pd_cache_index(raw);
-  _get_thread_cache[ix] = thread == NULL ? NO_CACHED_THREAD : thread;
-}
-
-void ThreadLocalStorage::pd_init() {
-  for (int i = 0; i < _pd_cache_size; i++) {
-    _get_thread_cache[i] = NO_CACHED_THREAD;
-  }
-}
-
-// Invalidate all the caches (happens to be the same as pd_init).
-void ThreadLocalStorage::pd_invalidate_all() { pd_init(); }
-
-#undef NO_CACHED_THREAD
-
-// END Thread Local Storage
-
 static inline size_t adjust_stack_size(address base, size_t size) {
   if ((ssize_t)size < 0) {
     // 4759953: Compensate for ridiculous stack size.
@@ -1289,67 +1220,6 @@
   return (int)(_initial_pid ? _initial_pid : getpid());
 }
 
-int os::allocate_thread_local_storage() {
-  // %%%       in Win32 this allocates a memory segment pointed to by a
-  //           register.  Dan Stein can implement a similar feature in
-  //           Solaris.  Alternatively, the VM can do the same thing
-  //           explicitly: malloc some storage and keep the pointer in a
-  //           register (which is part of the thread's context) (or keep it
-  //           in TLS).
-  // %%%       In current versions of Solaris, thr_self and TSD can
-  //           be accessed via short sequences of displaced indirections.
-  //           The value of thr_self is available as %g7(36).
-  //           The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4),
-  //           assuming that the current thread already has a value bound to k.
-  //           It may be worth experimenting with such access patterns,
-  //           and later having the parameters formally exported from a Solaris
-  //           interface.  I think, however, that it will be faster to
-  //           maintain the invariant that %g2 always contains the
-  //           JavaThread in Java code, and have stubs simply
-  //           treat %g2 as a caller-save register, preserving it in a %lN.
-  thread_key_t tk;
-  if (thr_keycreate(&tk, NULL)) {
-    fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed "
-                  "(%s)", strerror(errno)));
-  }
-  return int(tk);
-}
-
-void os::free_thread_local_storage(int index) {
-  // %%% don't think we need anything here
-  // if (pthread_key_delete((pthread_key_t) tk)) {
-  //   fatal("os::free_thread_local_storage: pthread_key_delete failed");
-  // }
-}
-
-// libthread allocate for tsd_common is a version specific
-// small number - point is NO swap space available
-#define SMALLINT 32
-void os::thread_local_storage_at_put(int index, void* value) {
-  // %%% this is used only in threadLocalStorage.cpp
-  if (thr_setspecific((thread_key_t)index, value)) {
-    if (errno == ENOMEM) {
-      vm_exit_out_of_memory(SMALLINT, OOM_MALLOC_ERROR,
-                            "thr_setspecific: out of swap space");
-    } else {
-      fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed "
-                    "(%s)", strerror(errno)));
-    }
-  } else {
-    ThreadLocalStorage::set_thread_in_slot((Thread *) value);
-  }
-}
-
-// This function could be called before TLS is initialized, for example, when
-// VM receives an async signal or when VM causes a fatal error during
-// initialization. Return NULL if thr_getspecific() fails.
-void* os::thread_local_storage_at(int index) {
-  // %%% this is used only in threadLocalStorage.cpp
-  void* r = NULL;
-  return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r;
-}
-
-
 // gethrtime() should be monotonic according to the documentation,
 // but some virtualized platforms are known to break this guarantee.
 // getTimeNanos() must be guaranteed not to move backwards, so we
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -219,9 +219,9 @@
     //
     return false;
   }
-  // See if the uid of the directory matches the effective uid of the process.
-  //
-  if (statp->st_uid != geteuid()) {
+  // If user is not root then see if the uid of the directory matches the effective uid of the process.
+  uid_t euid = geteuid();
+  if ((euid != 0) && (statp->st_uid != euid)) {
     // The directory was not created by this user, declare it insecure.
     //
     return false;
--- a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,19 +39,12 @@
 // For SPARC, to avoid excessive register window spill-fill faults,
 // we aggressively inline these routines.
 
+inline void ThreadLocalStorage::set_thread(Thread* thread) {
+  _thr_current = thread;
+}
+
 inline Thread* ThreadLocalStorage::thread()  {
-  // don't use specialized code if +UseMallocOnly -- may confuse Purify et al.
-  debug_only(if (UseMallocOnly) return get_thread_slow(););
-
-  uintptr_t raw = pd_raw_thread_id();
-  int ix = pd_cache_index(raw);
-  Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix];
-  if (candidate->self_raw_id() == raw) {
-    // hit
-    return candidate;
-  } else {
-    return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix);
-  }
+  return _thr_current;
 }
 
 #endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP
--- a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,19 +26,26 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadLocalStorage.hpp"
 
-// Provides an entry point we can link against and
-// a buffer we can emit code into. The buffer is
-// filled by ThreadLocalStorage::generate_code_for_get_thread
-// and called from ThreadLocalStorage::thread()
+// True thread-local variable
+__thread Thread * ThreadLocalStorage::_thr_current = NULL;
 
-#include <sys/systeminfo.h>
+// Implementations needed to support the shared API
 
-// The portable TLS mechanism (get_thread_via_cache) is enough on SPARC.
-// There is no need for hand-assembling a special function.
-void ThreadLocalStorage::generate_code_for_get_thread() {
+void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
+
+bool ThreadLocalStorage::_initialized = false;
+
+void ThreadLocalStorage::init() {
+  _initialized = true;
 }
 
-void ThreadLocalStorage::set_thread_in_slot (Thread * self) {}
+bool ThreadLocalStorage::is_initialized() {
+  return _initialized;
+}
+
+Thread* ThreadLocalStorage::get_thread_slow() {
+    return thread();
+}
 
 extern "C" Thread* get_thread() {
   return ThreadLocalStorage::thread();
--- a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,47 +25,15 @@
 #ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
 #define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
 
-public:
-  // Java Thread  - force inlining
-  static inline Thread* thread() ;
+// Solaris specific implementation involves simple, direct use
+// of a compiler-based thread-local variable
 
 private:
-  static Thread* _get_thread_cache[];  // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size]
-  static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index);
+  static __thread Thread * _thr_current;
 
-  NOT_PRODUCT(static int _tcacheHit;)
-  NOT_PRODUCT(static int _tcacheMiss;)
+  static bool _initialized;  // needed for shared API
 
 public:
-
-  // Print cache hit/miss statistics
-  static void print_statistics() PRODUCT_RETURN;
-
-  enum Constants {
-    _pd_cache_size         =  256*2  // projected typical # of threads * 2
-  };
-
-  static void set_thread_in_slot (Thread *) ;
-
-  static uintptr_t pd_raw_thread_id() {
-    return _raw_thread_id();
-  }
-
-  static int pd_cache_index(uintptr_t raw_id) {
-    // Hash function: From email from Dave:
-    // The hash function deserves an explanation.  %g7 points to libthread's
-    // "thread" structure.  On T1 the thread structure is allocated on the
-    // user's stack (yes, really!) so the ">>20" handles T1 where the JVM's
-    // stack size is usually >= 1Mb.  The ">>9" is for T2 where Roger allocates
-    // globs of thread blocks contiguously.  The "9" has to do with the
-    // expected size of the T2 thread structure.  If these constants are wrong
-    // the worst thing that'll happen is that the hit rate for heavily threaded
-    // apps won't be as good as it could be.  If you want to burn another
-    // shift+xor you could mix together _all of the %g7 bits to form the hash,
-    // but I think that's excessive.  Making the change above changed the
-    // T$ miss rate on SpecJBB (on a 16X system) from about 3% to imperceptible.
-    uintptr_t ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size);
-    return ix;
-  }
+  static inline Thread* thread();
 
 #endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP
--- a/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,10 @@
  */
 
 #include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "runtime/os.hpp"
 #include "runtime/threadLocalStorage.hpp"
-
+#include "runtime/thread.inline.hpp"
 
 void MacroAssembler::int3() {
   push(rax);
@@ -39,98 +38,32 @@
   pop(rax);
 }
 
-#define __  _masm->
-#ifndef _LP64
-static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) {
+// This is simply a call to ThreadLocalStorage::thread()
+void MacroAssembler::get_thread(Register thread) {
+  if (thread != rax) {
+    push(rax);
+  }
+  push(rdi);
+  push(rsi);
+  push(rdx);
+  push(rcx);
+  push(r8);
+  push(r9);
+  push(r10);
+  push(r11);
 
-  // slow call to of thr_getspecific
-  // int thr_getspecific(thread_key_t key, void **value);
-  // Consider using pthread_getspecific instead.
+  call(RuntimeAddress(CAST_FROM_FN_PTR(address, ThreadLocalStorage::thread)));
 
-__  push(0);                                                            // allocate space for return value
-  if (thread != rax) __ push(rax);                                      // save rax, if caller still wants it
-__  push(rcx);                                                          // save caller save
-__  push(rdx);                                                          // save caller save
+  pop(r11);
+  pop(r10);
+  pop(r9);
+  pop(r8);
+  pop(rcx);
+  pop(rdx);
+  pop(rsi);
+  pop(rdi);
   if (thread != rax) {
-__    lea(thread, Address(rsp, 3 * sizeof(int)));                       // address of return value
-  } else {
-__    lea(thread, Address(rsp, 2 * sizeof(int)));                       // address of return value
-  }
-__  push(thread);                                                       // and pass the address
-__  push(ThreadLocalStorage::thread_index());                           // the key
-__  call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific)));
-__  increment(rsp, 2 * wordSize);
-__  pop(rdx);
-__  pop(rcx);
-  if (thread != rax) __ pop(rax);
-__  pop(thread);
-
-}
-#else
-static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) {
-  // slow call to of thr_getspecific
-  // int thr_getspecific(thread_key_t key, void **value);
-  // Consider using pthread_getspecific instead.
-
-  if (thread != rax) {
-__    push(rax);
-  }
-__  push(0); // space for return value
-__  push(rdi);
-__  push(rsi);
-__  lea(rsi, Address(rsp, 16)); // pass return value address
-__  push(rdx);
-__  push(rcx);
-__  push(r8);
-__  push(r9);
-__  push(r10);
-  // XXX
-__  mov(r10, rsp);
-__  andptr(rsp, -16);
-__  push(r10);
-__  push(r11);
-
-__  movl(rdi, ThreadLocalStorage::thread_index());
-__  call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific)));
-
-__  pop(r11);
-__  pop(rsp);
-__  pop(r10);
-__  pop(r9);
-__  pop(r8);
-__  pop(rcx);
-__  pop(rdx);
-__  pop(rsi);
-__  pop(rdi);
-__  pop(thread); // load return value
-  if (thread != rax) {
-__    pop(rax);
+    movl(thread, rax);
+    pop(rax);
   }
 }
-#endif //LP64
-
-void MacroAssembler::get_thread(Register thread) {
-
-  int segment = NOT_LP64(Assembler::GS_segment) LP64_ONLY(Assembler::FS_segment);
-  // Try to emit a Solaris-specific fast TSD/TLS accessor.
-  ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode ();
-  if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) {            // T1
-     // Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset]
-     emit_int8 (segment);
-     // ExternalAddress doesn't work because it can't take NULL
-     AddressLiteral null(0, relocInfo::none);
-     movptr (thread, null);
-     movptr(thread, Address(thread, ThreadLocalStorage::pd_getTlsOffset())) ;
-     return ;
-  } else
-  if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) {              // T2
-     // mov r, gs:[tlsOffset]
-     emit_int8 (segment);
-     AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none);
-     movptr (thread, tls_off);
-     return ;
-  }
-
-  slow_call_thr_specific(this, thread);
-
-}
--- a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,167 +26,27 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadLocalStorage.hpp"
 
-#ifdef AMD64
-extern "C" Thread*  fs_load(ptrdiff_t tlsOffset);
-extern "C" intptr_t fs_thread();
-#else
-// From solaris_i486.s
-extern "C" Thread*  gs_load(ptrdiff_t tlsOffset);
-extern "C" intptr_t gs_thread();
-#endif // AMD64
+// True thread-local variable
+__thread Thread * ThreadLocalStorage::_thr_current = NULL;
 
-// tlsMode encoding:
-//
-// pd_tlsAccessUndefined : uninitialized
-// pd_tlsAccessSlow      : not available
-// pd_tlsAccessIndirect  :
-//   old-style indirect access - present in "T1" libthread.
-//   use thr_slot_sync_allocate() to attempt to allocate a slot.
-// pd_tlsAccessDirect    :
-//   new-style direct access - present in late-model "T2" libthread.
-//   Allocate the offset (slot) via _thr_slot_offset() or by
-//   defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing
-//   that offset into libjvm.so.
-//   See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/.
-//
-// Note that we have a capability gap - some early model T2 forms
-// (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor
-// _thr_slot_offset().  In that case we revert to the usual
-// thr_getspecific accessor.
-//
+// Implementations needed to support the shared API
 
-static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ;
-static ptrdiff_t tlsOffset = 0 ;
-static thread_key_t tlsKey ;
+void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
 
-typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ;
-typedef ptrdiff_t (*TSO_Entry) (int) ;
+bool ThreadLocalStorage::_initialized = false;
 
-ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode ()
-{
-   guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
-   return tlsMode ;
+void ThreadLocalStorage::init() {
+  _initialized = true;
 }
 
-ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () {
-   guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
-   return tlsOffset ;
+bool ThreadLocalStorage::is_initialized() {
+  return _initialized;
 }
 
-// TODO: Consider the following improvements:
-//
-// 1.   Convert from thr_*specific* to pthread_*specific*.
-//      The pthread_ forms are slightly faster.  Also, the
-//      pthread_ forms have a pthread_key_delete() API which
-//      would aid in clean JVM shutdown and the eventual goal
-//      of permitting a JVM to reinstantiate itself withing a process.
-//
-// 2.   See ThreadLocalStorage::init().  We end up allocating
-//      two TLS keys during VM startup.  That's benign, but we could collapse
-//      down to one key without too much trouble.
-//
-// 3.   MacroAssembler::get_thread() currently emits calls to thr_getspecific().
-//      Modify get_thread() to call Thread::current() instead.
-//
-// 4.   Thread::current() currently uses a cache keyed by %gs:[0].
-//      (The JVM has PSARC permission to use %g7/%gs:[0]
-//      as an opaque temporally unique thread identifier).
-//      For C++ access to a thread's reflexive "self" pointer we
-//      should consider using one of the following:
-//      a. a radix tree keyed by %esp - as in EVM.
-//         This requires two loads (the 2nd dependent on the 1st), but
-//         is easily inlined and doesn't require a "miss" slow path.
-//      b. a fast TLS/TSD slot allocated by _thr_slot_offset
-//         or _thr_slot_sync_allocate.
-//
-// 5.   'generate_code_for_get_thread' is a misnomer.
-//      We should change it to something more general like
-//      pd_ThreadSelf_Init(), for instance.
-//
-
-static void AllocateTLSOffset ()
-{
-   int rslt ;
-   TSSA_Entry tssa ;
-   TSO_Entry  tso ;
-   ptrdiff_t off ;
-
-   guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ;
-   tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
-   tlsOffset = 0 ;
-#ifndef AMD64
-
-   tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ;
-   if (tssa != NULL) {
-        off = -1 ;
-        rslt = (*tssa)(&off, NULL, NULL) ;                // (off,dtor,darg)
-        if (off != -1) {
-           tlsOffset = off ;
-           tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ;
-           return ;
-        }
-    }
-
-    rslt = thr_keycreate (&tlsKey, NULL) ;
-    if (rslt != 0) {
-        tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;   // revert to slow mode
-        return ;
-    }
-
-    tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ;
-    if (tso != NULL) {
-        off = (*tso)(tlsKey) ;
-        if (off >= 0) {
-           tlsOffset = off ;
-           tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ;
-           return ;
-        }
-    }
-
-    // Failure: Too bad ... we've allocated a TLS slot we don't need and there's
-    // no provision in the ABI for returning the slot.
-    //
-    // If we didn't find a slot then then:
-    // 1. We might be on liblwp.
-    // 2. We might be on T2 libthread, but all "fast" slots are already
-    //    consumed
-    // 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are
-    //    consumed.
-    // 4. We might be on T2 libthread, but it's be re-architected
-    //    so that fast slots are no longer g7-relative.
-    //
-
-    tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ;
-    return ;
-#endif // AMD64
+Thread* ThreadLocalStorage::get_thread_slow() {
+    return thread();
 }
 
-void ThreadLocalStorage::generate_code_for_get_thread() {
-    AllocateTLSOffset() ;
-}
-
-void ThreadLocalStorage::set_thread_in_slot(Thread *thread) {
-  guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ;
-  if (tlsMode == pd_tlsAccessIndirect) {
-#ifdef AMD64
-        intptr_t tbase = fs_thread();
-#else
-        intptr_t tbase = gs_thread();
-#endif // AMD64
-        *((Thread**) (tbase + tlsOffset)) = thread ;
-  } else
-  if (tlsMode == pd_tlsAccessDirect) {
-        thr_setspecific (tlsKey, (void *) thread) ;
-        // set with thr_setspecific and then readback with gs_load to validate.
-#ifdef AMD64
-        guarantee (thread == fs_load(tlsOffset), "tls readback failure") ;
-#else
-        guarantee (thread == gs_load(tlsOffset), "tls readback failure") ;
-#endif // AMD64
-  }
-}
-
-
 extern "C" Thread* get_thread() {
   return ThreadLocalStorage::thread();
 }
--- a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,61 +25,15 @@
 #ifndef OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
 #define OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
 
-// Processor dependent parts of ThreadLocalStorage
+// Solaris specific implementation involves simple, direct use
+// of a compiler-based thread-local variable
 
 private:
-  static Thread* _get_thread_cache[];  // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size]
-  static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index);
+  static __thread Thread * _thr_current;
 
-  NOT_PRODUCT(static int _tcacheHit;)
-  NOT_PRODUCT(static int _tcacheMiss;)
+  static bool _initialized;  // needed for shared API
 
 public:
-  // Cache hit/miss statistics
-  static void print_statistics() PRODUCT_RETURN;
-
-  enum Constants {
-#ifdef AMD64
-    _pd_cache_size         =  256*2   // projected typical # of threads * 2
-#else
-    _pd_cache_size         =  128*2   // projected typical # of threads * 2
-#endif // AMD64
-  };
-
-  enum pd_tlsAccessMode {
-     pd_tlsAccessUndefined      = -1,
-     pd_tlsAccessSlow           = 0,
-     pd_tlsAccessIndirect       = 1,
-     pd_tlsAccessDirect         = 2
-  } ;
-
-  static void set_thread_in_slot (Thread *) ;
-
-  static pd_tlsAccessMode pd_getTlsAccessMode () ;
-  static ptrdiff_t pd_getTlsOffset () ;
-
-  static uintptr_t pd_raw_thread_id() {
-#ifdef _GNU_SOURCE
-#ifdef AMD64
-    uintptr_t rv;
-    __asm__ __volatile__ ("movq %%fs:0, %0" : "=r"(rv));
-    return rv;
-#else
-    return gs_thread();
-#endif // AMD64
-#else  //_GNU_SOURCE
-    return _raw_thread_id();
-#endif //_GNU_SOURCE
-  }
-
-  static int pd_cache_index(uintptr_t raw_id) {
-    // Copied from the sparc version. Dave said it should also work fine
-    // for solx86.
-    int ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size);
-    return ix;
-  }
-
-  // Java Thread
   static inline Thread* thread();
 
 #endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -33,7 +33,9 @@
 #include "runtime/os.hpp"
 
 void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
-  // we must have enough patching space so that call can be inserted
+  // We must have enough patching space so that call can be inserted.
+  // We cannot use fat nops here, since the concurrent code rewrite may transiently
+  // create the illegal instruction sequence.
   while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeCall::instruction_size) {
     _masm->nop();
   }
@@ -592,9 +594,7 @@
 void LIR_Assembler::emit_op0(LIR_Op0* op) {
   switch (op->code()) {
     case lir_word_align: {
-      while (code_offset() % BytesPerWord != 0) {
-        _masm->nop();
-      }
+      _masm->align(BytesPerWord);
       break;
     }
 
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -620,12 +620,12 @@
   // Support for parallelizing survivor space rescan
   if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
     const size_t max_plab_samples =
-      ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size();
+      _young_gen->max_survivor_size() / (ThreadLocalAllocBuffer::min_size() * HeapWordSize);
 
     _survivor_plab_array  = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
-    _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
+    _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC);
     _cursor               = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads, mtGC);
-    _survivor_chunk_capacity = 2*max_plab_samples;
+    _survivor_chunk_capacity = max_plab_samples;
     for (uint i = 0; i < ParallelGCThreads; i++) {
       HeapWord** vec = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC);
       ChunkArray* cur = ::new (&_survivor_plab_array[i]) ChunkArray(vec, max_plab_samples);
@@ -641,12 +641,6 @@
   _inter_sweep_timer.start();  // start of time
 }
 
-size_t CMSCollector::plab_sample_minimum_size() {
-  // The default value of MinTLABSize is 2k, but there is
-  // no way to get the default value if the flag has been overridden.
-  return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K);
-}
-
 const char* ConcurrentMarkSweepGeneration::name() const {
   return "concurrent mark-sweep generation";
 }
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -739,10 +739,6 @@
   size_t*    _cursor;
   ChunkArray* _survivor_plab_array;
 
-  // A bounded minimum size of PLABs, should not return too small values since
-  // this will affect the size of the data structures used for parallel young gen rescan
-  size_t plab_sample_minimum_size();
-
   // Support for marking stack overflow handling
   bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
   bool par_take_from_overflow_list(size_t num,
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -300,5 +300,3 @@
   }
   return G1AllocRegion::release();
 }
-
-
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/g1/g1Allocator.hpp"
+#include "gc/g1/g1Allocator.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1MarkSweep.hpp"
@@ -67,11 +67,11 @@
     // retired. We have to remove it now, since we don't allow regions
     // we allocate to in the region sets. We'll re-add it later, when
     // it's retired again.
-    _g1h->_old_set.remove(retained_region);
+    _g1h->old_set_remove(retained_region);
     bool during_im = _g1h->collector_state()->during_initial_mark_pause();
     retained_region->note_start_of_copying(during_im);
     old->set(retained_region);
-    _g1h->_hr_printer.reuse(retained_region);
+    _g1h->hr_printer()->reuse(retained_region);
     evacuation_info.set_alloc_regions_used_before(retained_region->used());
   }
 }
@@ -116,15 +116,85 @@
 G1PLAB::G1PLAB(size_t gclab_word_size) :
   PLAB(gclab_word_size), _retired(true) { }
 
-HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest,
-                                                        size_t word_sz,
-                                                        AllocationContext_t context) {
+size_t G1Allocator::unsafe_max_tlab_alloc(AllocationContext_t context) {
+  // Return the remaining space in the cur alloc region, but not less than
+  // the min TLAB size.
+
+  // Also, this value can be at most the humongous object threshold,
+  // since we can't allow tlabs to grow big enough to accommodate
+  // humongous objects.
+
+  HeapRegion* hr = mutator_alloc_region(context)->get();
+  size_t max_tlab = _g1h->max_tlab_size() * wordSize;
+  if (hr == NULL) {
+    return max_tlab;
+  } else {
+    return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab);
+  }
+}
+
+HeapWord* G1Allocator::par_allocate_during_gc(InCSetState dest,
+                                              size_t word_size,
+                                              AllocationContext_t context) {
+  switch (dest.value()) {
+    case InCSetState::Young:
+      return survivor_attempt_allocation(word_size, context);
+    case InCSetState::Old:
+      return old_attempt_allocation(word_size, context);
+    default:
+      ShouldNotReachHere();
+      return NULL; // Keep some compilers happy
+  }
+}
+
+HeapWord* G1Allocator::survivor_attempt_allocation(size_t word_size,
+                                                   AllocationContext_t context) {
+  assert(!_g1h->is_humongous(word_size),
+         "we should not be seeing humongous-size allocations in this path");
+
+  HeapWord* result = survivor_gc_alloc_region(context)->attempt_allocation(word_size,
+                                                                           false /* bot_updates */);
+  if (result == NULL) {
+    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+    result = survivor_gc_alloc_region(context)->attempt_allocation_locked(word_size,
+                                                                          false /* bot_updates */);
+  }
+  if (result != NULL) {
+    _g1h->dirty_young_block(result, word_size);
+  }
+  return result;
+}
+
+HeapWord* G1Allocator::old_attempt_allocation(size_t word_size,
+                                              AllocationContext_t context) {
+  assert(!_g1h->is_humongous(word_size),
+         "we should not be seeing humongous-size allocations in this path");
+
+  HeapWord* result = old_gc_alloc_region(context)->attempt_allocation(word_size,
+                                                                      true /* bot_updates */);
+  if (result == NULL) {
+    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+    result = old_gc_alloc_region(context)->attempt_allocation_locked(word_size,
+                                                                     true /* bot_updates */);
+  }
+  return result;
+}
+
+G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) :
+  _g1h(G1CollectedHeap::heap()),
+  _allocator(allocator),
+  _survivor_alignment_bytes(calc_survivor_alignment_bytes()) {
+}
+
+HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(InCSetState dest,
+                                                       size_t word_sz,
+                                                       AllocationContext_t context) {
   size_t gclab_word_size = _g1h->desired_plab_sz(dest);
   if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
     G1PLAB* alloc_buf = alloc_buffer(dest, context);
     alloc_buf->retire();
 
-    HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context);
+    HeapWord* buf = _allocator->par_allocate_during_gc(dest, gclab_word_size, context);
     if (buf == NULL) {
       return NULL; // Let caller handle allocation failure.
     }
@@ -136,14 +206,18 @@
     assert(obj != NULL, "buffer was definitely big enough...");
     return obj;
   } else {
-    return _g1h->par_allocate_during_gc(dest, word_sz, context);
+    return _allocator->par_allocate_during_gc(dest, word_sz, context);
   }
 }
 
-G1DefaultParGCAllocator::G1DefaultParGCAllocator(G1CollectedHeap* g1h) :
-  G1ParGCAllocator(g1h),
-  _surviving_alloc_buffer(g1h->desired_plab_sz(InCSetState::Young)),
-  _tenured_alloc_buffer(g1h->desired_plab_sz(InCSetState::Old)) {
+void G1PLABAllocator::undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
+  alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
+}
+
+G1DefaultPLABAllocator::G1DefaultPLABAllocator(G1Allocator* allocator) :
+  G1PLABAllocator(allocator),
+  _surviving_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Young)),
+  _tenured_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Old)) {
   for (uint state = 0; state < InCSetState::Num; state++) {
     _alloc_buffers[state] = NULL;
   }
@@ -151,7 +225,7 @@
   _alloc_buffers[InCSetState::Old]  = &_tenured_alloc_buffer;
 }
 
-void G1DefaultParGCAllocator::retire_alloc_buffers() {
+void G1DefaultPLABAllocator::retire_alloc_buffers() {
   for (uint state = 0; state < InCSetState::Num; state++) {
     G1PLAB* const buf = _alloc_buffers[state];
     if (buf != NULL) {
@@ -160,7 +234,7 @@
   }
 }
 
-void G1DefaultParGCAllocator::waste(size_t& wasted, size_t& undo_wasted) {
+void G1DefaultPLABAllocator::waste(size_t& wasted, size_t& undo_wasted) {
   wasted = 0;
   undo_wasted = 0;
   for (uint state = 0; state < InCSetState::Num; state++) {
@@ -190,8 +264,8 @@
   }
   assert(hr->is_empty(), err_msg("expected empty region (index %u)", hr->hrm_index()));
   hr->set_archive();
-  _g1h->_old_set.add(hr);
-  _g1h->_hr_printer.alloc(hr, G1HRPrinter::Archive);
+  _g1h->old_set_add(hr);
+  _g1h->hr_printer()->alloc(hr, G1HRPrinter::Archive);
   _allocated_regions.append(hr);
   _allocation_region = hr;
 
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -33,17 +33,36 @@
 
 class EvacuationInfo;
 
-// Base class for G1 allocators.
+// Interface to keep track of which regions G1 is currently allocating into. Provides
+// some accessors (e.g. allocating into them, or getting their occupancy).
+// Also keeps track of retained regions across GCs.
 class G1Allocator : public CHeapObj<mtGC> {
   friend class VMStructs;
 protected:
   G1CollectedHeap* _g1h;
 
+  virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0;
+
+  // Accessors to the allocation regions.
+  virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0;
+  virtual OldGCAllocRegion* old_gc_alloc_region(AllocationContext_t context) = 0;
+
+  // Allocation attempt during GC for a survivor object / PLAB.
+  inline HeapWord* survivor_attempt_allocation(size_t word_size,
+                                               AllocationContext_t context);
+  // Allocation attempt during GC for an old object / PLAB.
+  inline HeapWord* old_attempt_allocation(size_t word_size,
+                                          AllocationContext_t context);
 public:
   G1Allocator(G1CollectedHeap* heap) : _g1h(heap) { }
+  virtual ~G1Allocator() { }
 
   static G1Allocator* create_allocator(G1CollectedHeap* g1h);
 
+#ifdef ASSERT
+  // Do we currently have an active mutator region to allocate into?
+  bool has_mutator_alloc_region(AllocationContext_t context) { return mutator_alloc_region(context)->get() != NULL; }
+#endif
   virtual void init_mutator_alloc_region() = 0;
   virtual void release_mutator_alloc_region() = 0;
 
@@ -51,24 +70,35 @@
   virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0;
   virtual void abandon_gc_alloc_regions() = 0;
 
-  virtual MutatorAllocRegion*    mutator_alloc_region(AllocationContext_t context) = 0;
-  virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0;
-  virtual OldGCAllocRegion*      old_gc_alloc_region(AllocationContext_t context) = 0;
-  virtual size_t                 used_in_alloc_regions() = 0;
-  virtual bool                   is_retained_old_region(HeapRegion* hr) = 0;
+  // Management of retained regions.
 
-  void                           reuse_retained_old_region(EvacuationInfo& evacuation_info,
-                                                           OldGCAllocRegion* old,
-                                                           HeapRegion** retained);
+  virtual bool is_retained_old_region(HeapRegion* hr) = 0;
+  void reuse_retained_old_region(EvacuationInfo& evacuation_info,
+                                 OldGCAllocRegion* old,
+                                 HeapRegion** retained);
 
-  virtual HeapRegion* new_heap_region(uint hrs_index,
-                                      G1BlockOffsetSharedArray* sharedOffsetArray,
-                                      MemRegion mr) {
-    return new HeapRegion(hrs_index, sharedOffsetArray, mr);
-  }
+  // Allocate blocks of memory during mutator time.
+
+  inline HeapWord* attempt_allocation(size_t word_size, AllocationContext_t context);
+  inline HeapWord* attempt_allocation_locked(size_t word_size, AllocationContext_t context);
+  inline HeapWord* attempt_allocation_force(size_t word_size, AllocationContext_t context);
+
+  size_t unsafe_max_tlab_alloc(AllocationContext_t context);
+
+  // Allocate blocks of memory during garbage collection. Will ensure an
+  // allocation region, either by picking one or expanding the
+  // heap, and then allocate a block of the given size. The block
+  // may not be a humongous - it must fit into a single heap region.
+  HeapWord* par_allocate_during_gc(InCSetState dest,
+                                   size_t word_size,
+                                   AllocationContext_t context);
+
+  virtual size_t used_in_alloc_regions() = 0;
 };
 
-// The default allocator for G1.
+// The default allocation region manager for G1. Provides a single mutator, survivor
+// and old generation allocation region.
+// Can retain the (single) old generation allocation region across GCs.
 class G1DefaultAllocator : public G1Allocator {
 protected:
   // Alloc region used to satisfy mutator allocation requests.
@@ -152,10 +182,14 @@
   }
 };
 
-class G1ParGCAllocator : public CHeapObj<mtGC> {
+// Manages the PLABs used during garbage collection. Interface for allocation from PLABs.
+// Needs to handle multiple contexts, extra alignment in any "survivor" area and some
+// statistics.
+class G1PLABAllocator : public CHeapObj<mtGC> {
   friend class G1ParScanThreadState;
 protected:
   G1CollectedHeap* _g1h;
+  G1Allocator* _allocator;
 
   // The survivor alignment in effect in bytes.
   // == 0 : don't align survivors
@@ -182,11 +216,10 @@
   }
 
 public:
-  G1ParGCAllocator(G1CollectedHeap* g1h) :
-    _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { }
-  virtual ~G1ParGCAllocator() { }
+  G1PLABAllocator(G1Allocator* allocator);
+  virtual ~G1PLABAllocator() { }
 
-  static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h);
+  static G1PLABAllocator* create_allocator(G1Allocator* allocator);
 
   virtual void waste(size_t& wasted, size_t& undo_wasted) = 0;
 
@@ -219,18 +252,18 @@
     return allocate_direct_or_new_plab(dest, word_sz, context);
   }
 
-  void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
-    alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
-  }
+  void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context);
 };
 
-class G1DefaultParGCAllocator : public G1ParGCAllocator {
+// The default PLAB allocator for G1. Keeps the current (single) PLAB for survivor
+// and old generation allocation.
+class G1DefaultPLABAllocator : public G1PLABAllocator {
   G1PLAB  _surviving_alloc_buffer;
   G1PLAB  _tenured_alloc_buffer;
   G1PLAB* _alloc_buffers[InCSetState::Num];
 
 public:
-  G1DefaultParGCAllocator(G1CollectedHeap* g1h);
+  G1DefaultPLABAllocator(G1Allocator* _allocator);
 
   virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) {
     assert(dest.is_valid(),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_G1ALLOCATOR_INLINE_HPP
+#define SHARE_VM_GC_G1_G1ALLOCATOR_INLINE_HPP
+
+#include "gc/g1/g1Allocator.hpp"
+#include "gc/g1/g1AllocRegion.inline.hpp"
+
+HeapWord* G1Allocator::attempt_allocation(size_t word_size, AllocationContext_t context) {
+  return mutator_alloc_region(context)->attempt_allocation(word_size, false /* bot_updates */);
+}
+
+HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size, AllocationContext_t context) {
+  HeapWord* result = mutator_alloc_region(context)->attempt_allocation_locked(word_size, false /* bot_updates */);
+  assert(result != NULL || mutator_alloc_region(context)->get() == NULL,
+         err_msg("Must not have a mutator alloc region if there is no memory, but is " PTR_FORMAT, p2i(mutator_alloc_region(context)->get())));
+  return result;
+}
+
+HeapWord* G1Allocator::attempt_allocation_force(size_t word_size, AllocationContext_t context) {
+  return mutator_alloc_region(context)->attempt_allocation_force(word_size, false /* bot_updates */);
+}
+
+#endif // SHARE_VM_GC_G1_G1ALLOCATOR_HPP
--- a/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -30,6 +30,6 @@
   return new G1DefaultAllocator(g1h);
 }
 
-G1ParGCAllocator* G1ParGCAllocator::create_allocator(G1CollectedHeap* g1h) {
-  return new G1DefaultParGCAllocator(g1h);
+G1PLABAllocator* G1PLABAllocator::create_allocator(G1Allocator* allocator) {
+  return new G1DefaultPLABAllocator(allocator);
 }
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -31,7 +31,7 @@
 #include "gc/g1/concurrentG1Refine.hpp"
 #include "gc/g1/concurrentG1RefineThread.hpp"
 #include "gc/g1/concurrentMarkThread.inline.hpp"
-#include "gc/g1/g1AllocRegion.inline.hpp"
+#include "gc/g1/g1Allocator.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1CollectorState.hpp"
@@ -815,22 +815,16 @@
 
     {
       MutexLockerEx x(Heap_lock);
-      result = _allocator->mutator_alloc_region(context)->attempt_allocation_locked(word_size,
-                                                                                    false /* bot_updates */);
+      result = _allocator->attempt_allocation_locked(word_size, context);
       if (result != NULL) {
         return result;
       }
 
-      // If we reach here, attempt_allocation_locked() above failed to
-      // allocate a new region. So the mutator alloc region should be NULL.
-      assert(_allocator->mutator_alloc_region(context)->get() == NULL, "only way to get here");
-
       if (GC_locker::is_active_and_needs_gc()) {
         if (g1_policy()->can_expand_young_list()) {
           // No need for an ergo verbose message here,
           // can_expand_young_list() does this when it returns true.
-          result = _allocator->mutator_alloc_region(context)->attempt_allocation_force(word_size,
-                                                                                       false /* bot_updates */);
+          result = _allocator->attempt_allocation_force(word_size, context);
           if (result != NULL) {
             return result;
           }
@@ -890,8 +884,7 @@
     // first attempt (without holding the Heap_lock) here and the
     // follow-on attempt will be at the start of the next loop
     // iteration (after taking the Heap_lock).
-    result = _allocator->mutator_alloc_region(context)->attempt_allocation(word_size,
-                                                                           false /* bot_updates */);
+    result = _allocator->attempt_allocation(word_size, context);
     if (result != NULL) {
       return result;
     }
@@ -1109,6 +1102,29 @@
   }
 }
 
+inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
+                                                     uint* gc_count_before_ret,
+                                                     uint* gclocker_retry_count_ret) {
+  assert_heap_not_locked_and_not_at_safepoint();
+  assert(!is_humongous(word_size), "attempt_allocation() should not "
+         "be called for humongous allocation requests");
+
+  AllocationContext_t context = AllocationContext::current();
+  HeapWord* result = _allocator->attempt_allocation(word_size, context);
+
+  if (result == NULL) {
+    result = attempt_allocation_slow(word_size,
+                                     context,
+                                     gc_count_before_ret,
+                                     gclocker_retry_count_ret);
+  }
+  assert_heap_not_locked();
+  if (result != NULL) {
+    dirty_young_block(result, word_size);
+  }
+  return result;
+}
+
 HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
                                                         uint* gc_count_before_ret,
                                                         uint* gclocker_retry_count_ret) {
@@ -1231,13 +1247,11 @@
                                                            AllocationContext_t context,
                                                            bool expect_null_mutator_alloc_region) {
   assert_at_safepoint(true /* should_be_vm_thread */);
-  assert(_allocator->mutator_alloc_region(context)->get() == NULL ||
-                                             !expect_null_mutator_alloc_region,
+  assert(!_allocator->has_mutator_alloc_region(context) || !expect_null_mutator_alloc_region,
          "the current alloc region was unexpectedly found to be non-NULL");
 
   if (!is_humongous(word_size)) {
-    return _allocator->mutator_alloc_region(context)->attempt_allocation_locked(word_size,
-                                                      false /* bot_updates */);
+    return _allocator->attempt_allocation_locked(word_size, context);
   } else {
     HeapWord* result = humongous_obj_allocate(word_size, context);
     if (result != NULL && g1_policy()->need_to_start_conc_mark("STW humongous allocation")) {
@@ -2373,7 +2387,6 @@
   assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!");
 }
 
-
 // Computes the sum of the storage used by the various regions.
 size_t G1CollectedHeap::used() const {
   size_t result = _summary_bytes_used + _allocator->used_in_alloc_regions();
@@ -2632,6 +2645,11 @@
 }
 #endif
 
+bool G1CollectedHeap::obj_in_cs(oop obj) {
+  HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj);
+  return r != NULL && r->in_collection_set();
+}
+
 // Iteration functions.
 
 // Applies an ExtendedOopClosure onto all references of objects within a HeapRegion.
@@ -2833,20 +2851,8 @@
 }
 
 size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const {
-  // Return the remaining space in the cur alloc region, but not less than
-  // the min TLAB size.
-
-  // Also, this value can be at most the humongous object threshold,
-  // since we can't allow tlabs to grow big enough to accommodate
-  // humongous objects.
-
-  HeapRegion* hr = _allocator->mutator_alloc_region(AllocationContext::current())->get();
-  size_t max_tlab = max_tlab_size() * wordSize;
-  if (hr == NULL) {
-    return max_tlab;
-  } else {
-    return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab);
-  }
+  AllocationContext_t context = AllocationContext::current();
+  return _allocator->unsafe_max_tlab_alloc(context);
 }
 
 size_t G1CollectedHeap::max_capacity() const {
@@ -4279,18 +4285,18 @@
   g1_policy()->phase_times()->record_evac_fail_remove_self_forwards((os::elapsedTime() - remove_self_forwards_start) * 1000.0);
 }
 
-void G1CollectedHeap::preserve_mark_during_evac_failure(uint queue_num, oop obj, markOop m) {
+void G1CollectedHeap::preserve_mark_during_evac_failure(uint worker_id, oop obj, markOop m) {
   if (!_evacuation_failed) {
     _evacuation_failed = true;
   }
 
-  _evacuation_failed_info_array[queue_num].register_copy_failure(obj->size());
+  _evacuation_failed_info_array[worker_id].register_copy_failure(obj->size());
 
   // We want to call the "for_promotion_failure" version only in the
   // case of a promotion failure.
   if (m->must_be_preserved_for_promotion_failure(obj)) {
     OopAndMarkOop elem(obj, m);
-    _preserved_objs[queue_num].push(elem);
+    _preserved_objs[worker_id].push(elem);
   }
 }
 
@@ -4334,7 +4340,7 @@
 
   oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
 
-  assert(_worker_id == _par_scan_state->queue_num(), "sanity");
+  assert(_worker_id == _par_scan_state->worker_id(), "sanity");
 
   const InCSetState state = _g1->in_cset_state(obj);
   if (state.is_in_cset()) {
@@ -4443,9 +4449,6 @@
   ParallelTaskTerminator _terminator;
   uint _n_workers;
 
-  Mutex _stats_lock;
-  Mutex* stats_lock() { return &_stats_lock; }
-
 public:
   G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
     : AbstractGangTask("G1 collection"),
@@ -4453,8 +4456,7 @@
       _queues(task_queues),
       _root_processor(root_processor),
       _terminator(n_workers, _queues),
-      _n_workers(n_workers),
-      _stats_lock(Mutex::leaf, "parallel G1 stats lock", true)
+      _n_workers(n_workers)
   {}
 
   RefToScanQueueSet* queues() { return _queues; }
@@ -4581,8 +4583,8 @@
       _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
 
       if (PrintTerminationStats) {
-        MutexLocker x(stats_lock());
-        pss.print_termination_stats(worker_id);
+        MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
+        pss.print_termination_stats();
       }
 
       assert(pss.queue_is_empty(), "should be empty");
@@ -5009,7 +5011,7 @@
 bool G1STWIsAliveClosure::do_object_b(oop p) {
   // An object is reachable if it is outside the collection set,
   // or is inside and copied.
-  return !_g1->obj_in_cs(p) || p->is_forwarded();
+  return !_g1->is_in_cset(p) || p->is_forwarded();
 }
 
 // Non Copying Keep Alive closure
@@ -5498,7 +5500,9 @@
     }
 
     // The individual threads will set their evac-failure closures.
-    if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr();
+    if (PrintTerminationStats) {
+      G1ParScanThreadState::print_termination_stats_hdr();
+    }
 
     workers()->run_task(&g1_par_task);
     end_par_time_sec = os::elapsedTime();
@@ -6491,7 +6495,6 @@
   return NULL;
 }
 
-
 // Heap region set verification
 
 class VerifyRegionListsClosure : public HeapRegionClosure {
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -27,7 +27,6 @@
 
 #include "gc/g1/concurrentMark.hpp"
 #include "gc/g1/evacuationInfo.hpp"
-#include "gc/g1/g1AllocRegion.hpp"
 #include "gc/g1/g1AllocationContext.hpp"
 #include "gc/g1/g1Allocator.hpp"
 #include "gc/g1/g1BiasedArray.hpp"
@@ -187,13 +186,11 @@
   friend class MutatorAllocRegion;
   friend class SurvivorGCAllocRegion;
   friend class OldGCAllocRegion;
-  friend class G1Allocator;
-  friend class G1ArchiveAllocator;
 
   // Closures used in implementation.
   friend class G1ParScanThreadState;
   friend class G1ParTask;
-  friend class G1ParGCAllocator;
+  friend class G1PLABAllocator;
   friend class G1PrepareCompactClosure;
 
   // Other related classes.
@@ -248,7 +245,7 @@
   // The sequence of all heap regions in the heap.
   HeapRegionManager _hrm;
 
-  // Class that handles the different kinds of allocations.
+  // Handles non-humongous allocations in the G1CollectedHeap.
   G1Allocator* _allocator;
 
   // Outside of GC pauses, the number of bytes used in all regions other
@@ -280,22 +277,6 @@
   // start of each GC.
   bool _expand_heap_after_alloc_failure;
 
-  // It resets the mutator alloc region before new allocations can take place.
-  void init_mutator_alloc_region();
-
-  // It releases the mutator alloc region.
-  void release_mutator_alloc_region();
-
-  // It initializes the GC alloc regions at the start of a GC.
-  void init_gc_alloc_regions(EvacuationInfo& evacuation_info);
-
-  // It releases the GC alloc regions at the end of a GC.
-  void release_gc_alloc_regions(EvacuationInfo& evacuation_info);
-
-  // It does any cleanup that needs to be done on the GC alloc regions
-  // before a Full GC.
-  void abandon_gc_alloc_regions();
-
   // Helper for monitoring and management support.
   G1MonitoringSupport* _g1mm;
 
@@ -551,31 +532,6 @@
                                             AllocationContext_t context,
                                             bool expect_null_mutator_alloc_region);
 
-  // It dirties the cards that cover the block so that so that the post
-  // write barrier never queues anything when updating objects on this
-  // block. It is assumed (and in fact we assert) that the block
-  // belongs to a young region.
-  inline void dirty_young_block(HeapWord* start, size_t word_size);
-
-  // Allocate blocks during garbage collection. Will ensure an
-  // allocation region, either by picking one or expanding the
-  // heap, and then allocate a block of the given size. The block
-  // may not be a humongous - it must fit into a single heap region.
-  inline HeapWord* par_allocate_during_gc(InCSetState dest,
-                                          size_t word_size,
-                                          AllocationContext_t context);
-  // Ensure that no further allocations can happen in "r", bearing in mind
-  // that parallel threads might be attempting allocations.
-  void par_allocate_remaining_space(HeapRegion* r);
-
-  // Allocation attempt during GC for a survivor object / PLAB.
-  inline HeapWord* survivor_attempt_allocation(size_t word_size,
-                                               AllocationContext_t context);
-
-  // Allocation attempt during GC for an old object / PLAB.
-  inline HeapWord* old_attempt_allocation(size_t word_size,
-                                          AllocationContext_t context);
-
   // These methods are the "callbacks" from the G1AllocRegion class.
 
   // For mutator alloc regions.
@@ -589,10 +545,6 @@
   void retire_gc_alloc_region(HeapRegion* alloc_region,
                               size_t allocated_bytes, InCSetState dest);
 
-  // Allocate the highest free region in the reserved heap. This will commit
-  // regions as necessary.
-  HeapRegion* alloc_highest_free_region();
-
   // - if explicit_gc is true, the GC is for a System.gc() or a heap
   //   inspection request and should collect the entire heap
   // - if clear_all_soft_refs is true, all soft references should be
@@ -725,6 +677,13 @@
 
   G1HRPrinter* hr_printer() { return &_hr_printer; }
 
+  // Allocates a new heap region instance.
+  HeapRegion* new_heap_region(uint hrs_index, MemRegion mr);
+
+  // Allocate the highest free region in the reserved heap. This will commit
+  // regions as necessary.
+  HeapRegion* alloc_highest_free_region();
+
   // Frees a non-humongous region by initializing its contents and
   // adding it to the free list that's passed as a parameter (this is
   // usually a local list which will be appended to the master free
@@ -738,6 +697,12 @@
                    bool par,
                    bool locked = false);
 
+  // It dirties the cards that cover the block so that the post
+  // write barrier never queues anything when updating objects on this
+  // block. It is assumed (and in fact we assert) that the block
+  // belongs to a young region.
+  inline void dirty_young_block(HeapWord* start, size_t word_size);
+
   // Frees a humongous region by collapsing it into individual regions
   // and calling free_region() for each of them. The freed regions
   // will be added to the free list that's passed as a parameter (this
@@ -887,7 +852,7 @@
 
   // Preserve the mark of "obj", if necessary, in preparation for its mark
   // word being overwritten with a self-forwarding-pointer.
-  void preserve_mark_during_evac_failure(uint queue, oop obj, markOop m);
+  void preserve_mark_during_evac_failure(uint worker_id, oop obj, markOop m);
 
 #ifndef PRODUCT
   // Support for forcing evacuation failures. Analogous to
@@ -1216,6 +1181,7 @@
     }
   }
 
+  inline void old_set_add(HeapRegion* hr);
   inline void old_set_remove(HeapRegion* hr);
 
   size_t non_young_capacity_bytes() {
@@ -1263,7 +1229,7 @@
 
   // Return "TRUE" iff the given object address is within the collection
   // set. Slow implementation.
-  inline bool obj_in_cs(oop obj);
+  bool obj_in_cs(oop obj);
 
   inline bool is_in_cset(const HeapRegion *hr);
   inline bool is_in_cset(oop obj);
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -26,7 +26,6 @@
 #define SHARE_VM_GC_G1_G1COLLECTEDHEAP_INLINE_HPP
 
 #include "gc/g1/concurrentMark.hpp"
-#include "gc/g1/g1AllocRegion.inline.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/g1/g1CollectorState.hpp"
@@ -57,20 +56,6 @@
   return MIN2(_humongous_object_threshold_in_words, gclab_word_size);
 }
 
-HeapWord* G1CollectedHeap::par_allocate_during_gc(InCSetState dest,
-                                                  size_t word_size,
-                                                  AllocationContext_t context) {
-  switch (dest.value()) {
-    case InCSetState::Young:
-      return survivor_attempt_allocation(word_size, context);
-    case InCSetState::Old:
-      return old_attempt_allocation(word_size, context);
-    default:
-      ShouldNotReachHere();
-      return NULL; // Keep some compilers happy
-  }
-}
-
 // Inline functions for G1CollectedHeap
 
 inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() {
@@ -122,71 +107,14 @@
   OrderAccess::fence();
 }
 
+inline void G1CollectedHeap::old_set_add(HeapRegion* hr) {
+  _old_set.add(hr);
+}
+
 inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
   _old_set.remove(hr);
 }
 
-inline bool G1CollectedHeap::obj_in_cs(oop obj) {
-  HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj);
-  return r != NULL && r->in_collection_set();
-}
-
-inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
-                                                     uint* gc_count_before_ret,
-                                                     uint* gclocker_retry_count_ret) {
-  assert_heap_not_locked_and_not_at_safepoint();
-  assert(!is_humongous(word_size), "attempt_allocation() should not "
-         "be called for humongous allocation requests");
-
-  AllocationContext_t context = AllocationContext::current();
-  HeapWord* result = _allocator->mutator_alloc_region(context)->attempt_allocation(word_size,
-                                                                                   false /* bot_updates */);
-  if (result == NULL) {
-    result = attempt_allocation_slow(word_size,
-                                     context,
-                                     gc_count_before_ret,
-                                     gclocker_retry_count_ret);
-  }
-  assert_heap_not_locked();
-  if (result != NULL) {
-    dirty_young_block(result, word_size);
-  }
-  return result;
-}
-
-inline HeapWord* G1CollectedHeap::survivor_attempt_allocation(size_t word_size,
-                                                              AllocationContext_t context) {
-  assert(!is_humongous(word_size),
-         "we should not be seeing humongous-size allocations in this path");
-
-  HeapWord* result = _allocator->survivor_gc_alloc_region(context)->attempt_allocation(word_size,
-                                                                                       false /* bot_updates */);
-  if (result == NULL) {
-    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
-    result = _allocator->survivor_gc_alloc_region(context)->attempt_allocation_locked(word_size,
-                                                                                      false /* bot_updates */);
-  }
-  if (result != NULL) {
-    dirty_young_block(result, word_size);
-  }
-  return result;
-}
-
-inline HeapWord* G1CollectedHeap::old_attempt_allocation(size_t word_size,
-                                                         AllocationContext_t context) {
-  assert(!is_humongous(word_size),
-         "we should not be seeing humongous-size allocations in this path");
-
-  HeapWord* result = _allocator->old_gc_alloc_region(context)->attempt_allocation(word_size,
-                                                                                  true /* bot_updates */);
-  if (result == NULL) {
-    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
-    result = _allocator->old_gc_alloc_region(context)->attempt_allocation_locked(word_size,
-                                                                                 true /* bot_updates */);
-  }
-  return result;
-}
-
 // It dirties the cards that cover the block so that so that the post
 // write barrier never queues anything when updating objects on this
 // block. It is assumed (and in fact we assert) that the block
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
 
 bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts,
                                                     jlong* totals,
@@ -31,3 +32,8 @@
                                                     jint len) {
   return false;
 }
+
+HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
+                                             MemRegion mr) {
+  return new HeapRegion(hrs_index, bot_shared(), mr);
+}
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -31,6 +31,7 @@
 #include "gc/g1/g1ErgoVerbose.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1Log.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
 #include "runtime/arguments.hpp"
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -48,7 +48,7 @@
   assert(par_scan_state != NULL, "Must set par_scan_state to non-NULL.");
 
   _par_scan_state = par_scan_state;
-  _worker_id = par_scan_state->queue_num();
+  _worker_id = par_scan_state->worker_id();
 
   assert(_worker_id < ParallelGCThreads,
          err_msg("The given worker id %u must be less than the number of threads %u", _worker_id, ParallelGCThreads));
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -31,6 +31,7 @@
 #include "gc/g1/g1ParScanThreadState.inline.hpp"
 #include "gc/g1/g1RemSet.hpp"
 #include "gc/g1/g1RemSet.inline.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "memory/iterator.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -31,13 +31,13 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
 
-G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
+G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp)
   : _g1h(g1h),
-    _refs(g1h->task_queue(queue_num)),
+    _refs(g1h->task_queue(worker_id)),
     _dcq(&g1h->dirty_card_queue_set()),
     _ct_bs(g1h->g1_barrier_set()),
     _g1_rem(g1h->g1_rem_set()),
-    _hash_seed(17), _queue_num(queue_num),
+    _hash_seed(17), _worker_id(worker_id),
     _term_attempts(0),
     _tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
     _age_table(false), _scanner(g1h, rp),
@@ -59,7 +59,7 @@
   _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
   memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
 
-  _g1_par_allocator = G1ParGCAllocator::create_allocator(_g1h);
+  _plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
 
   _dest[InCSetState::NotInCSet]    = InCSetState::NotInCSet;
   // The dest for Young is used when the objects are aged enough to
@@ -71,37 +71,29 @@
 }
 
 G1ParScanThreadState::~G1ParScanThreadState() {
-  _g1_par_allocator->retire_alloc_buffers();
-  delete _g1_par_allocator;
+  _plab_allocator->retire_alloc_buffers();
+  delete _plab_allocator;
   FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
 }
 
-void
-G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st)
-{
+void G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) {
   st->print_raw_cr("GC Termination Stats");
-  st->print_raw_cr("     elapsed  --strong roots-- -------termination-------"
-                   " ------waste (KiB)------");
-  st->print_raw_cr("thr     ms        ms      %        ms      %    attempts"
-                   "  total   alloc    undo");
-  st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"
-                   " ------- ------- -------");
+  st->print_raw_cr("     elapsed  --strong roots-- -------termination------- ------waste (KiB)------");
+  st->print_raw_cr("thr     ms        ms      %        ms      %    attempts  total   alloc    undo");
+  st->print_raw_cr("--- --------- --------- ------ --------- ------ -------- ------- ------- -------");
 }
 
-void
-G1ParScanThreadState::print_termination_stats(int i,
-                                              outputStream* const st) const
-{
+void G1ParScanThreadState::print_termination_stats(outputStream* const st) const {
   const double elapsed_ms = elapsed_time() * 1000.0;
   const double s_roots_ms = strong_roots_time() * 1000.0;
   const double term_ms    = term_time() * 1000.0;
   size_t alloc_buffer_waste = 0;
   size_t undo_waste = 0;
-  _g1_par_allocator->waste(alloc_buffer_waste, undo_waste);
-  st->print_cr("%3d %9.2f %9.2f %6.2f "
+  _plab_allocator->waste(alloc_buffer_waste, undo_waste);
+  st->print_cr("%3u %9.2f %9.2f %6.2f "
                "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
                SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
-               i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
+               _worker_id, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
                term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
                (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
                alloc_buffer_waste * HeapWordSize / K,
@@ -167,8 +159,9 @@
   // Right now we only have two types of regions (young / old) so
   // let's keep the logic here simple. We can generalize it when necessary.
   if (dest->is_young()) {
-    HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old,
-                                                          word_sz, context);
+    HeapWord* const obj_ptr = _plab_allocator->allocate(InCSetState::Old,
+                                                        word_sz,
+                                                        context);
     if (obj_ptr == NULL) {
       return NULL;
     }
@@ -209,12 +202,12 @@
 
   uint age = 0;
   InCSetState dest_state = next_state(state, old_mark, age);
-  HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context);
+  HeapWord* obj_ptr = _plab_allocator->plab_allocate(dest_state, word_sz, context);
 
   // PLAB allocations should succeed most of the time, so we'll
   // normally check against NULL once and that's it.
   if (obj_ptr == NULL) {
-    obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
+    obj_ptr = _plab_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
     if (obj_ptr == NULL) {
       obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context);
       if (obj_ptr == NULL) {
@@ -233,7 +226,7 @@
   if (_g1h->evacuation_should_fail()) {
     // Doing this after all the allocation attempts also tests the
     // undo_allocation() method too.
-    _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
+    _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
     return handle_evacuation_failure_par(old, old_mark);
   }
 #endif // !PRODUCT
@@ -274,7 +267,7 @@
              "sanity");
       G1StringDedup::enqueue_from_evacuation(is_from_young,
                                              is_to_young,
-                                             queue_num(),
+                                             _worker_id,
                                              obj);
     }
 
@@ -295,7 +288,7 @@
     }
     return obj;
   } else {
-    _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
+    _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context);
     return forward_ptr;
   }
 }
@@ -314,7 +307,7 @@
      _g1h->hr_printer()->evac_failure(r);
     }
 
-    _g1h->preserve_mark_during_evac_failure(_queue_num, old, m);
+    _g1h->preserve_mark_during_evac_failure(_worker_id, old, m);
 
     _scanner.set_region(r);
     old->oop_iterate_backwards(&_scanner);
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -46,7 +46,7 @@
   G1SATBCardTableModRefBS* _ct_bs;
   G1RemSet* _g1_rem;
 
-  G1ParGCAllocator* _g1_par_allocator;
+  G1PLABAllocator*  _plab_allocator;
 
   ageTable          _age_table;
   InCSetState       _dest[InCSetState::Num];
@@ -55,7 +55,7 @@
   G1ParScanClosure  _scanner;
 
   int  _hash_seed;
-  uint _queue_num;
+  uint _worker_id;
 
   size_t _term_attempts;
 
@@ -85,7 +85,7 @@
   }
 
  public:
-  G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
+  G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp);
   ~G1ParScanThreadState();
 
   ageTable*         age_table()       { return &_age_table;       }
@@ -112,8 +112,7 @@
     }
   }
 
-  int* hash_seed() { return &_hash_seed; }
-  uint queue_num() { return _queue_num; }
+  uint worker_id() { return _worker_id; }
 
   size_t term_attempts() const  { return _term_attempts; }
   void note_term_attempt() { _term_attempts++; }
@@ -139,8 +138,11 @@
     return os::elapsedTime() - _start;
   }
 
+  // Print the header for the per-thread termination statistics.
   static void print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
-  void print_termination_stats(int i, outputStream* const st = gclog_or_tty) const;
+
+  // Print actual per-thread termination statistics.
+  void print_termination_stats(outputStream* const st = gclog_or_tty) const;
 
   size_t* surviving_young_words() {
     // We add on to hide entry 0 which accumulates surviving words for
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -56,7 +56,7 @@
   }
 
   assert(obj != NULL, "Must be");
-  update_rs(from, p, queue_num());
+  update_rs(from, p, _worker_id);
 }
 
 template <class T> inline void G1ParScanThreadState::push_on_queue(T* ref) {
@@ -136,7 +136,7 @@
 
 void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) {
   StarTask stolen_task;
-  while (task_queues->steal(queue_num(), hash_seed(), stolen_task)) {
+  while (task_queues->steal(_worker_id, &_hash_seed, stolen_task)) {
     assert(verify_task(stolen_task), "sanity");
     dispatch_reference(stolen_task);
 
--- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -34,6 +34,7 @@
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1RemSet.inline.hpp"
 #include "gc/g1/g1RootProcessor.hpp"
+#include "gc/g1/heapRegion.inline.hpp"
 #include "memory/allocation.inline.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/mutex.hpp"
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -497,20 +497,10 @@
     return _rem_set;
   }
 
-  bool in_collection_set() const;
+  inline bool in_collection_set() const;
 
-  HeapRegion* next_in_collection_set() {
-    assert(in_collection_set(), "should only invoke on member of CS.");
-    assert(_next_in_special_set == NULL ||
-           _next_in_special_set->in_collection_set(),
-           "Malformed CS.");
-    return _next_in_special_set;
-  }
-  void set_next_in_collection_set(HeapRegion* r) {
-    assert(in_collection_set(), "should only invoke on member of CS.");
-    assert(r == NULL || r->in_collection_set(), "Malformed CS.");
-    _next_in_special_set = r;
-  }
+  inline HeapRegion* next_in_collection_set() const;
+  inline void set_next_in_collection_set(HeapRegion* r);
 
   void set_allocation_context(AllocationContext_t context) {
     _allocation_context = context;
--- a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -26,7 +26,7 @@
 #define SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP
 
 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
-#include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/shared/space.hpp"
 #include "oops/oop.inline.hpp"
@@ -200,4 +200,18 @@
   return G1CollectedHeap::heap()->is_in_cset(this);
 }
 
+inline HeapRegion* HeapRegion::next_in_collection_set() const {
+  assert(in_collection_set(), "should only invoke on member of CS.");
+  assert(_next_in_special_set == NULL ||
+         _next_in_special_set->in_collection_set(),
+         "Malformed CS.");
+  return _next_in_special_set;
+}
+
+void HeapRegion::set_next_in_collection_set(HeapRegion* r) {
+  assert(in_collection_set(), "should only invoke on member of CS.");
+  assert(r == NULL || r->in_collection_set(), "Malformed CS.");
+  _next_in_special_set = r;
+}
+
 #endif // SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -70,7 +70,7 @@
   HeapWord* bottom = g1h->bottom_addr_for_region(hrm_index);
   MemRegion mr(bottom, bottom + HeapRegion::GrainWords);
   assert(reserved().contains(mr), "invariant");
-  return g1h->allocator()->new_heap_region(hrm_index, g1h->bot_shared(), mr);
+  return g1h->new_heap_region(hrm_index, mr);
 }
 
 void HeapRegionManager::commit_regions(uint index, size_t num_regions) {
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -94,8 +94,9 @@
 
   if (_word_size > 0) {
     // An allocation has been requested. So, try to do that first.
-    _result = g1h->attempt_allocation_at_safepoint(_word_size, allocation_context(),
-                                     false /* expect_null_cur_alloc_region */);
+    _result = g1h->attempt_allocation_at_safepoint(_word_size,
+                                                   allocation_context(),
+                                                   false /* expect_null_cur_alloc_region */);
     if (_result != NULL) {
       // If we can successfully allocate before we actually do the
       // pause then we will consider this pause successful.
@@ -147,8 +148,9 @@
     g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
   if (_pause_succeeded && _word_size > 0) {
     // An allocation had been requested.
-    _result = g1h->attempt_allocation_at_safepoint(_word_size, allocation_context(),
-                                      true /* expect_null_cur_alloc_region */);
+    _result = g1h->attempt_allocation_at_safepoint(_word_size,
+                                                   allocation_context(),
+                                                   true /* expect_null_cur_alloc_region */);
   } else {
     assert(_result == NULL, "invariant");
     if (!_pause_succeeded) {
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1303,7 +1303,7 @@
   if (handler_index < 0) {
     if (PrintSignatureHandlers && (handler != Interpreter::slow_signature_handler())) {
       tty->cr();
-      tty->print_cr("argument handler #%d at "PTR_FORMAT" for fingerprint " UINT64_FORMAT,
+      tty->print_cr("argument handler #%d at " PTR_FORMAT " for fingerprint " UINT64_FORMAT,
                     _handlers->length(),
                     handler,
                     fingerprint);
@@ -1313,7 +1313,7 @@
   } else {
     if (PrintSignatureHandlers) {
       tty->cr();
-      tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: "PTR_FORMAT", new : "PTR_FORMAT")",
+      tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: " PTR_FORMAT ", new : " PTR_FORMAT ")",
                     _handlers->length(),
                     fingerprint,
                     _handlers->at(handler_index),
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -379,7 +379,8 @@
   if (!resolved_method->is_abstract() &&
     (InstanceKlass::cast(klass())->default_methods() != NULL)) {
     int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(),
-                                                 name, signature, Klass::find_overpass, Klass::find_static);
+                                                 name, signature, Klass::find_overpass,
+                                                 Klass::find_static, Klass::find_private);
     if (index >= 0 ) {
       vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
     }
@@ -1189,7 +1190,7 @@
   assert(resolved_method->method_holder()->is_linked(), "must be linked");
 
   // do lookup based on receiver klass using the vtable index
-  if (resolved_method->method_holder()->is_interface()) { // miranda method
+  if (resolved_method->method_holder()->is_interface()) { // default or miranda method
     vtable_index = vtable_index_of_interface_method(resolved_klass,
                            resolved_method);
     assert(vtable_index >= 0 , "we should have valid vtable index at this point");
@@ -1198,7 +1199,7 @@
     selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
   } else {
     // at this point we are sure that resolved_method is virtual and not
-    // a miranda method; therefore, it must have a valid vtable index.
+    // a default or miranda method; therefore, it must have a valid vtable index.
     assert(!resolved_method->has_itable_index(), "");
     vtable_index = resolved_method->vtable_index();
     // We could get a negative vtable_index for final methods,
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1381,12 +1381,14 @@
 
 // find_method looks up the name/signature in the local methods array
 Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
-  return find_method_impl(name, signature, find_overpass, find_static);
+  return find_method_impl(name, signature, find_overpass, find_static, find_private);
 }
 
 Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature,
-                                        OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const {
-  return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode);
+                                        OverpassLookupMode overpass_mode,
+                                        StaticLookupMode static_mode,
+                                        PrivateLookupMode private_mode) const {
+  return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode);
 }
 
 // find_instance_method looks up the name/signature in the local methods array
@@ -1394,7 +1396,7 @@
 Method* InstanceKlass::find_instance_method(
     Array<Method*>* methods, Symbol* name, Symbol* signature) {
   Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
-                                                 find_overpass, skip_static);
+                                                 find_overpass, skip_static, find_private);
   assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
   return meth;
 }
@@ -1405,22 +1407,51 @@
     return InstanceKlass::find_instance_method(methods(), name, signature);
 }
 
+// Find looks up the name/signature in the local methods array
+// and filters on the overpass, static and private flags
+// This returns the first one found
+// note that the local methods array can have up to one overpass, one static
+// and one instance (private or not) with the same name/signature
+Method* InstanceKlass::find_local_method(Symbol* name, Symbol* signature,
+                                        OverpassLookupMode overpass_mode,
+                                        StaticLookupMode static_mode,
+                                        PrivateLookupMode private_mode) const {
+  return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode);
+}
+
+// Find looks up the name/signature in the local methods array
+// and filters on the overpass, static and private flags
+// This returns the first one found
+// note that the local methods array can have up to one overpass, one static
+// and one instance (private or not) with the same name/signature
+Method* InstanceKlass::find_local_method(Array<Method*>* methods,
+                                        Symbol* name, Symbol* signature,
+                                        OverpassLookupMode overpass_mode,
+                                        StaticLookupMode static_mode,
+                                        PrivateLookupMode private_mode) {
+  return InstanceKlass::find_method_impl(methods, name, signature, overpass_mode, static_mode, private_mode);
+}
+
+
 // find_method looks up the name/signature in the local methods array
 Method* InstanceKlass::find_method(
     Array<Method*>* methods, Symbol* name, Symbol* signature) {
-  return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static);
+  return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static, find_private);
 }
 
 Method* InstanceKlass::find_method_impl(
-    Array<Method*>* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) {
-  int hit = find_method_index(methods, name, signature, overpass_mode, static_mode);
+    Array<Method*>* methods, Symbol* name, Symbol* signature,
+    OverpassLookupMode overpass_mode, StaticLookupMode static_mode,
+    PrivateLookupMode private_mode) {
+  int hit = find_method_index(methods, name, signature, overpass_mode, static_mode, private_mode);
   return hit >= 0 ? methods->at(hit): NULL;
 }
 
-bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) {
-    return (m->signature() == signature) &&
+bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private) {
+    return  ((m->signature() == signature) &&
             (!skipping_overpass || !m->is_overpass()) &&
-            (!skipping_static || !m->is_static());
+            (!skipping_static || !m->is_static()) &&
+            (!skipping_private || !m->is_private()));
 }
 
 // Used directly for default_methods to find the index into the
@@ -1430,17 +1461,25 @@
 // the search continues to find a potential non-overpass match.  This capability
 // is important during method resolution to prefer a static method, for example,
 // over an overpass method.
+// There is the possibility in any _method's array to have the same name/signature
+// for a static method, an overpass method and a local instance method
+// To correctly catch a given method, the search criteria may need
+// to explicitly skip the other two. For local instance methods, it
+// is often necessary to skip private methods
 int InstanceKlass::find_method_index(
-    Array<Method*>* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) {
+    Array<Method*>* methods, Symbol* name, Symbol* signature,
+    OverpassLookupMode overpass_mode, StaticLookupMode static_mode,
+    PrivateLookupMode private_mode) {
   bool skipping_overpass = (overpass_mode == skip_overpass);
   bool skipping_static = (static_mode == skip_static);
+  bool skipping_private = (private_mode == skip_private);
   int hit = binary_search(methods, name);
   if (hit != -1) {
     Method* m = methods->at(hit);
 
     // Do linear search to find matching signature.  First, quick check
     // for common case, ignoring overpasses if requested.
-    if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit;
+    if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return hit;
 
     // search downwards through overloaded methods
     int i;
@@ -1448,18 +1487,18 @@
         Method* m = methods->at(i);
         assert(m->is_method(), "must be method");
         if (m->name() != name) break;
-        if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
+        if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i;
     }
     // search upwards
     for (i = hit + 1; i < methods->length(); ++i) {
         Method* m = methods->at(i);
         assert(m->is_method(), "must be method");
         if (m->name() != name) break;
-        if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
+        if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i;
     }
     // not found
 #ifdef ASSERT
-    int index = (skipping_overpass || skipping_static) ? -1 : linear_search(methods, name, signature);
+    int index = (skipping_overpass || skipping_static || skipping_private) ? -1 : linear_search(methods, name, signature);
     assert(index == -1, err_msg("binary search should have found entry %d", index));
 #endif
   }
@@ -1489,7 +1528,7 @@
   OverpassLookupMode overpass_local_mode = overpass_mode;
   Klass* klass = const_cast<InstanceKlass*>(this);
   while (klass != NULL) {
-    Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static);
+    Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static, find_private);
     if (method != NULL) {
       return method;
     }
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -503,12 +503,28 @@
   Method* find_instance_method(Symbol* name, Symbol* signature);
   static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
 
+  // find a local method (returns NULL if not found)
+  Method* find_local_method(Symbol* name, Symbol* signature,
+                           OverpassLookupMode overpass_mode,
+                           StaticLookupMode static_mode,
+                           PrivateLookupMode private_mode) const;
+
+  // find a local method from given methods array (returns NULL if not found)
+  static Method* find_local_method(Array<Method*>* methods,
+                           Symbol* name, Symbol* signature,
+                           OverpassLookupMode overpass_mode,
+                           StaticLookupMode static_mode,
+                           PrivateLookupMode private_mode);
+
   // true if method matches signature and conforms to skipping_X conditions.
-  static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static);
+  static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private);
 
-  // find a local method index in default_methods (returns -1 if not found)
-  static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature,
-                               OverpassLookupMode overpass_mode, StaticLookupMode static_mode);
+  // find a local method index in methods or default_methods (returns -1 if not found)
+  static int find_method_index(Array<Method*>* methods,
+                               Symbol* name, Symbol* signature,
+                               OverpassLookupMode overpass_mode,
+                               StaticLookupMode static_mode,
+                               PrivateLookupMode private_mode);
 
   // lookup operation (returns NULL if not found)
   Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
@@ -1153,9 +1169,14 @@
 
   // find a local method (returns NULL if not found)
   Method* find_method_impl(Symbol* name, Symbol* signature,
-                           OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const;
-  static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature,
-                                  OverpassLookupMode overpass_mode, StaticLookupMode static_mode);
+                           OverpassLookupMode overpass_mode,
+                           StaticLookupMode static_mode,
+                           PrivateLookupMode private_mode) const;
+  static Method* find_method_impl(Array<Method*>* methods,
+                                  Symbol* name, Symbol* signature,
+                                  OverpassLookupMode overpass_mode,
+                                  StaticLookupMode static_mode,
+                                  PrivateLookupMode private_mode);
 
   // Free CHeap allocated fields.
   void release_C_heap_structures();
--- a/hotspot/src/share/vm/oops/klass.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -161,6 +161,7 @@
   enum DefaultsLookupMode { find_defaults, skip_defaults };
   enum OverpassLookupMode { find_overpass, skip_overpass };
   enum StaticLookupMode   { find_static,   skip_static };
+  enum PrivateLookupMode  { find_private,  skip_private };
 
   bool is_klass() const volatile { return true; }
 
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -683,7 +683,6 @@
   if (mhk->is_interface()) {
     assert(m->is_public(), "should be public");
     assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
-    // the search could find a miranda or a default method
     if (is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super())) {
       return true;
     }
@@ -691,25 +690,57 @@
   return false;
 }
 
-// check if a method is a miranda method, given a class's methods table,
-// its default_method table  and its super
-// Miranda methods are calculated twice:
-// first: before vtable size calculation: including abstract and superinterface default
+// Check if a method is a miranda method, given a class's methods array,
+// its default_method table and its super class.
+// "Miranda" means an abstract non-private method that would not be
+// overridden for the local class.
+// A "miranda" method should only include non-private interface
+// instance methods, i.e. not private methods, not static methods,
+// not default methods (concrete interface methods), not overpass methods.
+// If a given class already has a local (including overpass) method, a
+// default method, or any of its superclasses has the same which would have
+// overridden an abstract method, then this is not a miranda method.
+//
+// Miranda methods are checked multiple times.
+// Pass 1: during class load/class file parsing: before vtable size calculation:
+// include superinterface abstract and default methods (non-private instance).
 // We include potential default methods to give them space in the vtable.
-// During the first run, the default_methods list is empty
-// This is seen by default method creation
-// Second: recalculated during vtable initialization: only include abstract methods.
+// During the first run, the current instanceKlass has not yet been
+// created, the superclasses and superinterfaces do have instanceKlasses
+// but may not have vtables, the default_methods list is empty, no overpasses.
+// This is seen by default method creation.
+//
+// Pass 2: recalculated during vtable initialization: only include abstract methods.
+// The goal of pass 2 is to walk through the superinterfaces to see if any of
+// the superinterface methods (which were all abstract pre-default methods)
+// need to be added to the vtable.
+// With the addition of default methods, we have three new challenges:
+// overpasses, static interface methods and private interface methods.
+// Static and private interface methods do not get added to the vtable and
+// are not seen by the method resolution process, so we skip those.
+// Overpass methods are already in the vtable, so vtable lookup will
+// find them and we don't need to add a miranda method to the end of
+// the vtable. So we look for overpass methods and if they are found we
+// return false. Note that we inherit our superclasses vtable, so
+// the superclass' search also needs to use find_overpass so that if
+// one is found we return false.
+// False means - we don't need a miranda method added to the vtable.
+//
 // During the second run, default_methods is set up, so concrete methods from
 // superinterfaces with matching names/signatures to default_methods are already
 // in the default_methods list and do not need to be appended to the vtable
-// as mirandas
-// This is seen by link resolution and selection.
-// "miranda" means not static, not defined by this class.
-// private methods in interfaces do not belong in the miranda list.
-// the caller must make sure that the method belongs to an interface implemented by the class
-// Miranda methods only include public interface instance methods
-// Not private methods, not static methods, not default == concrete abstract
-// Miranda methods also do not include overpass methods in interfaces
+// as mirandas. Abstract methods may already have been handled via
+// overpasses - either local or superclass overpasses, which may be
+// in the vtable already.
+//
+// Pass 3: They are also checked by link resolution and selection,
+// for invocation on a method (not interface method) reference that
+// resolves to a method with an interface as its method_holder.
+// Used as part of walking from the bottom of the vtable to find
+// the vtable index for the miranda method.
+//
+// Part of the Miranda Rights in the US mean that if you do not have
+// an attorney one will be appointed for you.
 bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
                              Array<Method*>* default_methods, Klass* super) {
   if (m->is_static() || m->is_private() || m->is_overpass()) {
@@ -717,44 +748,36 @@
   }
   Symbol* name = m->name();
   Symbol* signature = m->signature();
-  Method* mo;
 
-  if ((mo = InstanceKlass::find_instance_method(class_methods, name, signature)) == NULL) {
-    // did not find it in the method table of the current class
-    if ((default_methods == NULL) ||
-        InstanceKlass::find_method(default_methods, name, signature) == NULL) {
-      if (super == NULL) {
-        // super doesn't exist
-        return true;
-      }
-
-      mo = InstanceKlass::cast(super)->lookup_method(name, signature);
-      while (mo != NULL && mo->access_flags().is_static()
-             && mo->method_holder() != NULL
-             && mo->method_holder()->super() != NULL)
-      {
-         mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::find_overpass);
-      }
-      if (mo == NULL || mo->access_flags().is_private() ) {
-        // super class hierarchy does not implement it or protection is different
-        return true;
-      }
-    }
-  } else {
-     // if the local class has a private method, the miranda will not
-     // override it, so a vtable slot is needed
-     if (mo->access_flags().is_private()) {
-
-       // Second round, weed out any superinterface methods that turned
-       // into default methods, i.e. were concrete not abstract in the end
-       if ((default_methods == NULL) ||
-         InstanceKlass::find_method(default_methods, name, signature) == NULL) {
-         return true;
-       }
-    }
+  // First look in local methods to see if already covered
+  if (InstanceKlass::find_local_method(class_methods, name, signature,
+              Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL)
+  {
+    return false;
   }
 
-  return false;
+  // Check local default methods
+  if ((default_methods != NULL) &&
+    (InstanceKlass::find_method(default_methods, name, signature) != NULL))
+   {
+     return false;
+   }
+
+  InstanceKlass* cursuper;
+  // Iterate on all superclasses, which should have instanceKlasses
+  // Note that we explicitly look for overpasses at each level.
+  // Overpasses may or may not exist for supers for pass 1,
+  // they should have been created for pass 2 and later.
+
+  for (cursuper = InstanceKlass::cast(super); cursuper != NULL;  cursuper = (InstanceKlass*)cursuper->super())
+  {
+     if (cursuper->find_local_method(name, signature,
+           Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL) {
+       return false;
+     }
+  }
+
+  return true;
 }
 
 // Scans current_interface_methods for miranda methods that do not
--- a/hotspot/src/share/vm/opto/block.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/block.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -393,7 +393,7 @@
   VectorSet visited(a);
 
   // Allocate stack with enough space to avoid frequent realloc
-  Node_Stack nstack(a, C->unique() >> 1);
+  Node_Stack nstack(a, C->live_nodes() >> 1);
   nstack.push(_root, 0);
   uint sum = 0;                 // Counter for blocks
 
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -802,7 +802,7 @@
   Compile *C = igvn->C;
   Arena *a = Thread::current()->resource_area();
   Node_Array node_map = new Node_Array(a);
-  Node_Stack stack(a, C->unique() >> 4);
+  Node_Stack stack(a, C->live_nodes() >> 4);
   PhiNode *nphi = slice_memory(at);
   igvn->register_new_node_with_optimizer( nphi );
   node_map.map(_idx, nphi);
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -3315,7 +3315,7 @@
 
   // Visit everybody reachable!
   // Allocate stack of size C->unique()/2 to avoid frequent realloc
-  Node_Stack nstack(unique() >> 1);
+  Node_Stack nstack(live_nodes() >> 1);
   final_graph_reshaping_walk(nstack, root(), frc);
 
   // Check for unreachable (from below) code (i.e., infinite loops).
--- a/hotspot/src/share/vm/opto/domgraph.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/domgraph.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -507,7 +507,7 @@
 // 'semi' as vertex to DFS mapping.  Set 'parent' to DFS parent.
 int NTarjan::DFS( NTarjan *ntarjan, VectorSet &visited, PhaseIdealLoop *pil, uint *dfsorder) {
   // Allocate stack of size C->unique()/8 to avoid frequent realloc
-  GrowableArray <Node *> dfstack(pil->C->unique() >> 3);
+  GrowableArray <Node *> dfstack(pil->C->live_nodes() >> 3);
   Node *b = pil->C->root();
   int dfsnum = 1;
   dfsorder[b->_idx] = dfsnum; // Cache parent's dfsnum for a later use
--- a/hotspot/src/share/vm/opto/gcm.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -107,8 +107,8 @@
 //------------------------------schedule_pinned_nodes--------------------------
 // Set the basic block for Nodes pinned into blocks
 void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) {
-  // Allocate node stack of size C->unique()+8 to avoid frequent realloc
-  GrowableArray <Node *> spstack(C->unique() + 8);
+  // Allocate node stack of size C->live_nodes()+8 to avoid frequent realloc
+  GrowableArray <Node *> spstack(C->live_nodes() + 8);
   spstack.push(_root);
   while (spstack.is_nonempty()) {
     Node* node = spstack.pop();
@@ -1310,7 +1310,7 @@
   visited.Clear();
   Node_List stack(arena);
   // Pre-grow the list
-  stack.map((C->unique() >> 1) + 16, NULL);
+  stack.map((C->live_nodes() >> 1) + 16, NULL);
   if (!schedule_early(visited, stack)) {
     // Bailout without retry
     C->record_method_not_compilable("early schedule failed");
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1282,7 +1282,7 @@
 
   if (C->do_vector_loop() && (PrintOpto && VerifyLoopOptimizations || TraceLoopOpts)) {
     Arena* arena = Thread::current()->resource_area();
-    Node_Stack stack(arena, C->unique() >> 2);
+    Node_Stack stack(arena, C->live_nodes() >> 2);
     Node_List rpo_list;
     VectorSet visited(arena);
     visited.set(loop_head->_idx);
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -2231,7 +2231,7 @@
   // _nodes array holds the earliest legal controlling CFG node.
 
   // Allocate stack with enough space to avoid frequent realloc
-  int stack_size = (C->unique() >> 1) + 16; // (unique>>1)+16 from Java2D stats
+  int stack_size = (C->live_nodes() >> 1) + 16; // (live_nodes>>1)+16 from Java2D stats
   Node_Stack nstack( a, stack_size );
 
   visited.Clear();
@@ -2691,7 +2691,7 @@
     }
   }
   if (_dom_stk == NULL) {
-    uint init_size = C->unique() / 100; // Guess that 1/100 is a reasonable initial size.
+    uint init_size = C->live_nodes() / 100; // Guess that 1/100 is a reasonable initial size.
     if (init_size < 10) init_size = 10;
     _dom_stk = new GrowableArray<uint>(init_size);
   }
@@ -2781,8 +2781,8 @@
 // The sort is of size number-of-control-children, which generally limits
 // it to size 2 (i.e., I just choose between my 2 target loops).
 void PhaseIdealLoop::build_loop_tree() {
-  // Allocate stack of size C->unique()/2 to avoid frequent realloc
-  GrowableArray <Node *> bltstack(C->unique() >> 1);
+  // Allocate stack of size C->live_nodes()/2 to avoid frequent realloc
+  GrowableArray <Node *> bltstack(C->live_nodes() >> 1);
   Node *n = C->root();
   bltstack.push(n);
   int pre_order = 1;
@@ -3672,7 +3672,7 @@
 void PhaseIdealLoop::dump( ) const {
   ResourceMark rm;
   Arena* arena = Thread::current()->resource_area();
-  Node_Stack stack(arena, C->unique() >> 2);
+  Node_Stack stack(arena, C->live_nodes() >> 2);
   Node_List rpo_list;
   VectorSet visited(arena);
   visited.set(C->top()->_idx);
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -2050,7 +2050,7 @@
 // Set bits if Node is shared or otherwise a root
 void Matcher::find_shared( Node *n ) {
   // Allocate stack of size C->unique() * 2 to avoid frequent realloc
-  MStack mstack(C->unique() * 2);
+  MStack mstack(C->live_nodes() * 2);
   // Mark nodes as address_visited if they are inputs to an address expression
   VectorSet address_visited(Thread::current()->resource_area());
   mstack.push(n, Visit);     // Don't need to pre-visit root node
--- a/hotspot/src/share/vm/opto/node.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/node.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1799,7 +1799,7 @@
 static void dump_nodes(const Node* start, int d, bool only_ctrl) {
   if (NotANode(start)) return;
 
-  GrowableArray <Node *> nstack(Compile::current()->unique());
+  GrowableArray <Node *> nstack(Compile::current()->live_nodes());
   collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false);
 
   int end = nstack.length();
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -791,7 +791,7 @@
 //------------------------------PhaseIterGVN-----------------------------------
 // Initialize hash table to fresh and clean for +VerifyOpto
 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
-                                                                      _stack(C->unique() >> 1),
+                                                                      _stack(C->live_nodes() >> 1),
                                                                       _delay_transform(false) {
 }
 
@@ -808,7 +808,11 @@
 // Initialize with previous PhaseGVN info from Parser
 PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
                                               _worklist(*C->for_igvn()),
-                                              _stack(C->unique() >> 1),
+// TODO: Before incremental inlining it was allocated only once and it was fine. Now that
+//       the constructor is used in incremental inlining, this consumes too much memory:
+//                                            _stack(C->live_nodes() >> 1),
+//       So, as a band-aid, we replace this by:
+                                              _stack(C->comp_arena(), 32),
                                               _delay_transform(false)
 {
   uint max;
@@ -1638,7 +1642,7 @@
   _nodes.map( n->_idx, new_node );  // Flag as having been cloned
 
   // Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
-  GrowableArray <Node *> trstack(C->unique() >> 1);
+  GrowableArray <Node *> trstack(C->live_nodes() >> 1);
 
   trstack.push(new_node);           // Process children of cloned node
   while ( trstack.is_nonempty() ) {
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -2295,13 +2295,13 @@
 }
 
 // Checks if name in command-line argument -agent{lib,path}:name[=options]
-// represents a valid HPROF of JDWP agent.  is_path==true denotes that we
+// represents a valid JDWP agent.  is_path==true denotes that we
 // are dealing with -agentpath (case where name is a path), otherwise with
 // -agentlib
-bool valid_hprof_or_jdwp_agent(char *name, bool is_path) {
+bool valid_jdwp_agent(char *name, bool is_path) {
   char *_name;
-  const char *_hprof = "hprof", *_jdwp = "jdwp";
-  size_t _len_hprof, _len_jdwp, _len_prefix;
+  const char *_jdwp = "jdwp";
+  size_t _len_jdwp, _len_prefix;
 
   if (is_path) {
     if ((_name = strrchr(name, (int) *os::file_separator())) == NULL) {
@@ -2316,13 +2316,9 @@
     }
 
     _name += _len_prefix;
-    _len_hprof = strlen(_hprof);
     _len_jdwp = strlen(_jdwp);
 
-    if (strncmp(_name, _hprof, _len_hprof) == 0) {
-      _name += _len_hprof;
-    }
-    else if (strncmp(_name, _jdwp, _len_jdwp) == 0) {
+    if (strncmp(_name, _jdwp, _len_jdwp) == 0) {
       _name += _len_jdwp;
     }
     else {
@@ -2336,7 +2332,7 @@
     return true;
   }
 
-  if (strcmp(name, _hprof) == 0 || strcmp(name, _jdwp) == 0) {
+  if (strcmp(name, _jdwp) == 0) {
     return true;
   }
 
@@ -2427,9 +2423,9 @@
           options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2);
         }
 #if !INCLUDE_JVMTI
-        if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
+        if (strcmp(name, "jdwp") == 0) {
           jio_fprintf(defaultStream::error_stream(),
-            "Profiling and debugging agents are not supported in this VM\n");
+            "Debugging agents are not supported in this VM\n");
           return JNI_ERR;
         }
 #endif // !INCLUDE_JVMTI
@@ -2449,9 +2445,9 @@
           options = os::strdup_check_oom(pos + 1, mtInternal);
         }
 #if !INCLUDE_JVMTI
-        if (valid_hprof_or_jdwp_agent(name, is_absolute_path)) {
+        if (valid_jdwp_agent(name, is_absolute_path)) {
           jio_fprintf(defaultStream::error_stream(),
-            "Profiling and debugging agents are not supported in this VM\n");
+            "Debugging agents are not supported in this VM\n");
           return JNI_ERR;
         }
 #endif // !INCLUDE_JVMTI
@@ -3305,7 +3301,9 @@
 
   if (scp_assembly_required) {
     // Assemble the bootclasspath elements into the final path.
-    Arguments::set_sysclasspath(scp_p->combined_path());
+    char *combined_path = scp_p->combined_path();
+    Arguments::set_sysclasspath(combined_path);
+    FREE_C_HEAP_ARRAY(char, combined_path);
   }
 
   // This must be done after all arguments have been processed.
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1271,6 +1271,7 @@
   bool has_jimage = (os::stat(jimage, &st) == 0);
   if (has_jimage) {
     Arguments::set_sysclasspath(jimage);
+    FREE_C_HEAP_ARRAY(char, jimage);
     return true;
   }
   FREE_C_HEAP_ARRAY(char, jimage);
@@ -1282,6 +1283,7 @@
       sysclasspath = expand_entries_to_path(modules_dir, fileSep, pathSep);
     }
   }
+  FREE_C_HEAP_ARRAY(char, modules_dir);
 
   // fallback to classes
   if (sysclasspath == NULL)
@@ -1289,6 +1291,7 @@
 
   if (sysclasspath == NULL) return false;
   Arguments::set_sysclasspath(sysclasspath);
+  FREE_C_HEAP_ARRAY(char, sysclasspath);
 
   return true;
 }
--- a/hotspot/src/share/vm/runtime/threadLocalStorage.cpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/threadLocalStorage.cpp	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,11 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadLocalStorage.hpp"
 
+// Solaris no longer has this kind of ThreadLocalStorage implementation.
+// This will be removed from all platforms in the near future.
+
+#ifndef SOLARIS
+
 // static member initialization
 int ThreadLocalStorage::_thread_index = -1;
 
@@ -54,3 +59,5 @@
 bool ThreadLocalStorage::is_initialized() {
     return (thread_index() != -1);
 }
+
+#endif // SOLARIS
--- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp	Thu Aug 20 11:38:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp	Wed Jul 05 20:46:35 2017 +0200
@@ -38,10 +38,14 @@
 extern "C" uintptr_t _raw_thread_id();
 
 class ThreadLocalStorage : AllStatic {
+
+ // Exported API
  public:
   static void    set_thread(Thread* thread);
   static Thread* get_thread_slow();
   static void    invalidate_all() { pd_invalidate_all(); }
+  static void    init();
+  static bool    is_initialized();
 
   // Machine dependent stuff
 #ifdef TARGET_OS_ARCH_linux_x86
@@ -81,17 +85,12 @@
 # include "threadLS_bsd_zero.hpp"
 #endif
 
-
+#ifndef SOLARIS
  public:
   // Accessor
   static inline int  thread_index()              { return _thread_index; }
   static inline void set_thread_index(int index) { _thread_index = index; }
 
-  // Initialization
-  // Called explicitly from VMThread::activate_system instead of init_globals.
-  static void init();
-  static bool is_initialized();
-
  private:
   static int     _thread_index;
 
@@ -100,6 +99,9 @@
   // Processor dependent parts of set_thread and initialization
   static void pd_set_thread(Thread* thread);
   static void pd_init();
+
+#endif // SOLARIS
+
   // Invalidate any thread cacheing or optimization schemes.
   static void pd_invalidate_all();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * @summary Simple jar builder
+ *   Input: jarName className1 className2 ...
+ *     do not specify extensions, just the names
+ *     E.g. prot_domain ProtDomainA ProtDomainB
+ *   Output: A jar containing compiled classes, placed in a test classes folder
+ */
+
+import jdk.test.lib.*;
+
+import java.io.File;
+import java.util.ArrayList;
+import sun.tools.jar.Main;
+
+public class BasicJarBuilder {
+    private static final String classDir = System.getProperty("test.classes");
+
+    public static void build(String jarName, String ...classNames)
+        throws Exception {
+
+        createSimpleJar(classDir, classDir + File.separator + jarName +
+            ".jar", classNames);
+    }
+
+    private static void createSimpleJar(String jarclassDir, String jarName,
+        String[] classNames) throws Exception {
+        ArrayList<String> args = new ArrayList<String>();
+        args.add("cf");
+        args.add(jarName);
+        addClassArgs(args, jarclassDir, classNames);
+        createJar(args);
+    }
+
+    private static void addClassArgs(ArrayList<String> args, String jarclassDir,
+        String[] classNames) {
+
+        for (String name : classNames) {
+            args.add("-C");
+            args.add(jarclassDir);
+            args.add(name + ".class");
+        }
+    }
+
+    private static void createJar(ArrayList<String> args) {
+        Main jarTool = new Main(System.out, System.err, "jar");
+        if (!jarTool.run(args.toArray(new String[1]))) {
+            throw new RuntimeException("jar operation failed");
+        }
+    }
+
+    // helpers
+    public static String getTestJar(String jar) {
+        File dir = new File(System.getProperty("test.classes", "."));
+        File jarFile = new File(dir, jar);
+        if (!jarFile.exists()) {
+            throw new RuntimeException("Cannot find " + jarFile.getPath());
+        }
+        if (!jarFile.isFile()) {
+            throw new RuntimeException("Not a regular file: " + jarFile.getPath());
+        }
+        return jarFile.getPath();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Check to make sure that shared strings in the bootstrap CDS archive
+ *          are actually shared
+ * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
+ * @requires (sun.arch.data.model != "32") & (os.family != "windows")
+ * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
+ * @requires (vm.gc=="G1" | vm.gc=="null")
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.management
+ * @ignore - 8133180
+ * @build SharedStringsWb SharedStrings BasicJarBuilder
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main SharedStrings
+ */
+
+import jdk.test.lib.*;
+
+public class SharedStrings {
+    public static void main(String[] args) throws Exception {
+        BasicJarBuilder.build("whitebox", "sun/hotspot/WhiteBox");
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=./SharedStrings.jsa",
+            "-XX:+PrintSharedSpaces",
+            // Needed for bootclasspath match, for CDS to work with WhiteBox API
+            "-Xbootclasspath/a:" + BasicJarBuilder.getTestJar("whitebox.jar"),
+            "-Xshare:dump");
+
+        new OutputAnalyzer(pb.start())
+            .shouldContain("Loading classes to share")
+            .shouldContain("Shared string table stats")
+            .shouldHaveExitValue(0);
+
+        pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=./SharedStrings.jsa",
+            // these are required modes for shared strings
+            "-XX:+UseCompressedOops", "-XX:+UseG1GC",
+            // needed for access to white box test API
+            "-Xbootclasspath/a:" + BasicJarBuilder.getTestJar("whitebox.jar"),
+            "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
+            "-Xshare:on", "-showversion", "SharedStringsWb");
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+        try {
+            output.shouldContain("sharing");
+            output.shouldHaveExitValue(0);
+        } catch (RuntimeException e) {
+            output.shouldContain("Unable to use shared archive");
+            output.shouldHaveExitValue(1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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 sun.hotspot.WhiteBox;
+
+// This class is used by the test SharedStrings.java
+// It should be launched in CDS mode
+public class SharedStringsWb {
+    public static void main(String[] args) throws Exception {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+
+        if (wb.areSharedStringsIgnored()) {
+            System.out.println("Shared strings are ignored, assuming PASS");
+            return;
+        }
+
+        // The string "java" is known to be interened and added to CDS archive
+        String s = "java";
+        String internedS = s.intern();
+
+        if (wb.isShared(internedS)) {
+            System.out.println("Found shared string, result: PASS");
+        } else {
+            throw new RuntimeException("String is not shared, result: FAIL");
+        }
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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 8087342
+ * @summary Test linkresolver search static, instance and overpass duplicates
+ * @run main/othervm -Xverify:none TestStaticandInstance
+ */
+
+
+import java.util.*;
+import jdk.internal.org.objectweb.asm.*;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+public class TestStaticandInstance {
+  static final String stringC = "C";
+  static final String stringD = "D";
+  static final String stringI = "I";
+
+  public static void main(String args[]) throws Throwable {
+    ClassLoader cl = new ClassLoader() {
+      public Class<?> loadClass(String name) throws ClassNotFoundException {
+        Class retClass;
+        if ((retClass = findLoadedClass(name)) != null) {
+           return retClass;
+        }
+        if (stringC.equals(name)) {
+            byte[] classFile=dumpC();
+            return defineClass(stringC, classFile, 0, classFile.length);
+        }
+        if (stringD.equals(name)) {
+            byte[] classFile=dumpD();
+            return defineClass(stringD, classFile, 0, classFile.length);
+        }
+        if (stringI.equals(name)) {
+            byte[] classFile=dumpI();
+            return defineClass(stringI, classFile, 0, classFile.length);
+        }
+        return super.loadClass(name);
+      }
+    };
+
+    Class classC = cl.loadClass(stringC);
+    Class classI = cl.loadClass(stringI);
+
+    try {
+      int staticret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallStatic").invoke(null);
+      if (staticret != 1) {
+        throw new RuntimeException("invokestatic failed to call correct method");
+      }
+      System.out.println("staticret: " + staticret); // should be 1
+
+      int invokeinterfaceret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallInterface").invoke(null);
+      if (invokeinterfaceret != 0) {
+        throw new RuntimeException(String.format("Expected java.lang.AbstractMethodError, got %d", invokeinterfaceret));
+      }
+      System.out.println("invokeinterfaceret: AbstractMethodError");
+
+      int invokevirtualret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallVirtual").invoke(null);
+      if (invokevirtualret != 0) {
+        throw new RuntimeException(String.format("Expected java.lang.IncompatibleClassChangeError, got %d", invokevirtualret));
+      }
+      System.out.println("invokevirtualret: IncompatibleClassChangeError");
+    } catch (java.lang.Throwable e) {
+      throw new RuntimeException("Unexpected exception: " + e.getMessage());
+    }
+  }
+
+/*
+interface I {
+  public int m(); // abstract
+  default int q() { return 3; } // trigger defmeth processing: C gets AME overpass
+}
+
+// C gets static, private and AME overpass m()I with -Xverify:none
+class C implements I {
+  static int m() { return 1;}  // javac with "n()" and patch to "m()"
+  private int m() { return 2;} // javac with public and patch to private
+}
+
+public class D {
+  public static int CallStatic() {
+    int staticret = C.m();    // javac with "C.n" and patch to "C.m"
+    return staticret;
+  }
+  public static int CallInterface() throws AbstractMethodError{
+    try {
+      I myI = new C();
+      return myI.m();
+    } catch (java.lang.AbstractMethodError e) {
+      return 0; // for success
+    }
+  }
+  public static int CallVirtual() {
+    try {
+      C myC = new C();
+      return myC.m();
+    } catch (java.lang.IncompatibleClassChangeError e) {
+      return 0; // for success
+    }
+  }
+}
+*/
+
+  public static byte[] dumpC() {
+
+    ClassWriter cw = new ClassWriter(0);
+    FieldVisitor fv;
+    MethodVisitor mv;
+    AnnotationVisitor av0;
+
+    cw.visit(52, ACC_SUPER, "C", null, "java/lang/Object", new String[] { "I" });
+
+    {
+      mv = cw.visitMethod(0, "<init>", "()V", null, null);
+      mv.visitCode();
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      mv.visitInsn(RETURN);
+      mv.visitMaxs(1, 1);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_STATIC, "m", "()I", null, null);
+      mv.visitCode();
+      mv.visitInsn(ICONST_1);
+      mv.visitInsn(IRETURN);
+      mv.visitMaxs(1, 0);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null);
+      mv.visitCode();
+      mv.visitInsn(ICONST_2);
+      mv.visitInsn(IRETURN);
+      mv.visitMaxs(1, 1);
+      mv.visitEnd();
+    }
+    cw.visitEnd();
+
+    return cw.toByteArray();
+  }
+
+  public static byte[] dumpD () {
+
+    ClassWriter cw = new ClassWriter(0);
+    FieldVisitor fv;
+    MethodVisitor mv;
+    AnnotationVisitor av0;
+
+    cw.visit(52, ACC_PUBLIC + ACC_SUPER, "D", null, "java/lang/Object", null);
+
+    {
+      mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+      mv.visitCode();
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      mv.visitInsn(RETURN);
+      mv.visitMaxs(1, 1);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallStatic", "()I", null, null);
+      mv.visitCode();
+      mv.visitMethodInsn(INVOKESTATIC, "C", "m", "()I", false);
+      mv.visitVarInsn(ISTORE, 0);
+      mv.visitVarInsn(ILOAD, 0);
+      mv.visitInsn(IRETURN);
+      mv.visitMaxs(1, 1);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallInterface", "()I", null, new String[] { "java/lang/AbstractMethodError" });
+      mv.visitCode();
+      Label l0 = new Label();
+      Label l1 = new Label();
+      Label l2 = new Label();
+      mv.visitTryCatchBlock(l0, l1, l2, "java/lang/AbstractMethodError");
+      mv.visitLabel(l0);
+      mv.visitTypeInsn(NEW, "C");
+      mv.visitInsn(DUP);
+      mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V", false);
+      mv.visitVarInsn(ASTORE, 0);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitMethodInsn(INVOKEINTERFACE, "I", "m", "()I", true);
+      mv.visitLabel(l1);
+      mv.visitInsn(IRETURN);
+      mv.visitLabel(l2);
+      mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AbstractMethodError"});
+      mv.visitVarInsn(ASTORE, 0);
+      mv.visitInsn(ICONST_0);
+      mv.visitInsn(IRETURN);
+      mv.visitMaxs(2, 1);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallVirtual", "()I", null, null);
+      mv.visitCode();
+      Label l0 = new Label();
+      Label l1 = new Label();
+      Label l2 = new Label();
+      mv.visitTryCatchBlock(l0, l1, l2, "java/lang/IncompatibleClassChangeError");
+      mv.visitLabel(l0);
+      mv.visitTypeInsn(NEW, "C");
+      mv.visitInsn(DUP);
+      mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V", false);
+      mv.visitVarInsn(ASTORE, 0);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitMethodInsn(INVOKEVIRTUAL, "C", "m", "()I", false);
+      mv.visitLabel(l1);
+      mv.visitInsn(IRETURN);
+      mv.visitLabel(l2);
+      mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"});
+      mv.visitVarInsn(ASTORE, 0);
+      mv.visitInsn(ICONST_0);
+      mv.visitInsn(IRETURN);
+      mv.visitMaxs(2, 1);
+      mv.visitEnd();
+    }
+    cw.visitEnd();
+
+    return cw.toByteArray();
+  }
+
+  public static byte[] dumpI() {
+
+    ClassWriter cw = new ClassWriter(0);
+    FieldVisitor fv;
+    MethodVisitor mv;
+    AnnotationVisitor av0;
+
+    cw.visit(52, ACC_ABSTRACT + ACC_INTERFACE, "I", null, "java/lang/Object", null);
+
+    {
+      mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PUBLIC, "q", "()I", null, null);
+      mv.visitCode();
+      mv.visitInsn(ICONST_3);
+      mv.visitInsn(IRETURN);
+      mv.visitMaxs(1, 1);
+      mv.visitEnd();
+    }
+    cw.visitEnd();
+
+    return cw.toByteArray();
+  }
+}
--- a/jaxp/.hgtags	Thu Aug 20 11:38:24 2015 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 20:46:35 2017 +0200
@@ -320,3 +320,4 @@
 16b5e696f948cd8aa9b3afdb686ddffd48bd17a8 jdk9-b75
 36801a89a04201b59874ec776ffe85d6253c9ab5 jdk9-b76
 be357705874c4ba1a69c38fb211e5e31e35bf9cb jdk9-b77
+5b1899c9822db4a80a29cac82af492afea9f8f41 jdk9-b78
--- a/jaxws/.hgtags	Thu Aug 20 11:38:24 2015 -0700
+++ b/jaxws/.hgtags	Wed Jul 05 20:46:35 2017 +0200
@@ -323,3 +323,4 @@
 086bcd5e4a531a350c84668c8dc019461588ee3d jdk9-b75
 55bb88306dc57d07f2c854803465f6d9a7eb4aba jdk9-b76
 bd6ece68cf8aca34c8d992569892060c82cfd3f1 jdk9-b77
+ac1748bab0743137574be3451307b6a6361719eb jdk9-b78
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/PostConstruct.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jaxws/src/java.annotations.common/share/classes/javax/annotation/PostConstruct.java	Wed Jul 05 20:46:35 2017 +0200
@@ -39,7 +39,6 @@
  * method can be annotated with this annotation. The method on which the
  * PostConstruct annotation is applied MUST fulfill all of the following
  * criteria:
- * <p>
  * <ul>
  * <li>The method MUST NOT have any parameters except in the case of
  * interceptors in which case it takes an InvocationContext object as
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/PreDestroy.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jaxws/src/java.annotations.common/share/classes/javax/annotation/PreDestroy.java	Wed Jul 05 20:46:35 2017 +0200
@@ -38,7 +38,6 @@
  * except the application client container in Java EE 5. The method on which
  * the PreDestroy annotation is applied MUST fulfill all of the following
  * criteria:
- * <p>
  * <ul>
  * <li>The method MUST NOT have any parameters except in the case of
  * interceptors in which case it takes an InvocationContext object as
--- a/jdk/.hgtags	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/.hgtags	Wed Jul 05 20:46:35 2017 +0200
@@ -320,3 +320,4 @@
 4dd09cb5f7c2a2a23a9958ea7a602dd74d5709b2 jdk9-b75
 4526c0da8fb362eebd7e88f4d44e86858cf9b80b jdk9-b76
 7fd081100f48828431e7c1bff65c906ee759069b jdk9-b77
+0940ce86c614458f5bdd72278b190abbf36b7b45 jdk9-b78
--- a/jdk/make/copy/Copy-jdk.hprof.agent.gmk	Thu Aug 20 11:38:24 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include CopyCommon.gmk
-
-################################################################################
-
-HPROF_SRC := $(JDK_TOPDIR)/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt
-
-$(LIB_DST_DIR)/jvm.hprof.txt: $(HPROF_SRC)
-	$(call install-file)
-
-TARGETS := $(LIB_DST_DIR)/jvm.hprof.txt
-
-################################################################################
--- a/jdk/make/data/tzdata/VERSION	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/VERSION	Wed Jul 05 20:46:35 2017 +0200
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2015e
+tzdata2015f
--- a/jdk/make/data/tzdata/africa	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/africa	Wed Jul 05 20:46:35 2017 +0200
@@ -561,7 +561,7 @@
 
 # From Alex Krivenyshev (2008-07-11):
 # Seems that English language article "The revival of daylight saving
-# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"- No. 16578 (07/11/2008) was originally
 # published on Monday, June 30, 2008...
 #
 # I guess that article in French "Le gouvernement avance l'introduction
@@ -693,7 +693,7 @@
 # Here is a link to official document from Royaume du Maroc Premier Ministre,
 # Ministère de la Modernisation des Secteurs Publics
 #
-# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
+# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 June 1967)
 # concerning the amendment of the legal time, the Ministry of Modernization of
 # Public Sectors announced that the official time in the Kingdom will be
 # advanced 60 minutes from Sunday 31 May 2009 at midnight.
--- a/jdk/make/data/tzdata/asia	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/asia	Wed Jul 05 20:46:35 2017 +0200
@@ -29,7 +29,7 @@
 # tz@iana.org for general use in the future).  For more, please see
 # the file CONTRIBUTING in the tz distribution.
 
-# From Paul Eggert (2014-10-31):
+# From Paul Eggert (2015-08-08):
 #
 # Unless otherwise specified, the source for data through 1990 is:
 # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -66,7 +66,7 @@
 #	2:00 EET  EEST	Eastern European Time
 #	2:00 IST  IDT	Israel
 #	3:00 AST  ADT	Arabia*
-#	3:30 IRST IRDT	Iran
+#	3:30 IRST IRDT	Iran*
 #	4:00 GST	Gulf*
 #	5:30 IST	India
 #	7:00 ICT	Indochina, most times and locations*
@@ -75,10 +75,11 @@
 #	8:00 CST	China
 #	8:00 IDT	Indochina, 1943-45, 1947-55, 1960-75 (some locations)*
 #	8:00 JWST	Western Standard Time (Japan, 1896/1937)*
+#	8:30 KST  KDT	Korea when at +0830*
 #	9:00 JCST	Central Standard Time (Japan, 1896/1937)
 #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
 #	9:00 JST  JDT	Japan
-#	9:00 KST  KDT	Korea
+#	9:00 KST  KDT	Korea when at +09
 #	9:30 ACST	Australian Central Standard Time
 #
 # See the 'europe' file for Russia and Turkey in Asia.
@@ -1050,7 +1051,7 @@
 #
 # From Roozbeh Pournader (2007-11-05):
 # This is quoted from Official Gazette of the Islamic Republic of
-# Iran, Volume 63, Number 18242, dated Tuesday 1386/6/24
+# Iran, Volume 63, No. 18242, dated Tuesday 1386/6/24
 # [2007-10-16]. I am doing the best translation I can:...
 # The official time of the country will be moved forward for one hour
 # on the 24 hours of the first day of the month of Farvardin and will
@@ -1580,7 +1581,7 @@
 # - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
 # - Oral switched from +5:00 to +4:00 in spring 1989.
 
-# From Kazakhstan Embassy's News Bulletin #11
+# From Kazakhstan Embassy's News Bulletin No. 11
 # <http://www.kazsociety.org.uk/news/2005/03/30.htm> (2005-03-21):
 # The Government of Kazakhstan passed a resolution March 15 abolishing
 # daylight saving time citing lack of economic benefits and health
@@ -1734,6 +1735,17 @@
 #
 # For Pyongyang we have no information; guess no changes since World War II.
 
+# From Steffen Thorsen (2015-08-07):
+# According to many news sources, North Korea is going to change to
+# the 8:30 time zone on August 15, one example:
+# http://www.bbc.com/news/world-asia-33815049
+#
+# From Paul Eggert (2015-08-07):
+# No transition time is specified; assume 00:00.
+# There is no common English-language abbreviation for this time zone.
+# Use %z rather than invent one.  We can't assume %z works everywhere yet,
+# so for now substitute its output manually.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Seoul	8:27:52	-	LMT	1908 Apr  1
 			8:30	-	KST	1912 Jan  1
@@ -1746,7 +1758,8 @@
 			8:30	-	KST	1912 Jan  1
 			9:00	-	JCST	1937 Oct  1
 			9:00	-	JST	1945 Aug 24
-			9:00	-	KST
+			9:00	-	KST	2015 Aug 15
+			8:30	-	KST
 
 ###############################################################################
 
--- a/jdk/make/data/tzdata/europe	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/europe	Wed Jul 05 20:46:35 2017 +0200
@@ -216,11 +216,14 @@
 #	republished in Finest Hour (Spring 2002) 1(114):26
 #	http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
 
-# From Paul Eggert (1996-09-03):
+# From Paul Eggert (2015-08-08):
 # The OED Supplement says that the English originally said "Daylight Saving"
 # when they were debating the adoption of DST in 1908; but by 1916 this
 # term appears only in quotes taken from DST's opponents, whereas the
 # proponents (who eventually won the argument) are quoted as using "Summer".
+# The term "Summer Time" was introduced by Herbert Samuel, Home Secretary; see:
+# Viscount Samuel. Leisure in a Democracy. Cambridge University Press
+# ISBN 978-1-107-49471-8 (1949, reissued 2015), p 8.
 
 # From Arthur David Olson (1989-01-19):
 # A source at the British Information Office in New York avers that it's
@@ -366,7 +369,7 @@
 
 # From an anonymous contributor (1996-06-02):
 # The law governing time in Ireland is under Statutory Instrument SI 395/94,
-# which gives force to European Union 7th Council Directive # 94/21/EC.
+# which gives force to European Union 7th Council Directive No. 94/21/EC.
 # Under this directive, the Minister for Justice in Ireland makes appropriate
 # regulations. I spoke this morning with the Secretary of the Department of
 # Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
@@ -615,11 +618,11 @@
 Rule	Russia	1921	only	-	Mar	20	23:00	2:00	MSM  # Midsummer
 Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	MSD
 Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
-# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
+# Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
 Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
 Rule	Russia	1981	1983	-	Oct	 1	 0:00	0	-
-# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
-# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
+# Act No. 967 of the Council of Ministers of the USSR (1984-09-13), repeated in
+# Act No. 227 of the Council of Ministers of the USSR (1989-03-14):
 Rule	Russia	1984	1991	-	Sep	lastSun	 2:00s	0	-
 Rule	Russia	1985	1991	-	Mar	lastSun	 2:00s	1:00	S
 #
@@ -851,7 +854,7 @@
 # Bulgaria
 #
 # From Plamen Simenov via Steffen Thorsen (1999-09-09):
-# A document of Government of Bulgaria (No.94/1997) says:
+# A document of Government of Bulgaria (No. 94/1997) says:
 # EET -> EETDST is in 03:00 Local time in last Sunday of March ...
 # EETDST -> EET is in 04:00 Local time in last Sunday of October
 #
@@ -868,7 +871,7 @@
 			1:00	C-Eur	CE%sT	1945
 			1:00	-	CET	1945 Apr  2  3:00
 			2:00	-	EET	1979 Mar 31 23:00
-			2:00	Bulg	EE%sT	1982 Sep 26  2:00
+			2:00	Bulg	EE%sT	1982 Sep 26  3:00
 			2:00	C-Eur	EE%sT	1991
 			2:00	E-Eur	EE%sT	1997
 			2:00	EU	EE%sT
@@ -1085,8 +1088,8 @@
 # after that.
 
 # From Mart Oruaas (2000-01-29):
-# Regulation no. 301 (1999-10-12) obsoletes previous regulation
-# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
+# Regulation No. 301 (1999-10-12) obsoletes previous regulation
+# No. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
 # the year round.  The regulation is effective 1999-11-01.
 
 # From Toomas Soome (2002-02-21):
@@ -1107,7 +1110,7 @@
 			3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
 			2:00	1:00	EEST	1989 Sep 24  2:00s
 			2:00	C-Eur	EE%sT	1998 Sep 22
-			2:00	EU	EE%sT	1999 Nov  1
+			2:00	EU	EE%sT	1999 Oct 31  4:00
 			2:00	-	EET	2002 Feb 21
 			2:00	EU	EE%sT
 
@@ -1550,21 +1553,21 @@
 # correct data in juridical acts and I found some juridical documents about
 # changes in the counting of time in Latvia from 1981....
 #
-# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
-# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
+# Act No. 35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
+# according to the Act No. 925 of the Council of Ministers of USSR of 1980-10-24
 # ...: all year round the time of 2nd time zone + 1 hour, in addition turning
 # the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
 # and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
 #
-# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
-# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
+# Act No. 592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
+# according to the Act No. 967 of the Council of Ministers of USSR of 1984-09-13
 # ...: all year round the time of 2nd time zone + 1 hour, in addition turning
 # the hands of the clock 1 hour forward on the last Sunday of March at 02:00
 # (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
 # September at 03:00 (GMT 23:00 on the previous day).
 #
-# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
-# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
+# Act No. 81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
+# according to the Act No. 227 of the Council of Ministers of USSR of 1989-03-14
 # ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
 # Estonian SSR and Kaliningrad region of Russian Federation all year round the
 # time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
@@ -1581,7 +1584,7 @@
 # From Andrei Ivanov (2000-03-06):
 # This year Latvia will not switch to Daylight Savings Time (as specified in
 # The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
+# 29-Feb-2000 (No. 79) <http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm>,
 # in Latvian for subscribers only).
 
 # From RFE/RL Newsline
@@ -1786,6 +1789,18 @@
 # News from Moldova (in russian):
 # http://ru.publika.md/link_317061.html
 
+# From Roman Tudos (2015-07-02):
+# http://lex.justice.md/index.php?action=view&view=doc&lang=1&id=355077
+# From Paul Eggert (2015-07-01):
+# The abovementioned official link to IGO1445-868/2014 states that
+# 2014-10-26's fallback transition occurred at 03:00 local time.  Also,
+# http://www.trm.md/en/social/la-30-martie-vom-trece-la-ora-de-vara
+# says the 2014-03-30 spring-forward transition was at 02:00 local time.
+# Guess that since 1997 Moldova has switched one hour before the EU.
+
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Moldova	1997	max	-	Mar	lastSun	 2:00	1:00	S
+Rule	Moldova	1997	max	-	Oct	lastSun	 3:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Chisinau	1:55:20 -	LMT	1880
@@ -1800,7 +1815,7 @@
 			2:00	Russia	EE%sT	1992
 			2:00	E-Eur	EE%sT	1997
 # See Romania commentary for the guessed 1997 transition to EU rules.
-			2:00	EU	EE%sT
+			2:00	Moldova	EE%sT
 
 # Monaco
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
@@ -2146,7 +2161,7 @@
 # Russia
 
 # From Alexander Krivenyshev (2011-09-15):
-# Based on last Russian Government Decree # 725 on August 31, 2011
+# Based on last Russian Government Decree No. 725 on August 31, 2011
 # (Government document
 # http://www.government.ru/gov/results/16355/print/
 # in Russian)
@@ -2156,7 +2171,7 @@
 # http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
 
 # From Sanjeev Gupta (2011-09-27):
-# Scans of [Decree #23 of January 8, 1992] are available at:
+# Scans of [Decree No. 23 of January 8, 1992] are available at:
 # http://government.consultant.ru/page.aspx?1223966
 # They are in Cyrillic letters (presumably Russian).
 
@@ -2167,19 +2182,19 @@
 # One source is
 # http://government.ru/gov/results/16355/
 # which, according to translate.google.com, begins "Decree of August 31,
-# 2011 No 725" and contains no other dates or "effective date" information.
+# 2011 No. 725" and contains no other dates or "effective date" information.
 #
 # Another source is
 # http://www.rg.ru/2011/09/06/chas-zona-dok.html
 # which, according to translate.google.com, begins "Resolution of the
 # Government of the Russian Federation on August 31, 2011 N 725" and also
 # contains "Date first official publication: September 6, 2011 Posted on:
-# in the 'RG' - Federal Issue number 5573 September 6, 2011" but which
+# in the 'RG' - Federal Issue No. 5573 September 6, 2011" but which
 # does not contain any "effective date" information.
 #
 # Another source is
 # http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# which, in note 8, contains "Resolution #725 of August 31, 2011...
+# which, in note 8, contains "Resolution No. 725 of August 31, 2011...
 # Effective as of after 7 days following the day of the official publication"
 # but which does not contain any reference to September 6, 2011.
 #
@@ -2387,7 +2402,7 @@
 # changed in May.
 			 2:00	E-Eur	EE%sT	1994 May
 # From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
-			 3:00	E-Eur	MSK/MSD	1996 Mar 31  3:00s
+			 3:00	E-Eur	MSK/MSD	1996 Mar 31  0:00s
 			 3:00	1:00	MSD	1996 Oct 27  3:00s
 # IATA SSIM (1997-09) says Crimea switched to EET/EEST.
 # Assume it happened in March by not changing the clocks.
@@ -2522,7 +2537,7 @@
 # from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
 # to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
 #
-# This is according to Government of Russia decree # 740, on September
+# This is according to Government of Russia decree No. 740, on September
 # 14, 2009 "Application in the territory of the Kemerovo region the Fifth
 # time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
 #
@@ -2945,7 +2960,7 @@
 Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 			-1:00	-	CANT	1946 Sep 30  1:00 # Canaries T
 			 0:00	-	WET	1980 Apr  6  0:00s
-			 0:00	1:00	WEST	1980 Sep 28  0:00s
+			 0:00	1:00	WEST	1980 Sep 28  1:00u
 			 0:00	EU	WE%sT
 # IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
 # Ignore this for now, as the Canaries are part of the EU.
@@ -3235,7 +3250,7 @@
 # From Igor Karpov, who works for the Ukrainian Ministry of Justice,
 # via Garrett Wollman (2003-01-27):
 # BTW, I've found the official document on this matter. It's government
-# regulations number 509, May 13, 1996. In my poor translation it says:
+# regulations No. 509, May 13, 1996. In my poor translation it says:
 # "Time in Ukraine is set to second timezone (Kiev time). Each last Sunday
 # of March at 3am the time is changing to 4am and each last Sunday of
 # October the time at 4am is changing to 3am"
@@ -3244,7 +3259,7 @@
 # On September 20, 2011 the deputies of the Verkhovna Rada agreed to
 # abolish the transfer clock to winter time.
 #
-# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
+# Bill No. 8330 of MP from the Party of Regions Oleg Nadoshi got
 # approval from 266 deputies.
 #
 # Ukraine abolishes transfer back to the winter time (in Russian)
--- a/jdk/make/data/tzdata/leapseconds	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/leapseconds	Wed Jul 05 20:46:35 2017 +0200
@@ -79,5 +79,5 @@
 Leap	2012	Jun	30	23:59:60	+	S
 Leap	2015	Jun	30	23:59:60	+	S
 
-#	Updated through IERS Bulletin C49
-#	File expires on:  28 December 2015
+#	Updated through IERS Bulletin C50
+#	File expires on:  28 June 2016
--- a/jdk/make/data/tzdata/northamerica	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/northamerica	Wed Jul 05 20:46:35 2017 +0200
@@ -1258,10 +1258,19 @@
 
 # west Labrador, Nova Scotia, Prince Edward I
 
-# From Paul Eggert (2006-03-22):
+# From Brian Inglis (2015-07-20):
+# From the historical weather station records available at:
+# https://weatherspark.com/history/28351/1971/Sydney-Nova-Scotia-Canada
+# Sydney shares the same time history as Glace Bay, so was
+# likely to be the same across the island....
+# Sydney, as the capital and most populous location, or Cape Breton, would
+# have been better names for the zone had we known this in 1996.
+
+# From Paul Eggert (2015-07-20):
 # Shanks & Pottenger write that since 1970 most of this region has been like
 # Halifax.  Many locales did not observe peacetime DST until 1972;
-# Glace Bay, NS is the largest that we know of.
+# the Cape Breton area, represented by Glace Bay, is the largest we know of
+# (Glace Bay was perhaps not the best name choice but no point changing now).
 # Shanks & Pottenger also write that Liverpool, NS was the only town
 # in Canada to observe DST in 1971 but not 1970; for now we'll assume
 # this is a typo.
@@ -1819,13 +1828,13 @@
 # Exact date in October unknown; Sunday October 1 is a reasonable guess.
 # 3. June 1918: switch to Pacific Daylight Time (GMT-7)
 # Exact date in June unknown; Sunday June 2 is a reasonable guess.
-# note#1:
+# note 1:
 # On Oct 27/1918 when daylight saving ended in the rest of Canada,
 # Creston did not change its clocks.
-# note#2:
+# note 2:
 # During WWII when the Federal Government legislated a mandatory clock change,
 # Creston did not oblige.
-# note#3:
+# note 3:
 # There is no guarantee that Creston will remain on Mountain Standard Time
 # (UTC-7) forever.
 # The subject was debated at least once this year by the town Council.
--- a/jdk/make/data/tzdata/southamerica	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/southamerica	Wed Jul 05 20:46:35 2017 +0200
@@ -154,7 +154,7 @@
 # Timezone Law (which never was effectively applied) will (would?) be
 # in effect.... The article is at
 # http://ar.clarin.com/diario/2001-06-06/e-01701.htm
-# ... The Law itself is "Ley No 25155", sanctioned on 1999-08-25, enacted
+# ... The Law itself is "Ley No. 25155", sanctioned on 1999-08-25, enacted
 # 1999-09-17, and published 1999-09-21.  The official publication is at:
 # http://www.boletin.jus.gov.ar/BON/Primera/1999/09-Septiembre/21/PDF/BO21-09-99LEG.PDF
 # Regretfully, you have to subscribe (and pay) for the on-line version....
@@ -198,15 +198,11 @@
 # http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
 # http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
 
-# From Rodrigo Severo (2008-10-06):
-# Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
-# ...
-# ------- Comment #1 from [jmdocile]  2008-10-06 16:28 0000 -------
-# Hi, there is a problem with timezone-data-2008e and maybe with
-# timezone-data-2008f
-# Argentinian law [Number] 25.155 is no longer valid.
+# From Juan Manuel Docile in https://bugs.gentoo.org/240339 (2008-10-07)
+# via Rodrigo Severo:
+# Argentinian law No. 25.155 is no longer valid.
 # http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# The new one is law [Number] 26.350
+# The new one is law No. 26.350
 # http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
 # So there is no summer time in Argentina for now.
 
@@ -794,7 +790,7 @@
 #	 [ and in a second message (same day): ]
 # I found the decree.
 #
-# DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
+# DECRETO No. 7.584, DE 13 DE OUTUBRO DE 2011
 # Link :
 # http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
 
@@ -1148,7 +1144,7 @@
 # Conflicts between [1] and [2] were resolved as follows:
 #
 #  - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites
-#    Boletín Nº 1, Aviso Nº 1 (1910).  Go with [2].
+#    Boletín No. 1, Aviso No. 1 (1910).  Go with [2].
 #
 #  - [1] says SMT was -4:42:45, [2] says Chile's official time from
 #    1916 to 1919 was -4:42:46.3, the meridian of Chile's National
@@ -1156,7 +1152,7 @@
 #    Quinta Normal in Santiago.  Go with [2], rounding it to -4:42:46.
 #
 #  - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites
-#    Boletín Nº 22, Aviso Nº 129/1918 (1918-08-23).  Go with [2].
+#    Boletín No. 22, Aviso No. 129/1918 (1918-08-23).  Go with [2].
 #
 #  - [1] does not give times for transitions; assume they occur
 #    at midnight mainland time, the current common practice.  However,
@@ -1556,7 +1552,7 @@
 # (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
 Rule	Para	1998	2001	-	Mar	Sun>=1	0:00	0	-
 # From Rives McDow (2002-02-28):
-# A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
+# A decree was issued in Paraguay (No. 16350) on 2002-02-26 that changed the
 # dst method to be from the first Sunday in September to the first Sunday in
 # April.
 Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
@@ -1736,8 +1732,19 @@
 Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
 # From Jesper Nørgaard Welen (2006-09-06):
 # http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
-Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
-Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
+#
+# From Steffen Thorsen (2015-06-30):
+# ... it looks like they will not be using DST the coming summer:
+# http://www.elobservador.com.uy/gobierno-resolvio-que-no-habra-cambio-horario-verano-n656787
+# http://www.republica.com.uy/este-ano-no-se-modificara-el-huso-horario-en-uruguay/523760/
+# From Paul Eggert (2015-06-30):
+# Apparently restaurateurs complained that DST caused people to go to the beach
+# instead of out to dinner.
+# From Pablo Camargo (2015-07-13):
+# http://archivo.presidencia.gub.uy/sci/decretos/2015/06/cons_min_201.pdf
+# [dated 2015-06-29; repeals Decree 311/006 dated 2006-09-04]
+Rule	Uruguay	2006	2014	-	Oct	Sun>=1	 2:00	1:00	S
+Rule	Uruguay	2007	2015	-	Mar	Sun>=8	 2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
 			-3:44:44 -	MMT	1920 May  1 # Montevideo MT
@@ -1746,6 +1753,10 @@
 
 # Venezuela
 #
+# From Paul Eggert (2015-07-28):
+# For the 1965 transition see Gaceta Oficial No. 27.619 (1964-12-15), p 205.533
+# http://www.pgr.gob.ve/dmdocuments/1964/27619.pdf
+#
 # From John Stainforth (2007-11-28):
 # ... the change for Venezuela originally expected for 2007-12-31 has
 # been brought forward to 2007-12-09.  The official announcement was
@@ -1757,6 +1768,6 @@
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
 			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
-			-4:30	-	VET	1965        # Venezuela Time
+			-4:30	-	VET	1965 Jan  1  0:00 # Venezuela T.
 			-4:00	-	VET	2007 Dec  9  3:00
 			-4:30	-	VET
--- a/jdk/make/data/tzdata/zone.tab	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/data/tzdata/zone.tab	Wed Jul 05 20:46:35 2017 +0200
@@ -129,8 +129,8 @@
 BY	+5354+02734	Europe/Minsk
 BZ	+1730-08812	America/Belize
 CA	+4734-05243	America/St_Johns	Newfoundland Time, including SE Labrador
-CA	+4439-06336	America/Halifax	Atlantic Time - Nova Scotia (most places), PEI
-CA	+4612-05957	America/Glace_Bay	Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
+CA	+4439-06336	America/Halifax	Atlantic Time - Nova Scotia (peninsula), PEI
+CA	+4612-05957	America/Glace_Bay	Atlantic Time - Nova Scotia (Cape Breton)
 CA	+4606-06447	America/Moncton	Atlantic Time - New Brunswick
 CA	+5320-06025	America/Goose_Bay	Atlantic Time - Labrador - most locations
 CA	+5125-05707	America/Blanc-Sablon	Atlantic Standard Time - Quebec - Lower North Shore
--- a/jdk/make/lib/Lib-java.base.gmk	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/lib/Lib-java.base.gmk	Wed Jul 05 20:46:35 2017 +0200
@@ -32,3 +32,4 @@
 include CoreLibraries.gmk
 include NetworkingLibraries.gmk
 include NioLibraries.gmk
+include SecurityLibraries.gmk
--- a/jdk/make/lib/Lib-jdk.deploy.osx.gmk	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/lib/Lib-jdk.deploy.osx.gmk	Wed Jul 05 20:46:35 2017 +0200
@@ -80,7 +80,6 @@
           -framework ApplicationServices \
           -framework JavaNativeFoundation \
           -framework JavaRuntimeSupport \
-          -framework Security \
           -framework SystemConfiguration \
           $(LDFLAGS_JDKLIB_SUFFIX), \
       OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosx, \
--- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk	Thu Aug 20 11:38:24 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include LibCommon.gmk
-
-################################################################################
-
-BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof)
-
-BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \
-    -I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo
-
-BUILD_LIBHPROF_LDFLAGS :=
-
-LIBHPROF_OPTIMIZATION := HIGHEST
-ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), )
-  ifeq ($(ENABLE_DEBUG_SYMBOLS), true)
-    LIBHPROF_OPTIMIZATION := LOW
-  endif
-endif
-
-$(eval $(call SetupNativeCompilation,BUILD_LIBHPROF, \
-    LIBRARY := hprof, \
-    OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-    SRC := $(BUILD_LIBHPROF_SRC), \
-    OPTIMIZATION := $(LIBHPROF_OPTIMIZATION), \
-    CFLAGS := $(CFLAGS_JDKLIB) \
-        $(BUILD_LIBHPROF_CFLAGS), \
-    CFLAGS_debug := -DHPROF_LOGGING, \
-    MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libhprof/mapfile-vers, \
-    LDFLAGS := $(LDFLAGS_JDKLIB) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LDFLAGS_windows := wsock32.lib winmm.lib advapi32.lib, \
-    LDFLAGS_SUFFIX_linux := $(LIBDL), \
-    LDFLAGS_SUFFIX_macosx := $(LIBDL), \
-    LDFLAGS_SUFFIX_solaris := -lsocket -lnsl $(LIBDL) -lc, \
-    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
-    RC_FLAGS := $(RC_FLAGS) \
-        -D "JDK_FNAME=hprof.dll" \
-        -D "JDK_INTERNAL_NAME=hprof" \
-        -D "JDK_FTYPE=0x2L", \
-    OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libhprof_jvmti, \
-    DEBUG_SYMBOLS := true))
-
-TARGETS += $(BUILD_LIBHPROF)
-
-################################################################################
-
-LIBJAVA_CRW_DEMO_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo
-
-$(eval $(call SetupNativeCompilation,BUILD_LIBJAVA_CRW_DEMO, \
-    LIBRARY := java_crw_demo, \
-    OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-    SRC := $(LIBJAVA_CRW_DEMO_SRC), \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(CFLAGS_JDKLIB) \
-        $(addprefix -I, $(LIBJAVA_CRW_DEMO_SRC)), \
-    MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava_crw_demo/mapfile-vers, \
-    LDFLAGS := $(LDFLAGS_JDKLIB) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LDFLAGS_SUFFIX_solaris := -lc, \
-    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
-    RC_FLAGS := $(RC_FLAGS) \
-        -D "JDK_FNAME=java_crw_demo.dll" \
-        -D "JDK_INTERNAL_NAME=java_crw_demo" \
-        -D "JDK_FTYPE=0x2L", \
-    OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava_crw_demo, \
-    DEBUG_SYMBOLS := true))
-
-TARGETS += $(BUILD_LIBJAVA_CRW_DEMO)
-
-################################################################################
--- a/jdk/make/lib/NioLibraries.gmk	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/lib/NioLibraries.gmk	Wed Jul 05 20:46:35 2017 +0200
@@ -69,9 +69,6 @@
     OPTIMIZATION := HIGH, \
     CFLAGS := $(CFLAGS_JDKLIB) \
         $(BUILD_LIBNIO_CFLAGS), \
-    DISABLED_WARNINGS_gcc := type-limits, \
-    DISABLED_WARNINGS_clang := tautological-compare, \
-    DISABLED_WARNINGS_microsoft := 4244 4996, \
     MAPFILE := $(BUILD_LIBNIO_MAPFILE), \
     LDFLAGS := $(LDFLAGS_JDKLIB) $(BUILD_LIBNIO_LDFLAGS) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/SecurityLibraries.gmk	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LibCommon.gmk
+
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+
+  ################################################################################
+
+  LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity
+  LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \
+      $(LIBJAVA_HEADER_FLAGS) \
+      -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+
+  $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \
+      LIBRARY := osxsecurity, \
+      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+      SRC := $(LIBOSXSECURITY_DIRS), \
+      OPTIMIZATION := LOW, \
+      CFLAGS := $(CFLAGS_JDKLIB) \
+          $(LIBOSXSECURITY_CFLAGS), \
+      DISABLED_WARNINGS_clang := deprecated-declarations, \
+      LDFLAGS := $(LDFLAGS_JDKLIB) \
+          -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \
+          $(call SET_SHARED_LIBRARY_ORIGIN), \
+      LDFLAGS_SUFFIX_macosx := \
+          -fobjc-link-runtime \
+          -framework JavaNativeFoundation \
+          -framework CoreServices \
+          -framework Security \
+          $(LDFLAGS_JDKLIB_SUFFIX), \
+      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \
+      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+
+  $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA)
+
+  TARGETS += $(BUILD_LIBOSXSECURITY)
+
+  ################################################################################
+
+endif
--- a/jdk/make/mapfiles/libhprof/mapfile-vers	Thu Aug 20 11:38:24 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# Define public interface.
-
-SUNWprivate_1.1 {
-	global:
-	    Agent_OnLoad;
-	    Agent_OnUnload;
-	local:
-	    *;
-};
--- a/jdk/make/mapfiles/libjava_crw_demo/mapfile-vers	Thu Aug 20 11:38:24 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# Define public interface.
-
-SUNWprivate_1.1 {
-	global:
-	    java_crw_demo;
-	    java_crw_demo_classname;
-	local:
-	    *;
-};
--- a/jdk/make/src/classes/build/tools/module/boot.modules	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/make/src/classes/build/tools/module/boot.modules	Wed Jul 05 20:46:35 2017 +0200
@@ -19,7 +19,6 @@
 jdk.charsets
 jdk.deploy
 jdk.deploy.osx
-jdk.hprof.agent
 jdk.httpserver
 jdk.jfr
 jdk.management
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+
+#include "ProcessHandleImpl_unix.h"
+
+#include <sys/procfs.h>
+
+/*
+ * Implementation of native ProcessHandleImpl functions for AIX.
+ * See ProcessHandleImpl_unix.c for more details.
+ */
+
+void os_initNative(JNIEnv *env, jclass clazz) {}
+
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+                    jlongArray jparentArray, jlongArray jstimesArray) {
+    return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
+}
+
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
+    return unix_getParentPidAndTimings(env, pid, total, start);
+}
+
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+    unix_getCmdlineAndUserInfo(env, jinfo, pid);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/linux/native/libjava/ProcessHandleImpl_linux.c	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "java_lang_ProcessHandleImpl.h"
+#include "java_lang_ProcessHandleImpl_Info.h"
+
+#include "ProcessHandleImpl_unix.h"
+
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * Implementation of native ProcessHandleImpl functions for Linux.
+ * See ProcessHandleImpl_unix.c for more details.
+ */
+
+/* Signatures for internal OS specific functions. */
+static long long getBoottime(JNIEnv *env);
+
+/* A static offset in milliseconds since boot. */
+static long long bootTime_ms;
+static long clock_ticks_per_second;
+static int pageSize;
+
+void os_initNative(JNIEnv *env, jclass clazz) {
+    bootTime_ms = getBoottime(env);
+    clock_ticks_per_second = sysconf(_SC_CLK_TCK);
+    pageSize = sysconf(_SC_PAGESIZE);
+}
+
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+                    jlongArray jparentArray, jlongArray jstimesArray) {
+    return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
+}
+
+/**
+ * Read /proc/<pid>/stat and return the ppid, total cputime and start time.
+ * -1 is fail;  >=  0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
+ */
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid,
+                                jlong *totalTime, jlong* startTime) {
+    FILE* fp;
+    char buffer[2048];
+    int statlen;
+    char fn[32];
+    char* s;
+    int parentPid;
+    long unsigned int utime = 0;      // clock tics
+    long unsigned int stime = 0;      // clock tics
+    long long unsigned int start = 0; // microseconds
+
+    /*
+     * Try to stat and then open /proc/%d/stat
+     */
+    snprintf(fn, sizeof fn, "/proc/%d/stat", pid);
+
+    fp = fopen(fn, "r");
+    if (fp == NULL) {
+        return -1;              // fail, no such /proc/pid/stat
+    }
+
+    /*
+     * The format is: pid (command) state ppid ...
+     * As the command could be anything we must find the right most
+     * ")" and then skip the white spaces that follow it.
+     */
+    statlen = fread(buffer, 1, (sizeof buffer - 1), fp);
+    fclose(fp);
+    if (statlen < 0) {
+        return -1;               // parent pid is not available
+    }
+
+    buffer[statlen] = '\0';
+    s = strchr(buffer, '(');
+    if (s == NULL) {
+        return -1;               // parent pid is not available
+    }
+    // Found start of command, skip to end
+    s++;
+    s = strrchr(s, ')');
+    if (s == NULL) {
+        return -1;               // parent pid is not available
+    }
+    s++;
+
+    // Scan the needed fields from status, retaining only ppid(4),
+    // utime (14), stime(15), starttime(22)
+    if (4 != sscanf(s, " %*c %d %*d %*d %*d %*d %*d %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %llu",
+            &parentPid, &utime, &stime, &start)) {
+        return 0;              // not all values parsed; return error
+    }
+
+    *totalTime = (utime + stime) * (jlong)(1000000000 / clock_ticks_per_second);
+
+    *startTime = bootTime_ms + ((start * 1000) / clock_ticks_per_second);
+
+    return parentPid;
+}
+
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+    int fd;
+    int cmdlen = 0;
+    char *cmdline = NULL, *cmdEnd = NULL; // used for command line args and exe
+    char *args = NULL;
+    jstring cmdexe = NULL;
+    char fn[32];
+    struct stat stat_buf;
+
+    /*
+     * Try to open /proc/<pid>/cmdline
+     */
+    snprintf(fn, sizeof fn, "/proc/%d/cmdline", pid);
+    if ((fd = open(fn, O_RDONLY)) < 0) {
+        return;
+    }
+
+    if (fstat(fd, &stat_buf) == 0) {
+        unix_getUserInfo(env, jinfo, stat_buf.st_uid);
+    }
+
+    do {                // Block to break out of on errors
+        int i, truncated = 0;
+        int count;
+        char *s;
+
+        /*
+         * The path name read by readlink() is limited to PATH_MAX characters.
+         * The content of /proc/<pid>/cmdline is limited to PAGE_SIZE characters.
+         */
+        cmdline = (char*)malloc((PATH_MAX > pageSize ? PATH_MAX : pageSize) + 1);
+        if (cmdline == NULL) {
+            break;
+        }
+
+        /*
+         * On Linux, the full path to the executable command is the link in
+         * /proc/<pid>/exe. But it is only readable for processes we own.
+         */
+        snprintf(fn, sizeof fn, "/proc/%d/exe", pid);
+        if ((cmdlen = readlink(fn, cmdline, PATH_MAX)) > 0) {
+            // null terminate and create String to store for command
+            cmdline[cmdlen] = '\0';
+            cmdexe = JNU_NewStringPlatform(env, cmdline);
+            (*env)->ExceptionClear(env);        // unconditionally clear any exception
+        }
+
+        /*
+         * The command-line arguments appear as a set of strings separated by
+         * null bytes ('\0'), with a further null byte after the last
+         * string. The last string is only null terminated if the whole command
+         * line is not exceeding (PAGE_SIZE - 1) characters.
+         */
+        cmdlen = 0;
+        s = cmdline;
+        while ((count = read(fd, s, pageSize - cmdlen)) > 0) {
+            cmdlen += count;
+            s += count;
+        }
+        if (count < 0) {
+            break;
+        }
+        // We have to null-terminate because the process may have changed argv[]
+        // or because the content in /proc/<pid>/cmdline is truncated.
+        cmdline[cmdlen] = '\0';
+        if (cmdlen == pageSize && cmdline[pageSize - 1] != '\0') {
+            truncated = 1;
+        } else if (cmdlen == 0) {
+            // /proc/<pid>/cmdline was empty. This usually happens for kernel processes
+            // like '[kthreadd]'. We could try to read /proc/<pid>/comm in the future.
+        }
+        if (cmdlen > 0 && (cmdexe == NULL || truncated)) {
+            // We have no exact command or the arguments are truncated.
+            // In this case we save the command line from /proc/<pid>/cmdline.
+            args = (char*)malloc(pageSize + 1);
+            if (args != NULL) {
+                memcpy(args, cmdline, cmdlen + 1);
+                for (i = 0; i < cmdlen; i++) {
+                    if (args[i] == '\0') {
+                        args[i] = ' ';
+                    }
+                }
+            }
+        }
+        i = 0;
+        if (!truncated) {
+            // Count the arguments
+            cmdEnd = &cmdline[cmdlen];
+            for (s = cmdline; *s != '\0' && (s < cmdEnd); i++) {
+                s += strnlen(s, (cmdEnd - s)) + 1;
+            }
+        }
+        unix_fillArgArray(env, jinfo, i, cmdline, cmdEnd, cmdexe, args);
+    } while (0);
+
+    if (cmdline != NULL) {
+        free(cmdline);
+    }
+    if (args != NULL) {
+        free(args);
+    }
+    if (fd >= 0) {
+        close(fd);
+    }
+}
+
+/**
+ * Read the boottime from /proc/stat.
+ */
+static long long getBoottime(JNIEnv *env) {
+    FILE *fp;
+    char *line = NULL;
+    size_t len = 0;
+    long long bootTime = 0;
+
+    fp = fopen("/proc/stat", "r");
+    if (fp == NULL) {
+        return -1;
+    }
+
+    while (getline(&line, &len, fp) != -1) {
+        if (sscanf(line, "btime %llu", &bootTime) == 1) {
+            break;
+        }
+    }
+    free(line);
+
+    if (fp != 0) {
+        fclose(fp);
+    }
+
+    return bootTime * 1000;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/classes/apple/security/AppleProvider.java	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package apple.security;
+
+import java.security.*;
+
+/**
+ * The Apple Security Provider.
+ */
+
+/**
+ * Defines the Apple provider.
+ *
+ * This provider only exists to provide access to the Apple keychain-based KeyStore implementation
+ */
+@SuppressWarnings("serial") // JDK implementation class
+public final class AppleProvider extends Provider {
+
+    private static final String info = "Apple Provider";
+
+    private static final class ProviderService extends Provider.Service {
+        ProviderService(Provider p, String type, String algo, String cn) {
+            super(p, type, algo, cn, null, null);
+        }
+
+        @Override
+        public Object newInstance(Object ctrParamObj)
+            throws NoSuchAlgorithmException {
+            String type = getType();
+            if (ctrParamObj != null) {
+                throw new InvalidParameterException
+                    ("constructorParameter not used with " + type + " engines");
+            }
+
+            String algo = getAlgorithm();
+            try {
+                if (type.equals("KeyStore")) {
+                    if (algo.equals("KeychainStore")) {
+                        return new KeychainStore();
+                    }
+                }
+            } catch (Exception ex) {
+                throw new NoSuchAlgorithmException("Error constructing " +
+                    type + " for " + algo + " using Apple", ex);
+            }
+            throw new ProviderException("No impl for " + algo +
+                " " + type);
+        }
+    }
+
+
+    public AppleProvider() {
+        /* We are the Apple provider */
+        super("Apple", 1.9d, info);
+
+        final Provider p = this;
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                putService(new ProviderService(p, "KeyStore",
+                           "KeychainStore", "apple.security.KeychainStore"));
+                return null;
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/classes/apple/security/KeychainStore.java	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,1149 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package apple.security;
+
+import java.io.*;
+import java.security.*;
+import java.security.cert.*;
+import java.security.cert.Certificate;
+import java.security.spec.*;
+import java.util.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import javax.security.auth.x500.*;
+
+import sun.security.pkcs.*;
+import sun.security.pkcs.EncryptedPrivateKeyInfo;
+import sun.security.util.*;
+import sun.security.x509.*;
+
+/**
+ * This class provides the keystore implementation referred to as "KeychainStore".
+ * It uses the current user's keychain as its backing storage, and does NOT support
+ * a file-based implementation.
+ */
+
+public final class KeychainStore extends KeyStoreSpi {
+
+    // Private keys and their supporting certificate chains
+    // If a key came from the keychain it has a SecKeyRef and one or more
+    // SecCertificateRef.  When we delete the key we have to delete all of the corresponding
+    // native objects.
+    class KeyEntry {
+        Date date; // the creation date of this entry
+        byte[] protectedPrivKey;
+        char[] password;
+        long keyRef;  // SecKeyRef for this key
+        Certificate chain[];
+        long chainRefs[];  // SecCertificateRefs for this key's chain.
+    };
+
+    // Trusted certificates
+    class TrustedCertEntry {
+        Date date; // the creation date of this entry
+
+        Certificate cert;
+        long certRef;  // SecCertificateRef for this key
+    };
+
+    /**
+     * Entries that have been deleted.  When something calls engineStore we'll
+     * remove them from the keychain.
+     */
+    private Hashtable<String, Object> deletedEntries = new Hashtable<>();
+
+    /**
+     * Entries that have been added.  When something calls engineStore we'll
+     * add them to the keychain.
+     */
+    private Hashtable<String, Object> addedEntries = new Hashtable<>();
+
+    /**
+     * Private keys and certificates are stored in a hashtable.
+     * Hash entries are keyed by alias names.
+     */
+    private Hashtable<String, Object> entries = new Hashtable<>();
+
+    /**
+     * Algorithm identifiers and corresponding OIDs for the contents of the PKCS12 bag we get from the Keychain.
+     */
+    private static final int keyBag[]  = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
+    private static final int pbeWithSHAAnd3KeyTripleDESCBC[] =     {1, 2, 840, 113549, 1, 12, 1, 3};
+    private static ObjectIdentifier PKCS8ShroudedKeyBag_OID;
+    private static ObjectIdentifier pbeWithSHAAnd3KeyTripleDESCBC_OID;
+
+    /**
+     * Constnats used in PBE decryption.
+     */
+    private static final int iterationCount = 1024;
+    private static final int SALT_LEN = 20;
+
+    static {
+        AccessController.doPrivileged(
+            new PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("osxsecurity");
+                    return null;
+                }
+            });
+        try {
+            PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag);
+            pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC);
+        } catch (IOException ioe) {
+            // should not happen
+        }
+    }
+
+    private static void permissionCheck() {
+        SecurityManager sec = System.getSecurityManager();
+
+        if (sec != null) {
+            sec.checkPermission(new RuntimePermission("useKeychainStore"));
+        }
+    }
+
+
+    /**
+     * Verify the Apple provider in the constructor.
+     *
+     * @exception SecurityException if fails to verify
+     * its own integrity
+     */
+    public KeychainStore() { }
+
+    /**
+        * Returns the key associated with the given alias, using the given
+     * password to recover it.
+     *
+     * @param alias the alias name
+     * @param password the password for recovering the key. This password is
+     *        used internally as the key is exported in a PKCS12 format.
+     *
+     * @return the requested key, or null if the given alias does not exist
+     * or does not identify a <i>key entry</i>.
+     *
+     * @exception NoSuchAlgorithmException if the algorithm for recovering the
+     * key cannot be found
+     * @exception UnrecoverableKeyException if the key cannot be recovered
+     * (e.g., the given password is wrong).
+     */
+    public Key engineGetKey(String alias, char[] password)
+        throws NoSuchAlgorithmException, UnrecoverableKeyException
+    {
+        permissionCheck();
+
+        // An empty password is rejected by MacOS API, no private key data
+        // is exported. If no password is passed (as is the case when
+        // this implementation is used as browser keystore in various
+        // deployment scenarios like Webstart, JFX and applets), create
+        // a dummy password so MacOS API is happy.
+        if (password == null || password.length == 0) {
+            // Must not be a char array with only a 0, as this is an empty
+            // string.
+            if (random == null) {
+                random = new SecureRandom();
+            }
+            password = Long.toString(random.nextLong()).toCharArray();
+        }
+
+        Object entry = entries.get(alias.toLowerCase());
+
+        if (entry == null || !(entry instanceof KeyEntry)) {
+            return null;
+        }
+
+        // This call gives us a PKCS12 bag, with the key inside it.
+        byte[] exportedKeyInfo = _getEncodedKeyData(((KeyEntry)entry).keyRef, password);
+        if (exportedKeyInfo == null) {
+            return null;
+        }
+
+        PrivateKey returnValue = null;
+
+        try {
+            byte[] pkcs8KeyData = fetchPrivateKeyFromBag(exportedKeyInfo);
+            byte[] encryptedKey;
+            AlgorithmParameters algParams;
+            ObjectIdentifier algOid;
+            try {
+                // get the encrypted private key
+                EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(pkcs8KeyData);
+                encryptedKey = encrInfo.getEncryptedData();
+
+                // parse Algorithm parameters
+                DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
+                DerInputStream in = val.toDerInputStream();
+                algOid = in.getOID();
+                algParams = parseAlgParameters(in);
+
+            } catch (IOException ioe) {
+                UnrecoverableKeyException uke =
+                new UnrecoverableKeyException("Private key not stored as "
+                                              + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
+                uke.initCause(ioe);
+                throw uke;
+            }
+
+            // Use JCE to decrypt the data using the supplied password.
+            SecretKey skey = getPBEKey(password);
+            Cipher cipher = Cipher.getInstance(algOid.toString());
+            cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
+            byte[] decryptedPrivateKey = cipher.doFinal(encryptedKey);
+            PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(decryptedPrivateKey);
+
+             // Parse the key algorithm and then use a JCA key factory to create the private key.
+            DerValue val = new DerValue(decryptedPrivateKey);
+            DerInputStream in = val.toDerInputStream();
+
+            // Ignore this -- version should be 0.
+            int i = in.getInteger();
+
+            // Get the Algorithm ID next
+            DerValue[] value = in.getSequence(2);
+            AlgorithmId algId = new AlgorithmId(value[0].getOID());
+            String algName = algId.getName();
+
+            // Get a key factory for this algorithm.  It's likely to be 'RSA'.
+            KeyFactory kfac = KeyFactory.getInstance(algName);
+            returnValue = kfac.generatePrivate(kspec);
+        } catch (Exception e) {
+            UnrecoverableKeyException uke =
+            new UnrecoverableKeyException("Get Key failed: " +
+                                          e.getMessage());
+            uke.initCause(e);
+            throw uke;
+        }
+
+        return returnValue;
+    }
+
+    private native byte[] _getEncodedKeyData(long secKeyRef, char[] password);
+
+    /**
+     * Returns the certificate chain associated with the given alias.
+     *
+     * @param alias the alias name
+     *
+     * @return the certificate chain (ordered with the user's certificate first
+                                      * and the root certificate authority last), or null if the given alias
+     * does not exist or does not contain a certificate chain (i.e., the given
+                                                               * alias identifies either a <i>trusted certificate entry</i> or a
+                                                               * <i>key entry</i> without a certificate chain).
+     */
+    public Certificate[] engineGetCertificateChain(String alias) {
+        permissionCheck();
+
+        Object entry = entries.get(alias.toLowerCase());
+
+        if (entry != null && entry instanceof KeyEntry) {
+            if (((KeyEntry)entry).chain == null) {
+                return null;
+            } else {
+                return ((KeyEntry)entry).chain.clone();
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the certificate associated with the given alias.
+     *
+     * <p>If the given alias name identifies a
+     * <i>trusted certificate entry</i>, the certificate associated with that
+     * entry is returned. If the given alias name identifies a
+     * <i>key entry</i>, the first element of the certificate chain of that
+     * entry is returned, or null if that entry does not have a certificate
+     * chain.
+     *
+     * @param alias the alias name
+     *
+     * @return the certificate, or null if the given alias does not exist or
+     * does not contain a certificate.
+     */
+    public Certificate engineGetCertificate(String alias) {
+        permissionCheck();
+
+        Object entry = entries.get(alias.toLowerCase());
+
+        if (entry != null) {
+            if (entry instanceof TrustedCertEntry) {
+                return ((TrustedCertEntry)entry).cert;
+            } else {
+                KeyEntry ke = (KeyEntry)entry;
+                if (ke.chain == null || ke.chain.length == 0) {
+                    return null;
+                }
+                return ke.chain[0];
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+        * Returns the creation date of the entry identified by the given alias.
+     *
+     * @param alias the alias name
+     *
+     * @return the creation date of this entry, or null if the given alias does
+     * not exist
+     */
+    public Date engineGetCreationDate(String alias) {
+        permissionCheck();
+
+        Object entry = entries.get(alias.toLowerCase());
+
+        if (entry != null) {
+            if (entry instanceof TrustedCertEntry) {
+                return new Date(((TrustedCertEntry)entry).date.getTime());
+            } else {
+                return new Date(((KeyEntry)entry).date.getTime());
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+        * Assigns the given key to the given alias, protecting it with the given
+     * password.
+     *
+     * <p>If the given key is of type <code>java.security.PrivateKey</code>,
+     * it must be accompanied by a certificate chain certifying the
+     * corresponding public key.
+     *
+     * <p>If the given alias already exists, the keystore information
+     * associated with it is overridden by the given key (and possibly
+                                                          * certificate chain).
+     *
+     * @param alias the alias name
+     * @param key the key to be associated with the alias
+     * @param password the password to protect the key
+     * @param chain the certificate chain for the corresponding public
+     * key (only required if the given key is of type
+            * <code>java.security.PrivateKey</code>).
+     *
+     * @exception KeyStoreException if the given key cannot be protected, or
+     * this operation fails for some other reason
+     */
+    public void engineSetKeyEntry(String alias, Key key, char[] password,
+                                  Certificate[] chain)
+        throws KeyStoreException
+    {
+        permissionCheck();
+
+        synchronized(entries) {
+            try {
+                KeyEntry entry = new KeyEntry();
+                entry.date = new Date();
+
+                if (key instanceof PrivateKey) {
+                    if ((key.getFormat().equals("PKCS#8")) ||
+                        (key.getFormat().equals("PKCS8"))) {
+                        entry.protectedPrivKey = encryptPrivateKey(key.getEncoded(), password);
+                        entry.password = password.clone();
+                    } else {
+                        throw new KeyStoreException("Private key is not encoded as PKCS#8");
+                    }
+                } else {
+                    throw new KeyStoreException("Key is not a PrivateKey");
+                }
+
+                // clone the chain
+                if (chain != null) {
+                    if ((chain.length > 1) && !validateChain(chain)) {
+                        throw new KeyStoreException("Certificate chain does not validate");
+                    }
+
+                    entry.chain = chain.clone();
+                    entry.chainRefs = new long[entry.chain.length];
+                }
+
+                String lowerAlias = alias.toLowerCase();
+                if (entries.get(lowerAlias) != null) {
+                    deletedEntries.put(lowerAlias, entries.get(lowerAlias));
+                }
+
+                entries.put(lowerAlias, entry);
+                addedEntries.put(lowerAlias, entry);
+            } catch (Exception nsae) {
+                KeyStoreException ke = new KeyStoreException("Key protection algorithm not found: " + nsae);
+                ke.initCause(nsae);
+                throw ke;
+            }
+        }
+    }
+
+    /**
+        * Assigns the given key (that has already been protected) to the given
+     * alias.
+     *
+     * <p>If the protected key is of type
+     * <code>java.security.PrivateKey</code>, it must be accompanied by a
+     * certificate chain certifying the corresponding public key. If the
+     * underlying keystore implementation is of type <code>jks</code>,
+     * <code>key</code> must be encoded as an
+     * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
+     *
+     * <p>If the given alias already exists, the keystore information
+     * associated with it is overridden by the given key (and possibly
+                                                          * certificate chain).
+     *
+     * @param alias the alias name
+     * @param key the key (in protected format) to be associated with the alias
+     * @param chain the certificate chain for the corresponding public
+     * key (only useful if the protected key is of type
+            * <code>java.security.PrivateKey</code>).
+     *
+     * @exception KeyStoreException if this operation fails.
+     */
+    public void engineSetKeyEntry(String alias, byte[] key,
+                                  Certificate[] chain)
+        throws KeyStoreException
+    {
+        permissionCheck();
+
+        synchronized(entries) {
+            // key must be encoded as EncryptedPrivateKeyInfo as defined in
+            // PKCS#8
+            KeyEntry entry = new KeyEntry();
+            try {
+                EncryptedPrivateKeyInfo privateKey = new EncryptedPrivateKeyInfo(key);
+                entry.protectedPrivKey = privateKey.getEncoded();
+            } catch (IOException ioe) {
+                throw new KeyStoreException("key is not encoded as "
+                                            + "EncryptedPrivateKeyInfo");
+            }
+
+            entry.date = new Date();
+
+            if ((chain != null) &&
+                (chain.length != 0)) {
+                entry.chain = chain.clone();
+                entry.chainRefs = new long[entry.chain.length];
+            }
+
+            String lowerAlias = alias.toLowerCase();
+            if (entries.get(lowerAlias) != null) {
+                deletedEntries.put(lowerAlias, entries.get(alias));
+            }
+            entries.put(lowerAlias, entry);
+            addedEntries.put(lowerAlias, entry);
+        }
+    }
+
+    /**
+        * Assigns the given certificate to the given alias.
+     *
+     * <p>If the given alias already exists in this keystore and identifies a
+     * <i>trusted certificate entry</i>, the certificate associated with it is
+     * overridden by the given certificate.
+     *
+     * @param alias the alias name
+     * @param cert the certificate
+     *
+     * @exception KeyStoreException if the given alias already exists and does
+     * not identify a <i>trusted certificate entry</i>, or this operation
+     * fails for some other reason.
+     */
+    public void engineSetCertificateEntry(String alias, Certificate cert)
+        throws KeyStoreException
+    {
+        permissionCheck();
+
+        synchronized(entries) {
+
+            Object entry = entries.get(alias.toLowerCase());
+            if ((entry != null) && (entry instanceof KeyEntry)) {
+                throw new KeyStoreException
+                ("Cannot overwrite key entry with certificate");
+            }
+
+            // This will be slow, but necessary.  Enumerate the values and then see if the cert matches the one in the trusted cert entry.
+            // Security framework doesn't support the same certificate twice in a keychain.
+            Collection<Object> allValues = entries.values();
+
+            for (Object value : allValues) {
+                if (value instanceof TrustedCertEntry) {
+                    TrustedCertEntry tce = (TrustedCertEntry)value;
+                    if (tce.cert.equals(cert)) {
+                        throw new KeyStoreException("Keychain does not support mulitple copies of same certificate.");
+                    }
+                }
+            }
+
+            TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
+            trustedCertEntry.cert = cert;
+            trustedCertEntry.date = new Date();
+            String lowerAlias = alias.toLowerCase();
+            if (entries.get(lowerAlias) != null) {
+                deletedEntries.put(lowerAlias, entries.get(lowerAlias));
+            }
+            entries.put(lowerAlias, trustedCertEntry);
+            addedEntries.put(lowerAlias, trustedCertEntry);
+        }
+    }
+
+    /**
+        * Deletes the entry identified by the given alias from this keystore.
+     *
+     * @param alias the alias name
+     *
+     * @exception KeyStoreException if the entry cannot be removed.
+     */
+    public void engineDeleteEntry(String alias)
+        throws KeyStoreException
+    {
+        permissionCheck();
+
+        synchronized(entries) {
+            Object entry = entries.remove(alias.toLowerCase());
+            deletedEntries.put(alias.toLowerCase(), entry);
+        }
+    }
+
+    /**
+        * Lists all the alias names of this keystore.
+     *
+     * @return enumeration of the alias names
+     */
+    public Enumeration<String> engineAliases() {
+        permissionCheck();
+        return entries.keys();
+    }
+
+    /**
+        * Checks if the given alias exists in this keystore.
+     *
+     * @param alias the alias name
+     *
+     * @return true if the alias exists, false otherwise
+     */
+    public boolean engineContainsAlias(String alias) {
+        permissionCheck();
+        return entries.containsKey(alias.toLowerCase());
+    }
+
+    /**
+        * Retrieves the number of entries in this keystore.
+     *
+     * @return the number of entries in this keystore
+     */
+    public int engineSize() {
+        permissionCheck();
+        return entries.size();
+    }
+
+    /**
+        * Returns true if the entry identified by the given alias is a
+     * <i>key entry</i>, and false otherwise.
+     *
+     * @return true if the entry identified by the given alias is a
+     * <i>key entry</i>, false otherwise.
+     */
+    public boolean engineIsKeyEntry(String alias) {
+        permissionCheck();
+        Object entry = entries.get(alias.toLowerCase());
+        if ((entry != null) && (entry instanceof KeyEntry)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+        * Returns true if the entry identified by the given alias is a
+     * <i>trusted certificate entry</i>, and false otherwise.
+     *
+     * @return true if the entry identified by the given alias is a
+     * <i>trusted certificate entry</i>, false otherwise.
+     */
+    public boolean engineIsCertificateEntry(String alias) {
+        permissionCheck();
+        Object entry = entries.get(alias.toLowerCase());
+        if ((entry != null) && (entry instanceof TrustedCertEntry)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+        * Returns the (alias) name of the first keystore entry whose certificate
+     * matches the given certificate.
+     *
+     * <p>This method attempts to match the given certificate with each
+     * keystore entry. If the entry being considered
+     * is a <i>trusted certificate entry</i>, the given certificate is
+     * compared to that entry's certificate. If the entry being considered is
+     * a <i>key entry</i>, the given certificate is compared to the first
+     * element of that entry's certificate chain (if a chain exists).
+     *
+     * @param cert the certificate to match with.
+     *
+     * @return the (alias) name of the first entry with matching certificate,
+     * or null if no such entry exists in this keystore.
+     */
+    public String engineGetCertificateAlias(Certificate cert) {
+        permissionCheck();
+        Certificate certElem;
+
+        for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
+            String alias = e.nextElement();
+            Object entry = entries.get(alias);
+            if (entry instanceof TrustedCertEntry) {
+                certElem = ((TrustedCertEntry)entry).cert;
+            } else {
+                KeyEntry ke = (KeyEntry)entry;
+                if (ke.chain == null || ke.chain.length == 0) {
+                    continue;
+                }
+                certElem = ke.chain[0];
+            }
+            if (certElem.equals(cert)) {
+                return alias;
+            }
+        }
+        return null;
+    }
+
+    /**
+        * Stores this keystore to the given output stream, and protects its
+     * integrity with the given password.
+     *
+     * @param stream Ignored. the output stream to which this keystore is written.
+     * @param password the password to generate the keystore integrity check
+     *
+     * @exception IOException if there was an I/O problem with data
+     * @exception NoSuchAlgorithmException if the appropriate data integrity
+     * algorithm could not be found
+     * @exception CertificateException if any of the certificates included in
+     * the keystore data could not be stored
+     */
+    public void engineStore(OutputStream stream, char[] password)
+        throws IOException, NoSuchAlgorithmException, CertificateException
+    {
+        permissionCheck();
+
+        // Delete items that do have a keychain item ref.
+        for (Enumeration<String> e = deletedEntries.keys(); e.hasMoreElements(); ) {
+            String alias = e.nextElement();
+            Object entry = deletedEntries.get(alias);
+            if (entry instanceof TrustedCertEntry) {
+                if (((TrustedCertEntry)entry).certRef != 0) {
+                    _removeItemFromKeychain(((TrustedCertEntry)entry).certRef);
+                    _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
+                }
+            } else {
+                Certificate certElem;
+                KeyEntry keyEntry = (KeyEntry)entry;
+
+                if (keyEntry.chain != null) {
+                    for (int i = 0; i < keyEntry.chain.length; i++) {
+                        if (keyEntry.chainRefs[i] != 0) {
+                            _removeItemFromKeychain(keyEntry.chainRefs[i]);
+                            _releaseKeychainItemRef(keyEntry.chainRefs[i]);
+                        }
+                    }
+
+                    if (keyEntry.keyRef != 0) {
+                        _removeItemFromKeychain(keyEntry.keyRef);
+                        _releaseKeychainItemRef(keyEntry.keyRef);
+                    }
+                }
+            }
+        }
+
+        // Add all of the certs or keys in the added entries.
+        // No need to check for 0 refs, as they are in the added list.
+        for (Enumeration<String> e = addedEntries.keys(); e.hasMoreElements(); ) {
+            String alias = e.nextElement();
+            Object entry = addedEntries.get(alias);
+            if (entry instanceof TrustedCertEntry) {
+                TrustedCertEntry tce = (TrustedCertEntry)entry;
+                Certificate certElem;
+                certElem = tce.cert;
+                tce.certRef = addCertificateToKeychain(alias, certElem);
+            } else {
+                KeyEntry keyEntry = (KeyEntry)entry;
+
+                if (keyEntry.chain != null) {
+                    for (int i = 0; i < keyEntry.chain.length; i++) {
+                        keyEntry.chainRefs[i] = addCertificateToKeychain(alias, keyEntry.chain[i]);
+                    }
+
+                    keyEntry.keyRef = _addItemToKeychain(alias, false, keyEntry.protectedPrivKey, keyEntry.password);
+                }
+            }
+        }
+
+        // Clear the added and deletedEntries hashtables here, now that we're done with the updates.
+        // For the deleted entries, we freed up the native references above.
+        deletedEntries.clear();
+        addedEntries.clear();
+    }
+
+    private long addCertificateToKeychain(String alias, Certificate cert) {
+        byte[] certblob = null;
+        long returnValue = 0;
+
+        try {
+            certblob = cert.getEncoded();
+            returnValue = _addItemToKeychain(alias, true, certblob, null);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    private native long _addItemToKeychain(String alias, boolean isCertificate, byte[] datablob, char[] password);
+    private native int _removeItemFromKeychain(long certRef);
+    private native void _releaseKeychainItemRef(long keychainItemRef);
+
+    /**
+      * Loads the keystore from the Keychain.
+     *
+     * @param stream Ignored - here for API compatibility.
+     * @param password Ignored - if user needs to unlock keychain Security
+     * framework will post any dialogs.
+     *
+     * @exception IOException if there is an I/O or format problem with the
+     * keystore data
+     * @exception NoSuchAlgorithmException if the algorithm used to check
+     * the integrity of the keystore cannot be found
+     * @exception CertificateException if any of the certificates in the
+     * keystore could not be loaded
+     */
+    public void engineLoad(InputStream stream, char[] password)
+        throws IOException, NoSuchAlgorithmException, CertificateException
+    {
+        permissionCheck();
+
+        // Release any stray keychain references before clearing out the entries.
+        synchronized(entries) {
+            for (Enumeration<String> e = entries.keys(); e.hasMoreElements(); ) {
+                String alias = e.nextElement();
+                Object entry = entries.get(alias);
+                if (entry instanceof TrustedCertEntry) {
+                    if (((TrustedCertEntry)entry).certRef != 0) {
+                        _releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
+                    }
+                } else {
+                    KeyEntry keyEntry = (KeyEntry)entry;
+
+                    if (keyEntry.chain != null) {
+                        for (int i = 0; i < keyEntry.chain.length; i++) {
+                            if (keyEntry.chainRefs[i] != 0) {
+                                _releaseKeychainItemRef(keyEntry.chainRefs[i]);
+                            }
+                        }
+
+                        if (keyEntry.keyRef != 0) {
+                            _releaseKeychainItemRef(keyEntry.keyRef);
+                        }
+                    }
+                }
+            }
+
+            entries.clear();
+            _scanKeychain();
+        }
+    }
+
+    private native void _scanKeychain();
+
+    /**
+     * Callback method from _scanKeychain.  If a trusted certificate is found, this method will be called.
+     */
+    private void createTrustedCertEntry(String alias, long keychainItemRef, long creationDate, byte[] derStream) {
+        TrustedCertEntry tce = new TrustedCertEntry();
+
+        try {
+            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+            InputStream input = new ByteArrayInputStream(derStream);
+            X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
+            input.close();
+            tce.cert = cert;
+            tce.certRef = keychainItemRef;
+
+            // Make a creation date.
+            if (creationDate != 0)
+                tce.date = new Date(creationDate);
+            else
+                tce.date = new Date();
+
+            int uniqueVal = 1;
+            String originalAlias = alias;
+
+            while (entries.containsKey(alias.toLowerCase())) {
+                alias = originalAlias + " " + uniqueVal;
+                uniqueVal++;
+            }
+
+            entries.put(alias.toLowerCase(), tce);
+        } catch (Exception e) {
+            // The certificate will be skipped.
+            System.err.println("KeychainStore Ignored Exception: " + e);
+        }
+    }
+
+    /**
+     * Callback method from _scanKeychain.  If an identity is found, this method will be called to create Java certificate
+     * and private key objects from the keychain data.
+     */
+    private void createKeyEntry(String alias, long creationDate, long secKeyRef, long[] secCertificateRefs, byte[][] rawCertData)
+        throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
+        KeyEntry ke = new KeyEntry();
+
+        // First, store off the private key information.  This is the easy part.
+        ke.protectedPrivKey = null;
+        ke.keyRef = secKeyRef;
+
+        // Make a creation date.
+        if (creationDate != 0)
+            ke.date = new Date(creationDate);
+        else
+            ke.date = new Date();
+
+        // Next, create X.509 Certificate objects from the raw data.  This is complicated
+        // because a certificate's public key may be too long for Java's default encryption strength.
+        List<CertKeychainItemPair> createdCerts = new ArrayList<>();
+
+        try {
+            CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+            for (int i = 0; i < rawCertData.length; i++) {
+                try {
+                    InputStream input = new ByteArrayInputStream(rawCertData[i]);
+                    X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
+                    input.close();
+
+                    // We successfully created the certificate, so track it and its corresponding SecCertificateRef.
+                    createdCerts.add(new CertKeychainItemPair(secCertificateRefs[i], cert));
+                } catch (CertificateException e) {
+                    // The certificate will be skipped.
+                    System.err.println("KeychainStore Ignored Exception: " + e);
+                }
+            }
+        } catch (CertificateException e) {
+            e.printStackTrace();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();  // How would this happen?
+        }
+
+        // We have our certificates in the List, so now extract them into an array of
+        // Certificates and SecCertificateRefs.
+        CertKeychainItemPair[] objArray = createdCerts.toArray(new CertKeychainItemPair[0]);
+        Certificate[] certArray = new Certificate[objArray.length];
+        long[] certRefArray = new long[objArray.length];
+
+        for (int i = 0; i < objArray.length; i++) {
+            CertKeychainItemPair addedItem = objArray[i];
+            certArray[i] = addedItem.mCert;
+            certRefArray[i] = addedItem.mCertificateRef;
+        }
+
+        ke.chain = certArray;
+        ke.chainRefs = certRefArray;
+
+        // If we don't have already have an item with this item's alias
+        // create a new one for it.
+        int uniqueVal = 1;
+        String originalAlias = alias;
+
+        while (entries.containsKey(alias.toLowerCase())) {
+            alias = originalAlias + " " + uniqueVal;
+            uniqueVal++;
+        }
+
+        entries.put(alias.toLowerCase(), ke);
+    }
+
+    private class CertKeychainItemPair {
+        long mCertificateRef;
+        Certificate mCert;
+
+        CertKeychainItemPair(long inCertRef, Certificate cert) {
+            mCertificateRef = inCertRef;
+            mCert = cert;
+        }
+    }
+
+    /*
+     * Validate Certificate Chain
+     */
+    private boolean validateChain(Certificate[] certChain)
+    {
+        for (int i = 0; i < certChain.length-1; i++) {
+            X500Principal issuerDN =
+            ((X509Certificate)certChain[i]).getIssuerX500Principal();
+            X500Principal subjectDN =
+                ((X509Certificate)certChain[i+1]).getSubjectX500Principal();
+            if (!(issuerDN.equals(subjectDN)))
+                return false;
+        }
+        return true;
+    }
+
+    @SuppressWarnings("deprecation")
+    private byte[] fetchPrivateKeyFromBag(byte[] privateKeyInfo) throws IOException, NoSuchAlgorithmException, CertificateException
+    {
+        byte[] returnValue = null;
+        DerValue val = new DerValue(new ByteArrayInputStream(privateKeyInfo));
+        DerInputStream s = val.toDerInputStream();
+        int version = s.getInteger();
+
+        if (version != 3) {
+            throw new IOException("PKCS12 keystore not in version 3 format");
+        }
+
+        /*
+            * Read the authSafe.
+         */
+        byte[] authSafeData;
+        ContentInfo authSafe = new ContentInfo(s);
+        ObjectIdentifier contentType = authSafe.getContentType();
+
+        if (contentType.equals(ContentInfo.DATA_OID)) {
+            authSafeData = authSafe.getData();
+        } else /* signed data */ {
+            throw new IOException("public key protected PKCS12 not supported");
+        }
+
+        DerInputStream as = new DerInputStream(authSafeData);
+        DerValue[] safeContentsArray = as.getSequence(2);
+        int count = safeContentsArray.length;
+
+        /*
+         * Spin over the ContentInfos.
+         */
+        for (int i = 0; i < count; i++) {
+            byte[] safeContentsData;
+            ContentInfo safeContents;
+            DerInputStream sci;
+            byte[] eAlgId = null;
+
+            sci = new DerInputStream(safeContentsArray[i].toByteArray());
+            safeContents = new ContentInfo(sci);
+            contentType = safeContents.getContentType();
+            safeContentsData = null;
+
+            if (contentType.equals(ContentInfo.DATA_OID)) {
+                safeContentsData = safeContents.getData();
+            } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
+                // The password was used to export the private key from the keychain.
+                // The Keychain won't export the key with encrypted data, so we don't need
+                // to worry about it.
+                continue;
+            } else {
+                throw new IOException("public key protected PKCS12" +
+                                      " not supported");
+            }
+            DerInputStream sc = new DerInputStream(safeContentsData);
+            returnValue = extractKeyData(sc);
+        }
+
+        return returnValue;
+    }
+
+    @SuppressWarnings("deprecation")
+    private byte[] extractKeyData(DerInputStream stream)
+        throws IOException, NoSuchAlgorithmException, CertificateException
+    {
+        byte[] returnValue = null;
+        DerValue[] safeBags = stream.getSequence(2);
+        int count = safeBags.length;
+
+        /*
+         * Spin over the SafeBags.
+         */
+        for (int i = 0; i < count; i++) {
+            ObjectIdentifier bagId;
+            DerInputStream sbi;
+            DerValue bagValue;
+            Object bagItem = null;
+
+            sbi = safeBags[i].toDerInputStream();
+            bagId = sbi.getOID();
+            bagValue = sbi.getDerValue();
+            if (!bagValue.isContextSpecific((byte)0)) {
+                throw new IOException("unsupported PKCS12 bag value type "
+                                      + bagValue.tag);
+            }
+            bagValue = bagValue.data.getDerValue();
+            if (bagId.equals(PKCS8ShroudedKeyBag_OID)) {
+                // got what we were looking for.  Return it.
+                returnValue = bagValue.toByteArray();
+            } else {
+                // log error message for "unsupported PKCS12 bag type"
+                System.out.println("Unsupported bag type '" + bagId + "'");
+            }
+        }
+
+        return returnValue;
+    }
+
+    /*
+        * Generate PBE Algorithm Parameters
+     */
+    private AlgorithmParameters getAlgorithmParameters(String algorithm)
+        throws IOException
+    {
+        AlgorithmParameters algParams = null;
+
+        // create PBE parameters from salt and iteration count
+        PBEParameterSpec paramSpec =
+            new PBEParameterSpec(getSalt(), iterationCount);
+        try {
+            algParams = AlgorithmParameters.getInstance(algorithm);
+            algParams.init(paramSpec);
+        } catch (Exception e) {
+            IOException ioe =
+            new IOException("getAlgorithmParameters failed: " +
+                            e.getMessage());
+            ioe.initCause(e);
+            throw ioe;
+        }
+        return algParams;
+    }
+
+    // the source of randomness
+    private SecureRandom random;
+
+    /*
+     * Generate random salt
+     */
+    private byte[] getSalt()
+    {
+        // Generate a random salt.
+        byte[] salt = new byte[SALT_LEN];
+        if (random == null) {
+            random = new SecureRandom();
+        }
+        salt = random.generateSeed(SALT_LEN);
+        return salt;
+    }
+
+    /*
+     * parse Algorithm Parameters
+     */
+    private AlgorithmParameters parseAlgParameters(DerInputStream in)
+        throws IOException
+    {
+        AlgorithmParameters algParams = null;
+        try {
+            DerValue params;
+            if (in.available() == 0) {
+                params = null;
+            } else {
+                params = in.getDerValue();
+                if (params.tag == DerValue.tag_Null) {
+                    params = null;
+                }
+            }
+            if (params != null) {
+                algParams = AlgorithmParameters.getInstance("PBE");
+                algParams.init(params.toByteArray());
+            }
+        } catch (Exception e) {
+            IOException ioe =
+            new IOException("parseAlgParameters failed: " +
+                            e.getMessage());
+            ioe.initCause(e);
+            throw ioe;
+        }
+        return algParams;
+    }
+
+    /*
+     * Generate PBE key
+     */
+    private SecretKey getPBEKey(char[] password) throws IOException
+    {
+        SecretKey skey = null;
+
+        try {
+            PBEKeySpec keySpec = new PBEKeySpec(password);
+            SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
+            skey = skFac.generateSecret(keySpec);
+        } catch (Exception e) {
+            IOException ioe = new IOException("getSecretKey failed: " +
+                                              e.getMessage());
+            ioe.initCause(e);
+            throw ioe;
+        }
+        return skey;
+    }
+
+    /*
+     * Encrypt private key using Password-based encryption (PBE)
+     * as defined in PKCS#5.
+     *
+     * NOTE: Currently pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is
+     *       used to derive the key and IV.
+     *
+     * @return encrypted private key encoded as EncryptedPrivateKeyInfo
+     */
+    private byte[] encryptPrivateKey(byte[] data, char[] password)
+        throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException
+    {
+        byte[] key = null;
+
+        try {
+            // create AlgorithmParameters
+            AlgorithmParameters algParams =
+            getAlgorithmParameters("PBEWithSHA1AndDESede");
+
+            // Use JCE
+            SecretKey skey = getPBEKey(password);
+            Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
+            cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
+            byte[] encryptedKey = cipher.doFinal(data);
+
+            // wrap encrypted private key in EncryptedPrivateKeyInfo
+            // as defined in PKCS#8
+            AlgorithmId algid =
+                new AlgorithmId(pbeWithSHAAnd3KeyTripleDESCBC_OID, algParams);
+            EncryptedPrivateKeyInfo encrInfo =
+                new EncryptedPrivateKeyInfo(algid, encryptedKey);
+            key = encrInfo.getEncoded();
+        } catch (Exception e) {
+            UnrecoverableKeyException uke =
+            new UnrecoverableKeyException("Encrypt Private Key failed: "
+                                          + e.getMessage());
+            uke.initCause(e);
+            throw uke;
+        }
+
+        return key;
+    }
+
+
+}
+
--- a/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/macosx/native/libjava/ProcessHandleImpl_macosx.c	Wed Jul 05 20:46:35 2017 +0200
@@ -28,6 +28,8 @@
 #include "java_lang_ProcessHandleImpl.h"
 #include "java_lang_ProcessHandleImpl_Info.h"
 
+#include "ProcessHandleImpl_unix.h"
+
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
@@ -38,144 +40,15 @@
 #include <sys/sysctl.h>
 
 /**
- * Implementations of ProcessHandleImpl functions for MAC OS X;
- * are NOT common to all Unix variants.
+ * Implementation of native ProcessHandleImpl functions for MAC OS X.
+ * See ProcessHandleImpl_unix.c for more details.
  */
 
-static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
-
-/*
- * Common Unix function to lookup the uid and return the user name.
- */
-extern jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
-
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
-
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl_Info
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
-    CHECK_NULL(ProcessHandleImpl_Info_commandID =
-            (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
-            (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
-            (*env)->GetFieldID(env, clazz, "totalTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
-            (*env)->GetFieldID(env, clazz, "startTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_userID =
-            (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
-}
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
-      clock_ticks_per_second = sysconf(_SC_CLK_TCK);
-}
-
-/*
- * Check if a process is alive.
- * Return the start time (ms since 1970) if it is available.
- * If the start time is not available return 0.
- * If the pid is invalid, return -1.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    isAlive0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
-    pid_t pid = (pid_t) jpid;
-    struct kinfo_proc kp;
-    size_t bufSize = sizeof kp;
-
-    // Read the process info for the specific pid
-    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
-
-    if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
-        return  (errno == EINVAL) ? -1 : 0;
-    } else {
-        return (bufSize == 0) ?  -1 :
-                                 (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
-                                        + kp.kp_proc.p_starttime.tv_usec / 1000);
-    }
-}
-
-/*
- * Returns the parent pid of the requested pid.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    parent0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
-                                         jobject obj,
-                                         jlong jpid,
-                                         jlong startTime) {
-    pid_t pid = (pid_t) jpid;
-    pid_t ppid = -1;
-
-    if (pid == getpid()) {
-        ppid = getppid();
-    } else {
-        const pid_t pid = (pid_t) jpid;
-        struct kinfo_proc kp;
-        size_t bufSize = sizeof kp;
-
-        // Read the process info for the specific pid
-        int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
-        if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
-            JNU_ThrowByNameWithLastError(env,
-                "java/lang/RuntimeException", "sysctl failed");
-            return -1;
-        }
-        // If the buffer is full and for the pid requested then check the start
-        if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
-            jlong start = (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000
-                                   + kp.kp_proc.p_starttime.tv_usec / 1000);
-            if (start == startTime || start == 0 || startTime == 0) {
-                ppid = kp.kp_eproc.e_ppid;
-            }
-        }
-    }
-    return (jlong) ppid;
-}
+void os_initNative(JNIEnv *env, jclass clazz) {}
 
 /*
  * Returns the children of the requested pid and optionally each parent.
  *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    getProcessPids0
- * Signature: (J[J[J)I
- *
  * Use sysctl to accumulate any process whose parent pid is zero or matches.
  * The resulting pids are stored into the array of longs.
  * The number of pids is returned if they all fit.
@@ -183,13 +56,8 @@
  * If the array is too short, excess pids are not stored and
  * the desired length is returned.
  */
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
-                                                 jclass clazz,
-                                                 jlong jpid,
-                                                 jlongArray jarray,
-                                                 jlongArray jparentArray,
-                                                 jlongArray jstimesArray) {
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+                    jlongArray jparentArray, jlongArray jstimesArray) {
     jlong* pids = NULL;
     jlong* ppids = NULL;
     jlong* stimes = NULL;
@@ -303,35 +171,17 @@
     return count;
 }
 
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
+/**
+ * Use sysctl and return the ppid, total cputime and start time.
+ * Return: -1 is fail;  >=  0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
  */
-
-/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    info0
- * Signature: (J)I
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
-                                                 jobject jinfo,
-                                                 jlong jpid) {
-    pid_t pid = (pid_t) jpid;
-    getStatInfo(env, jinfo, pid);
-    getCmdlineInfo(env, jinfo, pid);
-}
-
-/**
- * Read /proc/<pid>/stat and fill in the fields of the Info object.
- * The executable name, plus the user, system, and start times are gathered.
- */
-static void getStatInfo(JNIEnv *env, jobject jinfo, pid_t jpid) {
-    jlong totalTime;                    // nanoseconds
-    unsigned long long startTime;       // milliseconds
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t jpid,
+                                jlong *totalTime, jlong *startTime) {
 
     const pid_t pid = (pid_t) jpid;
+    pid_t ppid = -1;
     struct kinfo_proc kp;
     size_t bufSize = sizeof kp;
 
@@ -339,92 +189,70 @@
     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
 
     if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) < 0) {
-        if (errno == EINVAL) {
-            return;
-        } else {
-            JNU_ThrowByNameWithLastError(env,
-                "java/lang/RuntimeException", "sysctl failed");
-        }
-        return;
+        JNU_ThrowByNameWithLastError(env,
+            "java/lang/RuntimeException", "sysctl failed");
+        return -1;
     }
-
-    // Convert the UID to the username
-    jstring name = NULL;
-    CHECK_NULL((name = uidToUser(env, kp.kp_eproc.e_ucred.cr_uid)));
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
-    JNU_CHECK_EXCEPTION(env);
-
-    startTime = kp.kp_proc.p_starttime.tv_sec * 1000 +
-                kp.kp_proc.p_starttime.tv_usec / 1000;
-
-    (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
-    JNU_CHECK_EXCEPTION(env);
+    if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
+        *startTime = (jlong) (kp.kp_proc.p_starttime.tv_sec * 1000 +
+                              kp.kp_proc.p_starttime.tv_usec / 1000);
+        ppid = kp.kp_eproc.e_ppid;
+    }
 
     // Get cputime if for current process
     if (pid == getpid()) {
         struct rusage usage;
-        if (getrusage(RUSAGE_SELF, &usage) != 0) {
-            return;
+        if (getrusage(RUSAGE_SELF, &usage) == 0) {
+          jlong microsecs =
+              usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
+              usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
+          *totalTime = microsecs * 1000;
         }
-        jlong microsecs =
-            usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
-            usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
-        totalTime = microsecs * 1000;
-        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
-        JNU_CHECK_EXCEPTION(env);
     }
+
+    return ppid;
+
 }
 
 /**
- * Construct the argument array by parsing the arguments from the sequence of arguments.
+ * Return the uid of a process or -1 on error
  */
-static int fillArgArray(JNIEnv *env, jobject jinfo, int nargs,
-                        const char *cp, const char *argsEnd) {
-    jstring str = NULL;
-    jobject argsArray;
-    int i;
+static uid_t getUID(pid_t pid) {
+    struct kinfo_proc kp;
+    size_t bufSize = sizeof kp;
 
-    if (nargs < 1) {
-        return 0;
+    // Read the process info for the specific pid
+    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
+
+    if (sysctl(mib, 4, &kp, &bufSize, NULL, 0) == 0) {
+        if (bufSize > 0 && kp.kp_proc.p_pid == pid) {
+            return kp.kp_eproc.e_ucred.cr_uid;
+        }
     }
-    // Create a String array for nargs-1 elements
-    CHECK_NULL_RETURN((argsArray = (*env)->NewObjectArray(env,
-            nargs - 1, JNU_ClassString(env), NULL)), -1);
-
-    for (i = 0; i < nargs - 1; i++) {
-        // skip to the next argument; omits arg[0]
-        cp += strnlen(cp, (argsEnd - cp)) + 1;
-
-        if (cp > argsEnd || *cp == '\0') {
-            return -2;  // Off the end pointer or an empty argument is an error
-        }
-
-        CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
-
-        (*env)->SetObjectArrayElement(env, argsArray, i, str);
-        JNU_CHECK_EXCEPTION_RETURN(env, -3);
-    }
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
-    JNU_CHECK_EXCEPTION_RETURN(env, -4);
-    return 0;
+    return (uid_t)-1;
 }
 
 /**
  * Retrieve the command and arguments for the process and store them
  * into the Info object.
  */
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
     int mib[3], maxargs, nargs, i;
     size_t size;
     char *args, *cp, *sp, *np;
 
+    // Get the UID first. This is done here because it is cheap to do it here
+    // on other platforms like Linux/Solaris/AIX where the uid comes from the
+    // same source like the command line info.
+    unix_getUserInfo(env, jinfo, getUID(pid));
+
     // Get the maximum size of the arguments
     mib[0] = CTL_KERN;
     mib[1] = KERN_ARGMAX;
     size = sizeof(maxargs);
     if (sysctl(mib, 2, &maxargs, &size, NULL, 0) == -1) {
             JNU_ThrowByNameWithLastError(env,
-                    "java/lang/RuntimeException", "sysctl failed");
+                "java/lang/RuntimeException", "sysctl failed");
         return;
     }
 
@@ -437,7 +265,7 @@
 
     do {            // a block to break out of on error
         char *argsEnd;
-        jstring str = NULL;
+        jstring cmdexe = NULL;
 
         mib[0] = CTL_KERN;
         mib[1] = KERN_PROCARGS2;
@@ -445,7 +273,7 @@
         size = (size_t) maxargs;
         if (sysctl(mib, 3, args, &size, NULL, 0) == -1) {
             if (errno != EINVAL) {
-            JNU_ThrowByNameWithLastError(env,
+                JNU_ThrowByNameWithLastError(env,
                     "java/lang/RuntimeException", "sysctl failed");
             }
             break;
@@ -456,11 +284,7 @@
         argsEnd = &args[size];
 
         // Store the command executable path
-        if ((str = JNU_NewStringPlatform(env, cp)) == NULL) {
-            break;
-        }
-        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
-        if ((*env)->ExceptionCheck(env)) {
+        if ((cmdexe = JNU_NewStringPlatform(env, cp)) == NULL) {
             break;
         }
 
@@ -471,7 +295,7 @@
             }
         }
 
-        fillArgArray(env, jinfo, nargs, cp, argsEnd);
+        unix_fillArgArray(env, jinfo, nargs, cp, argsEnd, cmdexe, NULL);
     } while (0);
     // Free the arg buffer
     free(args);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m	Wed Jul 05 20:46:35 2017 +0200
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#import "apple_security_KeychainStore.h"
+
+#import <Security/Security.h>
+#import <Security/SecImportExport.h>
+#import <CoreServices/CoreServices.h>  // (for require() macros)
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+
+
+static JNF_CLASS_CACHE(jc_KeychainStore, "apple/security/KeychainStore");
+static JNF_MEMBER_CACHE(jm_createTrustedCertEntry, jc_KeychainStore, "createTrustedCertEntry", "(Ljava/lang/String;JJ[B)V");
+static JNF_MEMBER_CACHE(jm_createKeyEntry, jc_KeychainStore, "createKeyEntry", "(Ljava/lang/String;JJ[J[[B)V");
+
+static jstring getLabelFromItem(JNIEnv *env, SecKeychainItemRef inItem)
+{
+    OSStatus status;
+    jstring returnValue = NULL;
+    char *attribCString = NULL;
+
+    SecKeychainAttribute itemAttrs[] = { { kSecLabelItemAttr, 0, NULL } };
+    SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
+
+    status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
+
+    if(status) {
+        cssmPerror("getLabelFromItem: SecKeychainItemCopyContent", status);
+        goto errOut;
+    }
+
+    attribCString = malloc(itemAttrs[0].length + 1);
+    strncpy(attribCString, itemAttrs[0].data, itemAttrs[0].length);
+    attribCString[itemAttrs[0].length] = '\0';
+    returnValue = (*env)->NewStringUTF(env, attribCString);
+
+errOut:
+    SecKeychainItemFreeContent(&attrList, NULL);
+    if (attribCString) free(attribCString);
+    return returnValue;
+}
+
+static jlong getModDateFromItem(JNIEnv *env, SecKeychainItemRef inItem)
+{
+    OSStatus status;
+    SecKeychainAttribute itemAttrs[] = { { kSecModDateItemAttr, 0, NULL } };
+    SecKeychainAttributeList attrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
+    jlong returnValue = 0;
+
+    status = SecKeychainItemCopyContent(inItem, NULL, &attrList, NULL, NULL);
+
+    if(status) {
+        // This is almost always missing, so don't dump an error.
+        // cssmPerror("getModDateFromItem: SecKeychainItemCopyContent", status);
+        goto errOut;
+    }
+
+    memcpy(&returnValue, itemAttrs[0].data, itemAttrs[0].length);
+
+errOut:
+    SecKeychainItemFreeContent(&attrList, NULL);
+    return returnValue;
+}
+
+static void setLabelForItem(NSString *inLabel, SecKeychainItemRef inItem)
+{
+    OSStatus status;
+    const char *labelCString = [inLabel UTF8String];
+
+    // Set up attribute vector (each attribute consists of {tag, length, pointer}):
+    SecKeychainAttribute attrs[] = {
+        { kSecLabelItemAttr, strlen(labelCString), (void *)labelCString }
+    };
+
+    const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+
+    // Not changing data here, just attributes.
+    status = SecKeychainItemModifyContent(inItem, &attributes, 0, NULL);
+
+    if(status) {
+        cssmPerror("setLabelForItem: SecKeychainItemModifyContent", status);
+    }
+}
+
+/*
+ * Given a SecIdentityRef, do our best to construct a complete, ordered, and
+ * verified cert chain, returning the result in a CFArrayRef. The result is
+ * can be passed back to Java as a chain for a private key.
+ */
+static OSStatus completeCertChain(
+                                     SecIdentityRef         identity,
+                                     SecCertificateRef    trustedAnchor,    // optional additional trusted anchor
+                                     bool                 includeRoot,     // include the root in outArray
+                                     CFArrayRef            *outArray)        // created and RETURNED
+{
+    SecTrustRef                    secTrust = NULL;
+    SecPolicyRef                policy = NULL;
+    SecPolicySearchRef            policySearch = NULL;
+    SecTrustResultType            secTrustResult;
+    CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;            // not used
+    CFArrayRef                    certChain = NULL;   // constructed chain, CERTS ONLY
+    CFMutableArrayRef             subjCerts;            // passed to SecTrust
+    CFMutableArrayRef             certArray;            // returned array starting with
+                                                    //   identity
+    CFIndex                     numResCerts;
+    CFIndex                     dex;
+    OSStatus                     ortn;
+      SecCertificateRef             certRef;
+
+    /* First element in out array is the SecIdentity */
+    certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    CFArrayAppendValue(certArray, identity);
+
+    /* the single element in certs-to-be-evaluated comes from the identity */
+       ortn = SecIdentityCopyCertificate(identity, &certRef);
+    if(ortn) {
+        /* should never happen */
+        cssmPerror("SecIdentityCopyCertificate", ortn);
+        return ortn;
+    }
+
+    /*
+     * Now use SecTrust to get a complete cert chain, using all of the
+     * user's keychains to look for intermediate certs.
+     * NOTE this does NOT handle root certs which are not in the system
+     * root cert DB.
+     */
+    subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
+    CFArraySetValueAtIndex(subjCerts, 0, certRef);
+
+    /* the array owns the subject cert ref now */
+    CFRelease(certRef);
+
+    /* Get a SecPolicyRef for generic X509 cert chain verification */
+    ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
+                                 &CSSMOID_APPLE_X509_BASIC,
+                                 NULL,                // value
+                                 &policySearch);
+    if(ortn) {
+        /* should never happen */
+        cssmPerror("SecPolicySearchCreate", ortn);
+        goto errOut;
+    }
+    ortn = SecPolicySearchCopyNext(policySearch, &policy);
+    if(ortn) {
+        /* should never happen */
+        cssmPerror("SecPolicySearchCopyNext", ortn);
+        goto errOut;
+    }
+
+    /* build a SecTrustRef for specified policy and certs */
+    ortn = SecTrustCreateWithCertificates(subjCerts,
+                                          policy, &secTrust);
+    if(ortn) {
+        cssmPerror("SecTrustCreateWithCertificates", ortn);
+        goto errOut;
+    }
+
+    if(trustedAnchor) {
+        /*
+        * Tell SecTrust to trust this one in addition to the current
+         * trusted system-wide anchors.
+         */
+        CFMutableArrayRef newAnchors;
+        CFArrayRef currAnchors;
+
+        ortn = SecTrustCopyAnchorCertificates(&currAnchors);
+        if(ortn) {
+            /* should never happen */
+            cssmPerror("SecTrustCopyAnchorCertificates", ortn);
+            goto errOut;
+        }
+        newAnchors = CFArrayCreateMutableCopy(NULL,
+                                              CFArrayGetCount(currAnchors) + 1,
+                                              currAnchors);
+        CFRelease(currAnchors);
+        CFArrayAppendValue(newAnchors, trustedAnchor);
+        ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
+        CFRelease(newAnchors);
+        if(ortn) {
+            cssmPerror("SecTrustSetAnchorCertificates", ortn);
+            goto errOut;
+        }
+    }
+
+    /* evaluate: GO */
+    ortn = SecTrustEvaluate(secTrust, &secTrustResult);
+    if(ortn) {
+        cssmPerror("SecTrustEvaluate", ortn);
+        goto errOut;
+    }
+    switch(secTrustResult) {
+        case kSecTrustResultUnspecified:
+            /* cert chain valid, no special UserTrust assignments; drop thru */
+        case kSecTrustResultProceed:
+            /* cert chain valid AND user explicitly trusts this */
+            break;
+        default:
+            /*
+             * Cert chain construction failed.
+             * Just go with the single subject cert we were given; maybe the
+             * peer can complete the chain.
+             */
+            ortn = noErr;
+            goto errOut;
+    }
+
+    /* get resulting constructed cert chain */
+    ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
+    if(ortn) {
+        cssmPerror("SecTrustEvaluate", ortn);
+        goto errOut;
+    }
+
+    /*
+     * Copy certs from constructed chain to our result array, skipping
+     * the leaf (which is already there, as a SecIdentityRef) and possibly
+     * a root.
+     */
+    numResCerts = CFArrayGetCount(certChain);
+    if(numResCerts < 1) {
+        /*
+         * Can't happen: If chain doesn't verify to a root, we'd
+         * have bailed after SecTrustEvaluate().
+         */
+        ortn = noErr;
+        goto errOut;
+    }
+    if(!includeRoot) {
+        /* skip the last (root) cert) */
+        numResCerts--;
+    }
+    for(dex=1; dex<numResCerts; dex++) {
+        certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
+        CFArrayAppendValue(certArray, certRef);
+    }
+errOut:
+        /* clean up */
+        if(secTrust) {
+            CFRelease(secTrust);
+        }
+    if(subjCerts) {
+        CFRelease(subjCerts);
+    }
+    if(policy) {
+        CFRelease(policy);
+    }
+    if(policySearch) {
+        CFRelease(policySearch);
+    }
+    *outArray = certArray;
+    return ortn;
+}
+
+static void addIdentitiesToKeystore(JNIEnv *env, jobject keyStore)
+{
+    // Search the user keychain list for all identities. Identities are a certificate/private key association that
+    // can be chosen for a purpose such as signing or an SSL connection.
+    SecIdentitySearchRef identitySearch = NULL;
+    // Pass 0 if you want all identities returned by this search
+    OSStatus err = SecIdentitySearchCreate(NULL, 0, &identitySearch);
+    SecIdentityRef theIdentity = NULL;
+    OSErr searchResult = noErr;
+
+    do {
+        searchResult = SecIdentitySearchCopyNext(identitySearch, &theIdentity);
+
+        if (searchResult == noErr) {
+            // Get the cert from the identity, then generate a chain.
+            SecCertificateRef certificate;
+            SecIdentityCopyCertificate(theIdentity, &certificate);
+            CFArrayRef certChain = NULL;
+
+            // *** Should do something with this error...
+            err = completeCertChain(theIdentity, NULL, TRUE, &certChain);
+
+            CFIndex i, certCount = CFArrayGetCount(certChain);
+
+            // Make a java array of certificate data from the chain.
+            jclass byteArrayClass = (*env)->FindClass(env, "[B");
+            if (byteArrayClass == NULL) {
+                goto errOut;
+            }
+            jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
+            // Cleanup first then check for a NULL return code
+            (*env)->DeleteLocalRef(env, byteArrayClass);
+            if (javaCertArray == NULL) {
+                goto errOut;
+            }
+
+            // And, make an array of the certificate refs.
+            jlongArray certRefArray = (*env)->NewLongArray(env, certCount);
+            if (certRefArray == NULL) {
+                goto errOut;
+            }
+
+            SecCertificateRef currCertRef = NULL;
+
+            for (i = 0; i < certCount; i++) {
+                CSSM_DATA currCertData;
+
+                if (i == 0)
+                    currCertRef = certificate;
+                else
+                    currCertRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i);
+
+                bzero(&currCertData, sizeof(CSSM_DATA));
+                err = SecCertificateGetData(currCertRef, &currCertData);
+                jbyteArray encodedCertData = (*env)->NewByteArray(env, currCertData.Length);
+                if (encodedCertData == NULL) {
+                    goto errOut;
+                }
+                (*env)->SetByteArrayRegion(env, encodedCertData, 0, currCertData.Length, (jbyte *)currCertData.Data);
+                (*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
+                jlong certRefElement = ptr_to_jlong(currCertRef);
+                (*env)->SetLongArrayRegion(env, certRefArray, i, 1, &certRefElement);
+            }
+
+            // Get the private key.  When needed we'll export the data from it later.
+            SecKeyRef privateKeyRef;
+            err = SecIdentityCopyPrivateKey(theIdentity, &privateKeyRef);
+
+            // Find the label.  It's a 'blob', but we interpret as characters.
+            jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
+            if (alias == NULL) {
+                goto errOut;
+            }
+
+            // Find the creation date.
+            jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
+
+            // Call back to the Java object to create Java objects corresponding to this security object.
+            jlong nativeKeyRef = ptr_to_jlong(privateKeyRef);
+            JNFCallVoidMethod(env, keyStore, jm_createKeyEntry, alias, creationDate, nativeKeyRef, certRefArray, javaCertArray);
+        }
+    } while (searchResult == noErr);
+
+errOut:
+    if (identitySearch != NULL) {
+        CFRelease(identitySearch);
+    }
+}
+
+static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
+{
+    // Search the user keychain list for all X509 certificates.
+    SecKeychainSearchRef keychainItemSearch = NULL;
+    OSStatus err = SecKeychainSearchCreateFromAttributes(NULL, kSecCertificateItemClass, NULL, &keychainItemSearch);
+    SecKeychainItemRef theItem = NULL;
+    OSErr searchResult = noErr;
+
+    do {
+        searchResult = SecKeychainSearchCopyNext(keychainItemSearch, &theItem);
+
+        if (searchResult == noErr) {
+            // Make a byte array with the DER-encoded contents of the certificate.
+            SecCertificateRef certRef = (SecCertificateRef)theItem;
+            CSSM_DATA currCertificate;
+            err = SecCertificateGetData(certRef, &currCertificate);
+            jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
+            if (certData == NULL) {
+                goto errOut;
+            }
+            (*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
+
+            // Find the label.  It's a 'blob', but we interpret as characters.
+            jstring alias = getLabelFromItem(env, theItem);
+            if (alias == NULL) {
+                goto errOut;
+            }
+
+            // Find the creation date.
+            jlong creationDate = getModDateFromItem(env, theItem);
+
+            // Call back to the Java object to create Java objects corresponding to this security object.
+            jlong nativeRef = ptr_to_jlong(certRef);
+            JNFCallVoidMethod(env, keyStore, jm_createTrustedCertEntry, alias, nativeRef, creationDate, certData);
+        }
+    } while (searchResult == noErr);
+
+errOut:
+    if (keychainItemSearch != NULL) {
+        CFRelease(keychainItemSearch);
+    }
+}
+
+/*
+ * Class:     apple_security_KeychainStore
+ * Method:    _getEncodedKeyData
+ * Signature: (J)[B
+     */
+JNIEXPORT jbyteArray JNICALL Java_apple_security_KeychainStore__1getEncodedKeyData
+(JNIEnv *env, jobject this, jlong keyRefLong, jcharArray passwordObj)
+{
+    SecKeyRef keyRef = (SecKeyRef)jlong_to_ptr(keyRefLong);
+    SecKeyImportExportParameters paramBlock;
+    OSStatus err = noErr;
+    CFDataRef exportedData = NULL;
+    jbyteArray returnValue = NULL;
+    CFStringRef passwordStrRef = NULL;
+
+    jsize passwordLen = 0;
+    jchar *passwordChars = NULL;
+
+    if (passwordObj) {
+        passwordLen = (*env)->GetArrayLength(env, passwordObj);
+
+        if (passwordLen > 0) {
+            passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
+            if (passwordChars == NULL) {
+                goto errOut;
+            }
+            passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
+        }
+    }
+
+    paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+    // Note that setting the flags field **requires** you to pass in a password of some kind.  The keychain will not prompt you.
+    paramBlock.flags = 0;
+    paramBlock.passphrase = passwordStrRef;
+    paramBlock.alertTitle = NULL;
+    paramBlock.alertPrompt = NULL;
+    paramBlock.accessRef = NULL;
+    paramBlock.keyUsage = CSSM_KEYUSE_ANY;
+    paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
+
+    err = SecKeychainItemExport(keyRef, kSecFormatPKCS12, 0, &paramBlock, &exportedData);
+
+    if (err == noErr) {
+        CFIndex size = CFDataGetLength(exportedData);
+        returnValue = (*env)->NewByteArray(env, size);
+        if (returnValue == NULL) {
+            goto errOut;
+        }
+        (*env)->SetByteArrayRegion(env, returnValue, 0, size, (jbyte *)CFDataGetBytePtr(exportedData));
+    }
+
+errOut:
+    if (exportedData) CFRelease(exportedData);
+    if (passwordStrRef) CFRelease(passwordStrRef);
+
+    return returnValue;
+}
+
+
+/*
+ * Class:     apple_security_KeychainStore
+ * Method:    _scanKeychain
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1scanKeychain
+(JNIEnv *env, jobject this)
+{
+    // Look for 'identities' -- private key and certificate chain pairs -- and add those.
+    // Search for these first, because a certificate that's found here as part of an identity will show up
+    // again later as a certificate.
+    addIdentitiesToKeystore(env, this);
+
+    // Scan current keychain for trusted certificates.
+    addCertificatesToKeystore(env, this);
+
+}
+
+/*
+ * Class:     apple_security_KeychainStore
+ * Method:    _addItemToKeychain
+ * Signature: (Ljava/lang/String;[B)I
+*/
+JNIEXPORT jlong JNICALL Java_apple_security_KeychainStore__1addItemToKeychain
+(JNIEnv *env, jobject this, jstring alias, jboolean isCertificate, jbyteArray rawDataObj, jcharArray passwordObj)
+{
+    OSStatus err;
+    jlong returnValue = 0;
+
+JNF_COCOA_ENTER(env);
+
+    jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
+    jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
+    if (rawData == NULL) {
+        goto errOut;
+    }
+
+    CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
+    CFArrayRef createdItems = NULL;
+
+    SecKeychainRef defaultKeychain = NULL;
+    SecKeychainCopyDefault(&defaultKeychain);
+
+    SecExternalItemType dataType = (isCertificate == JNI_TRUE ? kSecFormatX509Cert : kSecFormatWrappedPKCS8);
+
+    // Convert the password obj into a CFStringRef that the keychain importer can use for encryption.
+    SecKeyImportExportParameters paramBlock;
+    CFStringRef passwordStrRef = NULL;
+
+    jsize passwordLen = 0;
+    jchar *passwordChars = NULL;
+
+    if (passwordObj) {
+        passwordLen = (*env)->GetArrayLength(env, passwordObj);
+        passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
+        passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
+    }
+
+    paramBlock.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+    // Note that setting the flags field **requires** you to pass in a password of some kind.  The keychain will not prompt you.
+    paramBlock.flags = 0;
+    paramBlock.passphrase = passwordStrRef;
+    paramBlock.alertTitle = NULL;
+    paramBlock.alertPrompt = NULL;
+    paramBlock.accessRef = NULL;
+    paramBlock.keyUsage = CSSM_KEYUSE_ANY;
+    paramBlock.keyAttributes = CSSM_KEYATTR_RETURN_DEFAULT;
+
+    err = SecKeychainItemImport(cfDataToImport, NULL, &dataType, NULL,
+                                0, &paramBlock, defaultKeychain, &createdItems);
+
+    if (err == noErr) {
+        SecKeychainItemRef anItem = (SecKeychainItemRef)CFArrayGetValueAtIndex(createdItems, 0);
+
+        // Don't bother labeling keys. They become part of an identity, and are not an accessible part of the keychain.
+        if (CFGetTypeID(anItem) == SecCertificateGetTypeID()) {
+            setLabelForItem(JNFJavaToNSString(env, alias), anItem);
+        }
+
+        // Retain the item, since it will be released once when the array holding it gets released.
+        CFRetain(anItem);
+        returnValue = ptr_to_jlong(anItem);
+    } else {
+        cssmPerror("_addItemToKeychain: SecKeychainItemImport", err);
+    }
+
+    (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT);
+
+    if (createdItems != NULL) {
+        CFRelease(createdItems);
+    }
+
+errOut: ;
+
+JNF_COCOA_EXIT(env);
+
+    return returnValue;
+}
+
+/*
+ * Class:     apple_security_KeychainStore
+ * Method:    _removeItemFromKeychain
+ * Signature: (J)I
+*/
+JNIEXPORT jint JNICALL Java_apple_security_KeychainStore__1removeItemFromKeychain
+(JNIEnv *env, jobject this, jlong keychainItem)
+{
+    SecKeychainItemRef itemToRemove = jlong_to_ptr(keychainItem);
+    return SecKeychainItemDelete(itemToRemove);
+}
+
+/*
+ * Class:     apple_security_KeychainStore
+ * Method:    _releaseKeychainItemRef
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_apple_security_KeychainStore__1releaseKeychainItemRef
+(JNIEnv *env, jobject this, jlong keychainItem)
+{
+    SecKeychainItemRef itemToFree = jlong_to_ptr(keychainItem);
+    CFRelease(itemToFree);
+}
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java	Wed Jul 05 20:46:35 2017 +0200
@@ -225,8 +225,34 @@
         public Optional<String> command();
 
         /**
+         * Returns the command line of the process.
+         * <p>
+         * If {@link #command command()} and  {@link #arguments arguments()} return
+         * non-empty optionals, this is simply a convenience method which concatenates
+         * the values of the two functions separated by spaces. Otherwise it will return a
+         * best-effort, platform dependent representation of the command line.
+         *
+         * @apiNote Note that the returned executable pathname and the
+         *          arguments may be truncated on some platforms due to system
+         *          limitations.
+         *          <p>
+         *          The executable pathname may contain only the
+         *          name of the executable without the full path information.
+         *          It is undecideable whether white space separates different
+         *          arguments or is part of a single argument.
+         *
+         * @return an {@code Optional<String>} of the command line
+         *         of the process
+         */
+        public Optional<String> commandLine();
+
+        /**
          * Returns an array of Strings of the arguments of the process.
          *
+         * @apiNote On some platforms, native applications are free to change
+         *          the arguments array after startup and this method may only
+         *          show the changed values.
+         *
          * @return an {@code Optional<String[]>} of the arguments of the process
          */
         public Optional<String[]> arguments();
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Wed Jul 05 20:46:35 2017 +0200
@@ -472,7 +472,7 @@
     /**
      * Implementation of ProcessHandle.Info.
      * Information snapshot about a process.
-     * The attributes of a process vary by operating system and not available
+     * The attributes of a process vary by operating system and are not available
      * in all implementations.  Additionally, information about other processes
      * is limited by the operating system privileges of the process making the request.
      * If a value is not available, either a {@code null} or {@code -1} is stored.
@@ -496,6 +496,7 @@
         private native void info0(long pid);
 
         String command;
+        String commandLine;
         String[] arguments;
         long startTime;
         long totalTime;
@@ -503,6 +504,7 @@
 
         Info() {
             command = null;
+            commandLine = null;
             arguments = null;
             startTime = -1L;
             totalTime = -1L;
@@ -539,6 +541,15 @@
         }
 
         @Override
+        public Optional<String> commandLine() {
+            if (command != null && arguments != null) {
+                return Optional.of(command + " " + String.join(" ", arguments));
+            } else {
+                return Optional.ofNullable(commandLine);
+            }
+        }
+
+        @Override
         public Optional<String[]> arguments() {
             return Optional.ofNullable(arguments);
         }
@@ -580,6 +591,11 @@
                 sb.append("args: ");
                 sb.append(Arrays.toString(arguments));
             }
+            if (commandLine != null) {
+                if (sb.length() != 0) sb.append(", ");
+                sb.append("cmdLine: ");
+                sb.append(commandLine);
+            }
             if (startTime > 0) {
                 if (sb.length() != 0) sb.append(", ");
                 sb.append("startTime: ");
--- a/jdk/src/java.base/share/classes/java/lang/Shutdown.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Shutdown.java	Wed Jul 05 20:46:35 2017 +0200
@@ -86,10 +86,10 @@
      *               to be registered even if the shutdown is in progress.
      * @params hook  the hook to be registered
      *
-     * @throw IllegalStateException
-     *        if registerShutdownInProgress is false and shutdown is in progress; or
-     *        if registerShutdownInProgress is true and the shutdown process
-     *           already passes the given slot
+     * @throws IllegalStateException
+     *         if registerShutdownInProgress is false and shutdown is in progress; or
+     *         if registerShutdownInProgress is true and the shutdown process
+     *         already passes the given slot
      */
     static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
         synchronized (lock) {
--- a/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java	Wed Jul 05 20:46:35 2017 +0200
@@ -65,10 +65,13 @@
                 return false;
             }
             assert queue == this;
-            r.queue = ENQUEUED;
             r.next = (head == null) ? r : head;
             head = r;
             queueLength++;
+            // Update r.queue *after* adding to list, to avoid race
+            // with concurrent enqueued checks and fast-path poll().
+            // Volatiles ensure ordering.
+            r.queue = ENQUEUED;
             if (r instanceof FinalReference) {
                 sun.misc.VM.addFinalRefCount(1);
             }
@@ -80,10 +83,13 @@
     private Reference<? extends T> reallyPoll() {       /* Must hold lock */
         Reference<? extends T> r = head;
         if (r != null) {
+            r.queue = NULL;
+            // Update r.queue *before* removing from list, to avoid
+            // race with concurrent enqueued checks and fast-path
+            // poll().  Volatiles ensure ordering.
             @SuppressWarnings("unchecked")
             Reference<? extends T> rn = r.next;
             head = (rn == r) ? null : rn;
-            r.queue = NULL;
             r.next = r;
             queueLength--;
             if (r instanceof FinalReference) {
--- a/jdk/src/java.base/share/classes/java/net/ContentHandler.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/ContentHandler.java	Wed Jul 05 20:46:35 2017 +0200
@@ -47,7 +47,7 @@
  * If no content handler could be {@linkplain URLConnection#getContent() found},
  * URLConnection will look for a content handler in a user-definable set of places.
  * Users can define a vertical-bar delimited set of class prefixes
- * to search through by defining the <i>{@value java.net.URLConnection#contentPathProp}</i>
+ * to search through by defining the <i>{@link java.net.URLConnection#contentPathProp}</i>
  * property. The class name must be of the form:
  * <blockquote>
  *     <i>{package-prefix}.{major}.{minor}</i>
--- a/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Wed Jul 05 20:46:35 2017 +0200
@@ -206,7 +206,7 @@
      * @param   hostname the Host name
      * @param   port    The port number
      * @throws IllegalArgumentException if the port parameter is outside the range
-     * of valid port values, or if the hostname parameter is <TT>null</TT>.
+     * of valid port values, or if the hostname parameter is {@code null}.
      * @throws SecurityException if a security manager is present and
      *                           permission to resolve the host name is
      *                           denied.
@@ -244,7 +244,7 @@
      * @param   port    The port number
      * @throws IllegalArgumentException if the port parameter is outside
      *                  the range of valid port values, or if the hostname
-     *                  parameter is <TT>null</TT>.
+     *                  parameter is {@code null}.
      * @see     #isUnresolved()
      * @return  a {@code InetSocketAddress} representing the unresolved
      *          socket address
--- a/jdk/src/java.base/share/classes/java/net/spi/package-info.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/net/spi/package-info.java	Wed Jul 05 20:46:35 2017 +0200
@@ -24,7 +24,7 @@
  */
 
 /**
- * Service-provider classes for the <tt>{@link java.net}</tt> package.
+ * Service-provider classes for the {@link java.net} package.
  *
  * <p> Only developers who are defining new URL stream handler providers
  * should need to make direct use of this package.
--- a/jdk/src/java.base/share/classes/java/nio/Buffer.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/nio/Buffer.java	Wed Jul 05 20:46:35 2017 +0200
@@ -215,8 +215,8 @@
      * {@code put(src)} when the parameter is the {@code Buffer} on which the
      * method is being invoked.
      *
-     * @returns  IllegalArgumentException
-     *           With a message indicating equal source and target buffers
+     * @return  IllegalArgumentException
+     *          With a message indicating equal source and target buffers
      */
     static IllegalArgumentException createSameBufferException() {
         return new IllegalArgumentException("The source buffer is this buffer");
--- a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java	Wed Jul 05 20:46:35 2017 +0200
@@ -618,9 +618,12 @@
      * @throws IOException if there is an I/O problem with the keystore data.
      * @throws NullPointerException if stream is {@code null}.
      *
-     * @since 1.9
+     * @since 9
      */
     public boolean engineProbe(InputStream stream) throws IOException {
+        if (stream == null) {
+            throw new NullPointerException("input stream must not be null");
+        }
         return false;
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java	Wed Jul 05 20:46:35 2017 +0200
@@ -273,6 +273,10 @@
  *
  * </ol>
  *
+ * <p> For category <i>General</i>, <i>Character</i>, <i>Numberic</i>,
+ * <i>Integral</i> and <i>Date/Time</i> conversion, unless otherwise specified,
+ * if the argument <i>arg</i> is {@code null}, then the result is "{@code null}".
+ *
  * <p> The following table summarizes the supported conversions.  Conversions
  * denoted by an upper-case character (i.e. {@code 'B'}, {@code 'H'},
  * {@code 'S'}, {@code 'C'}, {@code 'X'}, {@code 'E'}, {@code 'G'},
@@ -301,14 +305,12 @@
  *
  * <tr><td valign="top"> {@code 'h'}, {@code 'H'}
  *     <td valign="top"> general
- *     <td> If the argument <i>arg</i> is {@code null}, then the result is
- *     "{@code null}".  Otherwise, the result is obtained by invoking
+ *     <td> The result is obtained by invoking
  *     {@code Integer.toHexString(arg.hashCode())}.
  *
  * <tr><td valign="top"> {@code 's'}, {@code 'S'}
  *     <td valign="top"> general
- *     <td> If the argument <i>arg</i> is {@code null}, then the result is
- *     "{@code null}".  If <i>arg</i> implements {@link Formattable}, then
+ *     <td> If <i>arg</i> implements {@link Formattable}, then
  *     {@link Formattable#formatTo arg.formatTo} is invoked. Otherwise, the
  *     result is obtained by invoking {@code arg.toString()}.
  *
@@ -683,6 +685,10 @@
  * methods such as {@link String#format(String,Object...) String.format} and
  * {@link java.io.PrintStream#printf(String,Object...) PrintStream.printf}.
  *
+ * <p> For category <i>General</i>, <i>Character</i>, <i>Numberic</i>,
+ * <i>Integral</i> and <i>Date/Time</i> conversion, unless otherwise specified,
+ * if the argument <i>arg</i> is {@code null}, then the result is "{@code null}".
+ *
  * <p> Conversions denoted by an upper-case character (i.e. {@code 'B'},
  * {@code 'H'}, {@code 'S'}, {@code 'C'}, {@code 'X'}, {@code 'E'},
  * {@code 'G'}, {@code 'A'}, and {@code 'T'}) are the same as those for the
@@ -722,9 +728,8 @@
  *     <td valign="top"> <code>'&#92;u0068'</code>
  *     <td> Produces a string representing the hash code value of the object.
  *
- *     <p> If the argument, <i>arg</i> is {@code null}, then the
- *     result is "{@code null}".  Otherwise, the result is obtained
- *     by invoking {@code Integer.toHexString(arg.hashCode())}.
+ *     <p> The result is obtained by invoking
+ *     {@code Integer.toHexString(arg.hashCode())}.
  *
  *     <p> If the {@code '#'} flag is given, then a {@link
  *     FormatFlagsConversionMismatchException} will be thrown.
@@ -737,8 +742,7 @@
  *     <td valign="top"> <code>'&#92;u0073'</code>
  *     <td> Produces a string.
  *
- *     <p> If the argument is {@code null}, then the result is
- *     "{@code null}".  If the argument implements {@link Formattable}, then
+ *     <p> If the argument implements {@link Formattable}, then
  *     its {@link Formattable#formatTo formatTo} method is invoked.
  *     Otherwise, the result is obtained by invoking the argument's
  *     {@code toString()} method.
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java	Wed Jul 05 20:46:35 2017 +0200
@@ -39,7 +39,7 @@
  * <p> Every implementation of the Java platform is required to support the
  * following standard {@code SSLContext} protocol:
  * <ul>
- * <li><tt>TLSv1</tt></li>
+ * <li>{@code TLSv1}</li>
  * </ul>
  * This protocol is described in the <a href=
  * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLException.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLException.java	Wed Jul 05 20:46:35 2017 +0200
@@ -53,13 +53,13 @@
     }
 
     /**
-     * Creates a <code>SSLException</code> with the specified
+     * Creates a {@code SSLException} with the specified
      * detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
      *          by the {@link #getMessage()} method).
      * @param cause the cause (which is saved for later retrieval by the
-     *          {@link #getCause()} method).  (A <tt>null</tt> value is
+     *          {@link #getCause()} method).  (A {@code null} value is
      *          permitted, and indicates that the cause is nonexistent or
      *          unknown.)
      * @since 1.5
@@ -70,13 +70,13 @@
     }
 
     /**
-     * Creates a <code>SSLException</code> with the specified cause
-     * and a detail message of <tt>(cause==null ? null : cause.toString())</tt>
+     * Creates a {@code SSLException} with the specified cause
+     * and a detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
-     * <tt>cause</tt>).
+     * {@code cause}).
      *
      * @param cause the cause (which is saved for later retrieval by the
-     *          {@link #getCause()} method).  (A <tt>null</tt> value is
+     *          {@link #getCause()} method).  (A {@code null} value is
      *          permitted, and indicates that the cause is nonexistent or
      *          unknown.)
      * @since 1.5
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java	Wed Jul 05 20:46:35 2017 +0200
@@ -139,6 +139,7 @@
     }
 
     public static void recreateJimage(Path jimageFile,
+            String jdataName,
             Set<Archive> archives,
             Map<String, Set<String>> modulePackages)
             throws IOException {
@@ -159,12 +160,7 @@
             throw new UnsupportedOperationException("Not supported, no external file "
                     + "in a jimage file");
         }, entriesForModule, order);
-        String fileName = jimageFile.getFileName().toString();
-        if (fileName.endsWith(IMAGE_EXT)) {
-            fileName = fileName.substring(0, fileName.length()
-                    - BasicImageWriter.IMAGE_EXT.length());
-        }
-        generateJImage(jimageFile, fileName, resources, order);
+        generateJImage(jimageFile, jdataName, resources, order);
     }
 
     private void writeImage(String fileName,
--- a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java	Wed Jul 05 20:46:35 2017 +0200
@@ -52,7 +52,7 @@
      * Initializes a new instance of this class.
      *
      * @throws SecurityException if a security manager is installed and it denies
-     *         {@link RuntimePermission}<tt>("ftpClientProvider")</tt>
+     *         {@link RuntimePermission}{@code ("ftpClientProvider")}
      */
     protected FtpClientProvider() {
         SecurityManager sm = System.getSecurityManager();
@@ -108,7 +108,7 @@
      * <ol>
      *
      *   <li><p> If the system property
-     *   <tt>java.net.FtpClientProvider</tt> is defined then it is
+     *   {@code java.net.FtpClientProvider} is defined then it is
      *   taken to be the fully-qualified name of a concrete provider class.
      *   The class is loaded and instantiated; if this process fails then an
      *   unspecified unchecked error or exception is thrown.  </p></li>
@@ -116,8 +116,8 @@
      *   <li><p> If a provider class has been installed in a jar file that is
      *   visible to the system class loader, and that jar file contains a
      *   provider-configuration file named
-     *   <tt>java.net.FtpClientProvider</tt> in the resource
-     *   directory <tt>META-INF/services</tt>, then the first class name
+     *   {@code java.net.FtpClientProvider} in the resource
+     *   directory {@code META-INF/services}, then the first class name
      *   specified in that file is taken.  The class is loaded and
      *   instantiated; if this process fails then an unspecified unchecked error or exception is
      *   thrown.  </p></li>
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Wed Jul 05 20:46:35 2017 +0200
@@ -191,7 +191,7 @@
 
     /**
      * return the first token.
-     * @returns the token
+     * @return the token
      * @throws IOException if <code>Negotiator.getNegotiator()</code> or
      *                     <code>Negotiator.firstToken()</code> failed.
      */
@@ -219,7 +219,7 @@
     /**
      * return more tokens
      * @param token the token to be fed into <code>negotiator.nextToken()</code>
-     * @returns the token
+     * @return the token
      * @throws IOException if <code>negotiator.nextToken()</code> throws Exception.
      *  May happen if the input token is invalid.
      */
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java	Wed Jul 05 20:46:35 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -391,8 +391,7 @@
     private static native boolean isIPv6Available0();
 
     /*
-     * Returns 1 for Windows versions that support exclusive binding by default, 0
-     * for those that do not, and -1 for Solaris/Linux/Mac OS
+     * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
      */
     private static native int isExclusiveBindAvailable();
 
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java	Wed Jul 05 20:46:35 2017 +0200
@@ -98,8 +98,8 @@
      * Sole constructor.
      *
      * @param annotationClass the class object for the annotation type
-     * @throw IllegalArgumentException if the specified class object for
-     *     does not represent a valid annotation type
+     * @throws IllegalArgumentException if the specified class object for
+     *         does not represent a valid annotation type
      */
     private AnnotationType(final Class<? extends Annotation> annotationClass) {
         if (!annotationClass.isAnnotation())
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java	Wed Jul 05 20:46:35 2017 +0200
@@ -178,6 +178,26 @@
             p = new com.sun.crypto.provider.SunJCE();
         } else if (provName.equals("SunJSSE") || provName.equals("com.sun.net.ssl.internal.ssl.Provider")) {
             p = new com.sun.net.ssl.internal.ssl.Provider();
+        } else if (provName.equals("Apple") || provName.equals("apple.security.AppleProvider")) {
+            // need to use reflection since this class only exists on MacOsx
+            p = AccessController.doPrivileged(new PrivilegedAction<Provider>() {
+                public Provider run() {
+                    try {
+                        Class<?> c = Class.forName("apple.security.AppleProvider");
+                        if (Provider.class.isAssignableFrom(c)) {
+                            return (Provider) c.newInstance();
+                        } else {
+                            return null;
+                        }
+                    } catch (Exception ex) {
+                        if (debug != null) {
+                        debug.println("Error loading provider Apple");
+                        ex.printStackTrace();
+                    }
+                    return null;
+                }
+             }
+             });
         } else {
             if (isLoading) {
                 // because this method is synchronized, this can only
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAPadding.java	Wed Jul 05 20:46:35 2017 +0200
@@ -319,18 +319,17 @@
             }
             // generate non-zero padding bytes
             // use a buffer to reduce calls to SecureRandom
-            byte[] r = new byte[64];
-            int i = -1;
-            while (psSize-- > 0) {
-                int b;
-                do {
-                    if (i < 0) {
-                        random.nextBytes(r);
-                        i = r.length - 1;
+            while (psSize > 0) {
+                // extra bytes to avoid zero bytes,
+                // number of zero bytes <= 4 in 98% cases
+                byte[] r = new byte[psSize + 4];
+                random.nextBytes(r);
+                for (int i = 0; i < r.length && psSize > 0; i++) {
+                    if (r[i] != 0) {
+                        padded[k++] = r[i];
+                        psSize--;
                     }
-                    b = r[i--] & 0xff;
-                } while (b == 0);
-                padded[k++] = (byte)b;
+                }
             }
         }
         return padded;
--- a/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template	Wed Jul 05 20:46:35 2017 +0200
@@ -92,7 +92,7 @@
     }
 
     /**
-     * @returns a list of candidate locales to search from.
+     * @return a list of candidate locales to search from.
      * @exception NullPointerException if baseName or locale is null.
      */
     @Override
--- a/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java	Wed Jul 05 20:46:35 2017 +0200
@@ -56,7 +56,7 @@
  *
  * }</pre></blockquote>
  *
- * <p> The <tt>init</tt> method is invoked by the <tt>PreHashedMap</tt>
+ * <p> The {@code init} method is invoked by the {@code PreHashedMap}
  * constructor with an object array long enough for the map's rows.  The method
  * must construct the hash chain for each row and store it in the appropriate
  * element of the array.
@@ -73,7 +73,7 @@
  * methods in the {@link java.util.Collections} utility class.
  *
  * <p> In the JDK build, subclasses of this class are typically created via the
- * <tt>Hasher</tt> program in the <tt>make/tools/Hasher</tt> directory.
+ * {@code Hasher} program in the {@code make/tools/Hasher} directory.
  *
  * @author Mark Reinhold
  * @since 1.5
@@ -95,7 +95,7 @@
      * Creates a new map.
      *
      * <p> This constructor invokes the {@link #init init} method, passing it a
-     * newly-constructed row array that is <tt>rows</tt> elements long.
+     * newly-constructed row array that is {@code rows} elements long.
      *
      * @param rows
      *        The number of rows in the map
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java	Wed Jul 05 20:46:35 2017 +0200
@@ -201,7 +201,7 @@
          *
          * @param baseName the resource bundle base name.
          *        locale   the requested locale for the resource bundle.
-         * @returns a list of candidate locales to search from.
+         * @return a list of candidate locales to search from.
          * @exception NullPointerException if baseName or locale is null.
          */
         @Override
--- a/jdk/src/java.base/share/native/libjli/java.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjli/java.c	Wed Jul 05 20:46:35 2017 +0200
@@ -1082,15 +1082,6 @@
             AddOption("-Xverify:remote", NULL);
         } else if (JLI_StrCmp(arg, "-noverify") == 0) {
             AddOption("-Xverify:none", NULL);
-        } else if (JLI_StrCCmp(arg, "-prof") == 0) {
-            char *p = arg + 5;
-            char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 50);
-            if (*p) {
-                sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
-            } else {
-                sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
-            }
-            AddOption(tmp, NULL);
         } else if (JLI_StrCCmp(arg, "-ss") == 0 ||
                    JLI_StrCCmp(arg, "-oss") == 0 ||
                    JLI_StrCCmp(arg, "-ms") == 0 ||
--- a/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/solaris/native/libjava/ProcessHandleImpl_solaris.c	Wed Jul 05 20:46:35 2017 +0200
@@ -24,368 +24,28 @@
  */
 
 #include "jni.h"
-#include "jni_util.h"
-#include "java_lang_ProcessHandleImpl.h"
-#include "java_lang_ProcessHandleImpl_Info.h"
 
+#include "ProcessHandleImpl_unix.h"
 
-#include <stdio.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
 #include <procfs.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <limits.h>
 
-/**
- * Implementations of ProcessHandleImpl functions that are
- * NOT common to all Unix variants:
- * - getProcessPids0(pid, pidArray)
- *
- * Implementations of ProcessHandleImpl_Info
- * - totalTime, startTime
- * - Command
- * - Arguments
+/*
+ * Implementation of native ProcessHandleImpl functions for Solaris.
+ * See ProcessHandleImpl_unix.c for more details.
  */
 
-/*
- * Signatures for internal OS specific functions.
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
-                                     jlong *totalTime, jlong* startTime,
-                                     uid_t *uid);
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid);
+void os_initNative(JNIEnv *env, jclass clazz) {}
 
-extern jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandle.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
-
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
-
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl_Info
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
-    CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env,
-        clazz, "command", "Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env,
-        clazz, "arguments", "[Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env,
-        clazz, "totalTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env,
-        clazz, "startTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env,
-        clazz, "user", "Ljava/lang/String;"));
+jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+                    jlongArray jparentArray, jlongArray jstimesArray) {
+    return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
 }
 
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
-    clock_ticks_per_second = sysconf(_SC_CLK_TCK);
+pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
+    return unix_getParentPidAndTimings(env, pid, total, start);
 }
 
-/*
- * Check if a process is alive.
- * Return the start time (ms since 1970) if it is available.
- * If the start time is not available return 0.
- * If the pid is invalid, return -1.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    isAlive0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_isAlive0(JNIEnv *env, jobject obj, jlong jpid) {
-    pid_t pid = (pid_t) jpid;
-    jlong startTime = 0L;
-    jlong totalTime = 0L;
-    uid_t uid = -1;
-    pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime, &uid);
-    return (ppid < 0) ? -1 : startTime;
+void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+    unix_getCmdlineAndUserInfo(env, jinfo, pid);
 }
 
-/*
- * Returns the parent pid of the requested pid.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    parent0
- * Signature: (J)J
- */
-JNIEXPORT jlong JNICALL
-Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
-                                         jobject obj,
-                                         jlong jpid,
-                                         jlong startTime) {
-    pid_t pid = (pid_t) jpid;
-    pid_t ppid = -1;
-
-    if (pid == getpid()) {
-        ppid = getppid();
-    } else {
-        jlong start = 0L;
-        jlong total = 0L;
-        uid_t uid = -1;
-
-        pid_t ppid = getStatInfo(env, pid, &total, &start, &uid);
-        if (start != startTime
-            && start != 0
-            && startTime != 0) {
-            ppid = -1;
-        }
-    }
-    return (jlong) ppid;
-}
-
-/*
- * Returns the children of the requested pid and optionally each parent.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    getChildPids
- * Signature: (J[J)I
- *
- * Reads /proc and accumulates any process who parent pid matches.
- * The resulting pids are stored into the array of longs.
- * The number of pids is returned if they all fit.
- * If the array is too short, the desired length is returned.
- */
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
-                                                 jclass clazz,
-                                                 jlong jpid,
-                                                 jlongArray jarray,
-                                                 jlongArray jparentArray,
-                                                 jlongArray jstimesArray) {
-    DIR* dir;
-    struct dirent* ptr;
-    pid_t pid = (pid_t) jpid;
-    jlong* pids = NULL;
-    jlong* ppids = NULL;
-    jlong* stimes = NULL;
-    jsize parentArraySize = 0;
-    jsize arraySize = 0;
-    jsize stimesSize = 0;
-    jsize count = 0;
-    char procname[32];
-
-    arraySize = (*env)->GetArrayLength(env, jarray);
-    JNU_CHECK_EXCEPTION_RETURN(env, 0);
-    if (jparentArray != NULL) {
-        parentArraySize = (*env)->GetArrayLength(env, jparentArray);
-        JNU_CHECK_EXCEPTION_RETURN(env, 0);
-
-        if (arraySize != parentArraySize) {
-            JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
-            return 0;
-        }
-    }
-    if (jstimesArray != NULL) {
-        stimesSize = (*env)->GetArrayLength(env, jstimesArray);
-        JNU_CHECK_EXCEPTION_RETURN(env, -1);
-
-        if (arraySize != stimesSize) {
-            JNU_ThrowIllegalArgumentException(env, "array sizes not equal");
-            return 0;
-        }
-    }
-
-    /*
-     * To locate the children we scan /proc looking for files that have a
-     * positive integer as a filename.
-     */
-    if ((dir = opendir("/proc")) == NULL) {
-        JNU_ThrowByNameWithLastError(env,
-            "java/lang/Runtime", "Unable to open /proc");
-        return 0;
-    }
-
-    do { // Block to break out of on Exception
-        pids = (*env)->GetLongArrayElements(env, jarray, NULL);
-        if (pids == NULL) {
-            break;
-        }
-        if (jparentArray != NULL) {
-            ppids  = (*env)->GetLongArrayElements(env, jparentArray, NULL);
-            if (ppids == NULL) {
-                break;
-            }
-        }
-        if (jstimesArray != NULL) {
-            stimes  = (*env)->GetLongArrayElements(env, jstimesArray, NULL);
-            if (stimes == NULL) {
-                break;
-            }
-        }
-
-        while ((ptr = readdir(dir)) != NULL) {
-            pid_t ppid = 0;
-            jlong totalTime = 0L;
-            jlong startTime = 0L;
-            uid_t uid; // value unused
-
-            /* skip files that aren't numbers */
-            pid_t childpid = (pid_t) atoi(ptr->d_name);
-            if ((int) childpid <= 0) {
-                continue;
-            }
-
-            // Read /proc/pid/stat and get the parent pid, and start time
-            ppid = getStatInfo(env, childpid, &totalTime, &startTime, &uid);
-            if (ppid >= 0 && (pid == 0 || ppid == pid)) {
-                if (count < arraySize) {
-                    // Only store if it fits
-                    pids[count] = (jlong) childpid;
-
-                    if (ppids != NULL) {
-                        // Store the parent Pid
-                        ppids[count] = (jlong) ppid;
-                    }
-                    if (stimes != NULL) {
-                        // Store the process start time
-                        stimes[count] = startTime;
-                    }
-                }
-                count++; // Count to tabulate size needed
-            }
-        }
-    } while (0);
-
-    if (pids != NULL) {
-        (*env)->ReleaseLongArrayElements(env, jarray, pids, 0);
-    }
-    if (ppids != NULL) {
-        (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0);
-    }
-    if (stimes != NULL) {
-        (*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0);
-    }
-
-    closedir(dir);
-    // If more pids than array had size for; count will be greater than array size
-    return count;
-}
-
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
- */
-
-/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class:     java_lang_ProcessHandleImpl_Info
- * Method:    info0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
-                                                 jobject jinfo,
-                                                  jlong jpid) {
-    pid_t pid = (pid_t) jpid;
-    jlong startTime = 0L;
-    jlong totalTime = 0L;
-    uid_t uid = -1;
-    pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime, &uid);
-
-    getCmdlineInfo(env, jinfo, pid);
-
-    if (ppid > 0) {
-        jstring str;
-        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
-        JNU_CHECK_EXCEPTION(env);
-
-        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
-        JNU_CHECK_EXCEPTION(env);
-
-        CHECK_NULL((str = uidToUser(env, uid)));
-        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, str);
-        JNU_CHECK_EXCEPTION(env);
-    }
-}
-
-/**
- * Read /proc/<pid>/status and return the ppid, total cputime and start time.
- * Return: -1 is fail;  zero is unknown; >  0 is parent pid
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
-                                      jlong *totalTime, jlong* startTime,
-                                      uid_t* uid) {
-    FILE* fp;
-    psinfo_t psinfo;
-    char fn[32];
-    int ret;
-
-    /*
-     * Try to open /proc/%d/status
-     */
-    snprintf(fn, sizeof fn, "/proc/%d/psinfo", pid);
-    fp = fopen(fn, "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    ret = fread(&psinfo, 1, (sizeof psinfo), fp);
-    fclose(fp);
-    if (ret < (sizeof psinfo)) {
-        return -1;
-    }
-
-    *totalTime = psinfo.pr_time.tv_sec * 1000000000L + psinfo.pr_time.tv_nsec;
-
-    *startTime = psinfo.pr_start.tv_sec * (jlong)1000 +
-                 psinfo.pr_start.tv_nsec / 1000000;
-
-    *uid = psinfo.pr_uid;
-
-    return (pid_t) psinfo.pr_ppid;
-}
-
-static void getCmdlineInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
-    char fn[32];
-    char exePath[PATH_MAX];
-    jstring str = NULL;
-    int ret;
-
-    /*
-     * The path to the executable command is the link in /proc/<pid>/paths/a.out.
-     */
-    snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
-    if ((ret = readlink(fn, exePath, PATH_MAX - 1)) < 0) {
-        return;
-    }
-
-    // null terminate and create String to store for command
-    exePath[ret] = '\0';
-    CHECK_NULL(str = JNU_NewStringPlatform(env, exePath));
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, str);
-    JNU_CHECK_EXCEPTION(env);
-}
-
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/file/Handler.java	Wed Jul 05 20:46:35 2017 +0200
@@ -116,8 +116,8 @@
      * Compares the host components of two URLs.
      * @param u1 the URL of the first host to compare
      * @param u2 the URL of the second host to compare
-     * @return  <tt>true</tt> if and only if they
-     * are equal, <tt>false</tt> otherwise.
+     * @return  {@code true} if and only if they
+     * are equal, {@code false} otherwise.
      */
     protected boolean hostsEqual(URL u1, URL u2) {
         /*
--- a/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c	Thu Aug 20 11:38:24 2015 -0700
+++ b/jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c	Wed Jul 05 20:46:35 2017 +0200
@@ -28,31 +28,87 @@
 #include "java_lang_ProcessHandleImpl.h"
 #include "java_lang_ProcessHandleImpl_Info.h"
 
+#include "ProcessHandleImpl_unix.h"
+
 
 #include <stdio.h>
-
 #include <errno.h>
 #include <fcntl.h>
 #include <pwd.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 
-#include <string.h>
-#include <dirent.h>
-#include <ctype.h>
+#ifdef _AIX
+#include <sys/procfs.h>
+#endif
+#ifdef __solaris__
+#include <procfs.h>
+#endif
 
 /**
- * Implementations of ProcessHandleImpl functions that are common to all
- * Unix variants:
- * - waitForProcessExit0(pid, reap)
- * - getCurrentPid0()
- * - destroy0(pid, force)
+ * This file contains the implementation of the native ProcessHandleImpl
+ * functions which are common to all Unix variants.
+ *
+ * The currently supported Unix variants are Solaris, Linux, MaxOS X and AIX.
+ * The various similarities and differences between these systems make it hard
+ * to find a clear boundary between platform specific and shared code.
+ *
+ * In order to ease code sharing between the platforms while still keeping the
+ * code as clean as possible (i.e. free of preprocessor macros) we use the
+ * following source code layout (remember that ProcessHandleImpl_unix.c will
+ * be compiled on EVERY Unix platform while ProcessHandleImpl_<os>.c will be
+ * only compiled on the specific OS):
+ *
+ * - all the JNI wrappers for the ProcessHandleImpl functions go into this file
+ * - if their implementation is common on ALL the supported Unix platforms it
+ *   goes right into the JNI wrappers
+ * - if the whole function or substantial parts of it are platform dependent,
+ *   the implementation goes into os_<function_name> functions in
+ *   ProcessHandleImpl_<os>.c
+ * - if at least two platforms implement an os_<function_name> function in the
+ *   same way, this implementation is factored out into unix_<function_name>,
+ *   placed into this file and called from the corresponding os_<function_name>
+ *   function.
+ * - For convenience, all the os_ and unix_ functions are declared in
+ *   ProcessHandleImpl_unix.h which is included into every
+ *   ProcessHandleImpl_<os>.c file.
+ *
+ * Example 1:
+ * ----------
+ * The implementation of Java_java_lang_ProcessHandleImpl_initNative()
+ * is the same on all platforms except on Linux where it initilizes one
+ * additional field. So we place the implementation right into
+ * Java_java_lang_ProcessHandleImpl_initNative() but add call to
+ * os_init() at the end of the function which is empty on all platforms
+ * except Linux where it performs the additionally initializations.
+ *
+ * Example 2:
+ * ----------
+ * The implementation of Java_java_lang_ProcessHandleImpl_00024Info_info0 is the
+ * same on Solaris and AIX but different on Linux and MacOSX. We therefore simply
+ * call the helpers os_getParentPidAndTimings() and os_getCmdlineAndUserInfo().
+ * The Linux and MaxOS X versions of these functions (in the corresponding files
+ * ProcessHandleImpl_linux.c and ProcessHandleImpl_macosx.c) directly contain
+ * the platform specific implementations while the Solaris and AIX
+ * implementations simply call back to unix_getParentPidAndTimings() and
+ * unix_getCmdlineAndUserInfo() which are implemented right in this file.
+ *
+ * The term "same implementation" is still a question of interpretation. It my
+ * be acceptable to have a few ifdef'ed lines if that allows the sharing of a
+ * huge function. On the other hand, if the platform specific code in a shared
+ * function grows over a certain limit, it may be better to refactor that
+ * functionality into corresponding, platform-specific os_ functions.
  */
 
+
 #ifndef WIFEXITED
 #define WIFEXITED(status) (((status)&0xFF) == 0)
 #endif
@@ -69,6 +125,19 @@
 #define WTERMSIG(status) ((status)&0x7F)
 #endif
 
+#ifdef __solaris__
+/* The child exited because of a signal.
+ * The best value to return is 0x80 + signal number,
+ * because that is what all Unix shells do, and because
+ * it allows callers to distinguish between process exit and
+ * process death by signal.
+ * Unfortunately, the historical behavior on Solaris is to return
+ * the signal number, and we preserve this for compatibility. */
+#define WTERMSIG_RETURN(status) WTERMSIG(status)
+#else
+#define WTERMSIG_RETURN(status) (WTERMSIG(status) + 0x80)
+#endif
+
 #define RESTARTABLE(_cmd, _result) do { \
   do { \
     _result = _cmd; \
@@ -81,21 +150,83 @@
   } while((_result == NULL) && (errno == EINTR)); \
 } while(0)
 
-#ifdef __solaris__
-    #define STAT_FILE "/proc/%d/status"
-#else
-    #define STAT_FILE "/proc/%d/stat"
-#endif
+
+/* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_commandID;
+
+/* Field id for jString 'commandLine' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_commandLineID;
+
+/* Field id for jString[] 'arguments' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_argumentsID;
+
+/* Field id for jlong 'totalTime' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_totalTimeID;
+
+/* Field id for jlong 'startTime' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_startTimeID;
+
+/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
+jfieldID ProcessHandleImpl_Info_userID;
+
+/* Size of password or group entry when not available via sysconf */
+#define ENT_BUF_SIZE   1024
+/* The value for the size of the buffer used by getpwuid_r(). The result of */
+/* sysconf(_SC_GETPW_R_SIZE_MAX) if available or ENT_BUF_SIZE otherwise. */
+static long getpw_buf_size;
+
+/**************************************************************
+ * Static method to initialize field IDs and the ticks per second rate.
+ *
+ * Class:     java_lang_ProcessHandleImpl_Info
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
+
+    CHECK_NULL(ProcessHandleImpl_Info_commandID =
+            (*env)->GetFieldID(env, clazz, "command", "Ljava/lang/String;"));
+    CHECK_NULL(ProcessHandleImpl_Info_commandLineID =
+            (*env)->GetFieldID(env, clazz, "commandLine", "Ljava/lang/String;"));
+    CHECK_NULL(ProcessHandleImpl_Info_argumentsID =
+            (*env)->GetFieldID(env, clazz, "arguments", "[Ljava/lang/String;"));
+    CHECK_NULL(ProcessHandleImpl_Info_totalTimeID =
+            (*env)->GetFieldID(env, clazz, "totalTime", "J"));
+    CHECK_NULL(ProcessHandleImpl_Info_startTimeID =
+            (*env)->GetFieldID(env, clazz, "startTime", "J"));
+    CHECK_NULL(ProcessHandleImpl_Info_userID =
+            (*env)->GetFieldID(env, clazz, "user", "Ljava/lang/String;"));
+}
+
+/***********************************************************
+ * Static method to initialize platform dependent constants.
+ *
+ * Class:     java_lang_ProcessHandleImpl
+ * Method:    initNative
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
+    getpw_buf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+    if (getpw_buf_size == -1) {
+        getpw_buf_size = ENT_BUF_SIZE;
+    }
+    os_initNative(env, clazz);
+}
 
 /* Block until a child process exits and return its exit code.
  * Note, can only be called once for any given pid if reapStatus = true.
+ *
+ * Class:     java_lang_ProcessHandleImpl
+ * Method:    waitForProcessExit0
+ * Signature: (JZ)I
  */
 JNIEXPORT jint JNICALL
 Java_java_lang_ProcessHandleImpl_waitForProcessExit0(JNIEnv* env,
                                                      jclass junk,
                                                      jlong jpid,
-                                                     jboolean reapStatus)
-{
+                                                     jboolean reapStatus) {
     pid_t pid = (pid_t)jpid;
     errno = 0;
 
@@ -117,18 +248,7 @@
         if (WIFEXITED(status)) {
             return WEXITSTATUS(status);
         } else if (WIFSIGNALED(status)) {
-            /* The child exited because of a signal.
-             * The best value to return is 0x80 + signal number,
-             * because that is what all Unix shells do, and because
-             * it allows callers to distinguish between process exit and
-             * process death by signal.
-             * Unfortunately, the historical behavior on Solaris is to return
-             * the signal number, and we preserve this for compatibility. */
-#ifdef __solaris__
-            return WTERMSIG(status);
-#else
-            return 0x80 + WTERMSIG(status);
-#endif
+            return WTERMSIG_RETURN(status);
         } else {
             return status;
         }
@@ -156,18 +276,7 @@
               */
              return siginfo.si_status;
         } else if (siginfo.si_code == CLD_KILLED || siginfo.si_code == CLD_DUMPED) {
-             /* The child exited because of a signal.
-              * The best value to return is 0x80 + signal number,
-              * because that is what all Unix shells do, and because
-              * it allows callers to distinguish between process exit and
-              * process death by signal.
-              * Unfortunately, the historical behavior on Solaris is to return
-              * the signal number, and we preserve this for compatibility. */
- #ifdef __solaris__
-             return WTERMSIG(siginfo.si_status);
- #else
-             return 0x80 + WTERMSIG(siginfo.si_status);
- #endif
+             return WTERMSIG_RETURN(siginfo.si_status);
         } else {
              /*
               * Unknown exit code; pass it through.
@@ -191,7 +300,7 @@
 /*
  * Class:     java_lang_ProcessHandleImpl
  * Method:    destroy0
- * Signature: (Z)Z
+ * Signature: (JJZ)Z
  */
 JNIEXPORT jboolean JNICALL
 Java_java_lang_ProcessHandleImpl_destroy0(JNIEnv *env,
@@ -210,119 +319,52 @@
     }
 }
 
-/**
- * Size of password or group entry when not available via sysconf
+/*
+ * Returns the children of the requested pid and optionally each parent and
+ * start time.
+ * Accumulates any process who parent pid matches.
+ * The resulting pids are stored into the array of longs.
+ * The number of pids is returned if they all fit.
+ * If the array is too short, the negative of the desired length is returned.
+ * Class:     java_lang_ProcessHandleImpl
+ * Method:    getProcessPids0
+ * Signature: (J[J[J[J)I
  */
-#define ENT_BUF_SIZE   1024
-
-/**
- * Return a strong username for the uid_t or null.
- */
-jstring uidToUser(JNIEnv* env, uid_t uid) {
-    int result = 0;
-    int buflen;
-    char* pwbuf;
-    jstring name = NULL;
-
-    /* allocate buffer for password record */
-    buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX);
-    if (buflen == -1)
-        buflen = ENT_BUF_SIZE;
-    pwbuf = (char*)malloc(buflen);
-    if (pwbuf == NULL) {
-        JNU_ThrowOutOfMemoryError(env, "Unable to open getpwent");
-    } else {
-        struct passwd pwent;
-        struct passwd* p = NULL;
-
-#ifdef __solaris__
-        RESTARTABLE_RETURN_PTR(getpwuid_r(uid, &pwent, pwbuf, (size_t)buflen), p);
-#else
-        RESTARTABLE(getpwuid_r(uid, &pwent, pwbuf, (size_t)buflen, &p), result);
-#endif
-
-        // Return the Java String if a name was found
-        if (result == 0 && p != NULL &&
-            p->pw_name != NULL && *(p->pw_name) != '\0') {
-            name = JNU_NewStringPlatform(env, p->pw_name);
-        }
-        free(pwbuf);
-    }
-    return name;
+JNIEXPORT jint JNICALL
+Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
+                                                 jclass clazz,
+                                                 jlong jpid,
+                                                 jlongArray jarray,
+                                                 jlongArray jparentArray,
+                                                 jlongArray jstimesArray) {
+    return os_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
 }
 
-/**
- * Implementations of ProcessHandleImpl functions that are common to
- * (some) Unix variants:
- * - getProcessPids0(pid, pidArray, parentArray)
- */
-
-#if defined(__linux__) || defined(__AIX__)
-
 /*
- * Signatures for internal OS specific functions.
- */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
-                                     jlong *totalTime, jlong* startTime);
-static void getCmdlineInfo(JNIEnv *env, pid_t pid, jobject jinfo);
-static long long getBoottime(JNIEnv *env);
-
-jstring uidToUser(JNIEnv* env, uid_t uid);
-
-/* Field id for jString 'command' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_commandID;
-
-/* Field id for jString[] 'arguments' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_argumentsID;
-
-/* Field id for jlong 'totalTime' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_totalTimeID;
-
-/* Field id for jlong 'startTime' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_startTimeID;
-
-/* Field id for jString 'user' in java.lang.ProcessHandleImpl.Info */
-static jfieldID ProcessHandleImpl_Info_userID;
-
-/* static value for clock ticks per second. */
-static long clock_ticks_per_second;
-
-/* A static offset in milliseconds since boot. */
-static long long bootTime_ms;
-
-/**************************************************************
- * Static method to initialize field IDs and the ticks per second rate.
+ * Fill in the Info object from the OS information about the process.
  *
  * Class:     java_lang_ProcessHandleImpl_Info
- * Method:    initIDs
- * Signature: ()V
+ * Method:    info0
+ * Signature: (Ljava/lang/ProcessHandle/Info;J)I
  */
 JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_initIDs(JNIEnv *env, jclass clazz) {
+Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
+                                                 jobject jinfo,
+                                                 jlong jpid) {
+    pid_t pid = (pid_t) jpid;
+    pid_t ppid;
+    jlong totalTime = -1L;
+    jlong startTime = -1L;
 
-    CHECK_NULL(ProcessHandleImpl_Info_commandID = (*env)->GetFieldID(env,
-        clazz, "command", "Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_argumentsID = (*env)->GetFieldID(env,
-        clazz, "arguments", "[Ljava/lang/String;"));
-    CHECK_NULL(ProcessHandleImpl_Info_totalTimeID = (*env)->GetFieldID(env,
-        clazz, "totalTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_startTimeID = (*env)->GetFieldID(env,
-        clazz, "startTime", "J"));
-    CHECK_NULL(ProcessHandleImpl_Info_userID = (*env)->GetFieldID(env,
-        clazz, "user", "Ljava/lang/String;"));
-}
+    ppid = os_getParentPidAndTimings(env, pid,  &totalTime, &startTime);
+    if (ppid >= 0) {
+        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
+        JNU_CHECK_EXCEPTION(env);
 
-/**************************************************************
- * Static method to initialize the ticks per second rate.
- *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    initNative
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_initNative(JNIEnv *env, jclass clazz) {
-    clock_ticks_per_second = sysconf(_SC_CLK_TCK);
-    bootTime_ms = getBoottime(env);
+        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
+        JNU_CHECK_EXCEPTION(env);
+    }
+    os_getCmdlineAndUserInfo(env, jinfo, pid);
 }
 
 /*
@@ -340,8 +382,8 @@
     pid_t pid = (pid_t) jpid;
     jlong startTime = 0L;
     jlong totalTime = 0L;
-    pid_t ppid = getStatInfo(env, pid, &totalTime, &startTime);
-    return (ppid <= 0) ? -1 : startTime;
+    pid_t ppid = os_getParentPidAndTimings(env, pid, &totalTime, &startTime);
+    return (ppid < 0) ? -1 : startTime;
 }
 
 /*
@@ -350,7 +392,7 @@
  *
  * Class:     java_lang_ProcessHandleImpl
  * Method:    parent0
- * Signature: (J)J
+ * Signature: (JJ)J
  */
 JNIEXPORT jlong JNICALL
 Java_java_lang_ProcessHandleImpl_parent0(JNIEnv *env,
@@ -360,13 +402,12 @@
     pid_t pid = (pid_t) jpid;
     pid_t ppid;
 
-    pid_t mypid = getpid();
-    if (pid == mypid) {
+    if (pid == getpid()) {
         ppid = getppid();
     } else {
-        jlong start = 0L;;
+        jlong start = 0L;
         jlong total = 0L;        // unused
-        ppid = getStatInfo(env, pid, &total, &start);
+        ppid = os_getParentPidAndTimings(env, pid, &total, &start);
         if (start != startTime && start != 0 && startTime != 0) {
             ppid = -1;
         }
@@ -374,24 +415,94 @@
     return (jlong) ppid;
 }
 
+/**
+ * Construct the argument array by parsing the arguments from the sequence
+ * of arguments.
+ */
+void unix_fillArgArray(JNIEnv *env, jobject jinfo, int nargs, char *cp,
+                       char *argsEnd, jstring cmdexe, char *cmdline) {
+    jobject argsArray;
+    int i;
+
+    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, cmdexe);
+    JNU_CHECK_EXCEPTION(env);
+
+    if (nargs >= 1) {
+        // Create a String array for nargs-1 elements
+        argsArray = (*env)->NewObjectArray(env, nargs - 1, JNU_ClassString(env), NULL);
+        CHECK_NULL(argsArray);
+
+        for (i = 0; i < nargs - 1; i++) {
+            jstring str = NULL;
+
+            cp += strlen(cp) + 1;
+            if (cp > argsEnd || *cp == '\0') {
+                return;  // Off the end pointer or an empty argument is an error
+            }
+
+            CHECK_NULL((str = JNU_NewStringPlatform(env, cp)));
+
+            (*env)->SetObjectArrayElement(env, argsArray, i, str);
+            JNU_CHECK_EXCEPTION(env);
+        }
+        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
+        JNU_CHECK_EXCEPTION(env);
+    }
+    if (cmdline != NULL) {
+        jstring commandLine = NULL;
+        CHECK_NULL((commandLine = JNU_NewStringPlatform(env, cmdline)));
+        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandLineID, commandLine);
+        JNU_CHECK_EXCEPTION(env);
+    }
+}
+
+void unix_getUserInfo(JNIEnv* env, jobject jinfo, uid_t uid) {
+    int result = 0;
+    char* pwbuf;
+    jstring name = NULL;
+
+    /* allocate buffer for password record */
+    pwbuf = (char*)malloc(getpw_buf_size);
+    if (pwbuf == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "Unable to open getpwent");
+    } else {
+        struct passwd pwent;
+        struct passwd* p = NULL;
+
+#ifdef __solaris__
+        RESTARTABLE_RETURN_PTR(getpwuid_r(uid, &pwent, pwbuf, (size_t)getpw_buf_size), p);
+#else
+        RESTARTABLE(getpwuid_r(uid, &pwent, pwbuf, (size_t)getpw_buf_size, &p), result);
+#endif
+
+        // Create the Java String if a name was found
+        if (result == 0 && p != NULL &&
+            p->pw_name != NULL && *(p->pw_name) != '\0') {
+            name = JNU_NewStringPlatform(env, p->pw_name);
+        }
+        free(pwbuf);
+    }
+    if (name != NULL) {
+        (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
+    }
+}
+
 /*
- * Returns the children of the requested pid and optionally each parent.
+ * The following functions are common on Solaris, Linux and AIX.
+ */
+
+#if defined(__solaris__) || defined (__linux__) || defined(_AIX)
+
+/*
+ * Returns the children of the requested pid and optionally each parent and
+ * start time.
  * Reads /proc and accumulates any process who parent pid matches.
  * The resulting pids are stored into the array of longs.
  * The number of pids is returned if they all fit.
- * If the array is too short, the negative of the desired length is returned. *
- * Class:     java_lang_ProcessHandleImpl
- * Method:    getChildPids
- * Signature: (J[J[J)I
+ * If the array is too short, the negative of the desired length is returned.
  */
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessHandleImpl_getProcessPids0(JNIEnv *env,
-                                                 jclass clazz,
-                                                 jlong jpid,
-                                                 jlongArray jarray,
-                                                 jlongArray jparentArray,
-                                                 jlongArray jstimesArray) {
-
+jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
+                      jlongArray jparentArray, jlongArray jstimesArray) {
     DIR* dir;
     struct dirent* ptr;
     pid_t pid = (pid_t) jpid;
@@ -462,9 +573,10 @@
             if ((int) childpid <= 0) {
                 continue;
             }
-            // Read /proc/pid/stat and get the parent pid, and start time
-            ppid = getStatInfo(env, childpid, &totalTime, &startTime);
-            if (ppid > 0 && (pid == 0 || ppid == pid)) {
+
+            // Get the parent pid, and start time
+            ppid = os_getParentPidAndTimings(env, childpid, &totalTime, &startTime);
+            if (ppid >= 0 && (pid == 0 || ppid == pid)) {
                 if (count < arraySize) {
                     // Only store if it fits
                     pids[count] = (jlong) childpid;
@@ -498,293 +610,110 @@
     return count;
 }
 
+#endif // defined(__solaris__) || defined (__linux__) || defined(_AIX)
 
-/**************************************************************
- * Implementation of ProcessHandleImpl_Info native methods.
+/*
+ * The following functions are common on Solaris and AIX.
  */
 
-/*
- * Fill in the Info object from the OS information about the process.
- *
- * Class:     java_lang_ProcessHandleImpl_Info
- * Method:    info0
- * Signature: (JLjava/lang/ProcessHandle/Info;)I
- */
-JNIEXPORT void JNICALL
-Java_java_lang_ProcessHandleImpl_00024Info_info0(JNIEnv *env,
-                                                 jobject jinfo,
-                                                 jlong jpid) {
-    pid_t pid = (pid_t) jpid;
-    pid_t ppid;
-    jlong totalTime = 0L;
-    jlong startTime = -1L;
-
-    ppid = getStatInfo(env, pid,  &totalTime, &startTime);
-    if (ppid > 0) {
-        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_totalTimeID, totalTime);
-        JNU_CHECK_EXCEPTION(env);
-
-        (*env)->SetLongField(env, jinfo, ProcessHandleImpl_Info_startTimeID, startTime);
-        JNU_CHECK_EXCEPTION(env);
-
-        getCmdlineInfo(env, pid, jinfo);
-    }
-}
+#if defined(__solaris__) || defined(_AIX)
 
 /**
- * Read /proc/<pid>/stat and return the ppid, total cputime and start time.
- * -1 is fail;  zero is unknown; >  0 is parent pid
+ * Helper function to get the 'psinfo_t' data from "/proc/%d/psinfo".
+ * Returns 0 on success and -1 on error.
  */
-static pid_t getStatInfo(JNIEnv *env, pid_t pid,
-                                     jlong *totalTime, jlong* startTime) {
+static int getPsinfo(pid_t pid, psinfo_t *psinfo) {
     FILE* fp;
-    char buffer[2048];
-    int statlen;
     char fn[32];
-    char* s;
-    int parentPid;
-    long unsigned int utime = 0;      // clock tics
-    long unsigned int stime = 0;      // clock tics
-    long long unsigned int start = 0; // microseconds
+    int ret;
 
     /*
-     * Try to stat and then open /proc/%d/stat
+     * Try to open /proc/%d/psinfo
      */
-    snprintf(fn, sizeof fn, STAT_FILE, pid);
-
+    snprintf(fn, sizeof fn, "/proc/%d/psinfo", pid);
     fp = fopen(fn, "r");
     if (fp == NULL) {
-        return -1;              // fail, no such /proc/pid/stat
-    }
-
-    /*
-     * The format is: pid (command) state ppid ...
-     * As the command could be anything we must find the right most
-     * ")" and then skip the white spaces that follow it.
-     */
-    statlen = fread(buffer, 1, (sizeof buffer - 1), fp);
-    fclose(fp);
-    if (statlen < 0) {
-        return 0;               // parent pid is not available
-    }
-
-    buffer[statlen] = '\0';
-    s = strchr(buffer, '(');
-    if (s == NULL) {
-        return 0;               // parent pid is not available
-    }
-    // Found start of command, skip to end
-    s++;
-    s = strrchr(s, ')');
-    if (s == NULL) {
-        return 0;               // parent pid is not available
-    }
-    s++;
-
-    // Scan the needed fields from status, retaining only ppid(4),
-    // utime (14), stime(15), starttime(22)
-    if (4 != sscanf(s, " %*c %d %*d %*d %*d %*d %*d %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %llu",
-            &parentPid, &utime, &stime, &start)) {
-        return 0;              // not all values parsed; return error
-    }
-
-    *totalTime = (utime + stime) * (jlong)(1000000000 / clock_ticks_per_second);
-
-    *startTime = bootTime_ms + ((start * 1000) / clock_ticks_per_second);
-
-    return parentPid;
-}
-
-/**
- * Construct the argument array by parsing the arguments from the sequence
- * of arguments. The zero'th arg is the command executable
- */
-static int fillArgArray(JNIEnv *env, jobject jinfo,
-                        int nargs, char *cp, char *argsEnd, jstring cmdexe) {
-    jobject argsArray;
-    int i;
-
-    if (nargs < 1) {
-        return 0;
-    }
-
-    if (cmdexe == NULL) {
-        // Create a string from arg[0]
-        CHECK_NULL_RETURN((cmdexe = JNU_NewStringPlatform(env, cp)), -1);
-    }
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_commandID, cmdexe);
-    JNU_CHECK_EXCEPTION_RETURN(env, -3);
-
-    // Create a String array for nargs-1 elements
-    argsArray = (*env)->NewObjectArray(env, nargs - 1, JNU_ClassString(env), NULL);
-    CHECK_NULL_RETURN(argsArray, -1);
-
-    for (i = 0; i < nargs - 1; i++) {
-        jstring str = NULL;
-
-        cp += strnlen(cp, (argsEnd - cp)) + 1;
-        if (cp > argsEnd || *cp == '\0') {
-            return -2;  // Off the end pointer or an empty argument is an error
-        }
-
-        CHECK_NULL_RETURN((str = JNU_NewStringPlatform(env, cp)), -1);
-
-        (*env)->SetObjectArrayElement(env, argsArray, i, str);
-        JNU_CHECK_EXCEPTION_RETURN(env, -3);
-    }
-    (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_argumentsID, argsArray);
-    JNU_CHECK_EXCEPTION_RETURN(env, -4);
-    return 0;
-}
-
-
-static void getCmdlineInfo(JNIEnv *env, pid_t pid, jobject jinfo) {
-    int fd;
-    int cmdlen = 0;
-    char *cmdline = NULL, *cmdEnd;  // used for command line args and exe
-    jstring cmdexe = NULL;
-    char fn[32];
-    struct stat stat_buf;
-
-    /*
-     * Try to open /proc/%d/cmdline
-     */
-    snprintf(fn, sizeof fn, "/proc/%d/cmdline", pid);
-    if ((fd = open(fn, O_RDONLY)) < 0) {
-        return;
-    }
-
-    do {                // Block to break out of on errors
-        int i;
-        char *s;
-
-        cmdline = (char*)malloc(PATH_MAX);
-        if (cmdline == NULL) {
-            break;
-        }
-
-        /*
-         * The path to the executable command is the link in /proc/<pid>/exe.
-         */
-        snprintf(fn, sizeof fn, "/proc/%d/exe", pid);
-        if ((cmdlen = readlink(fn, cmdline, PATH_MAX - 1)) > 0) {
-            // null terminate and create String to store for command
-            cmdline[cmdlen] = '\0';
-            cmdexe = JNU_NewStringPlatform(env, cmdline);
-            (*env)->ExceptionClear(env);        // unconditionally clear any exception
-        }
-
-        /*
-         * The buffer format is the arguments nul terminated with an extra nul.
-         */
-        cmdlen = read(fd, cmdline, PATH_MAX-1);
-        if (cmdlen < 0) {
-            break;
-        }
-
-        // Terminate the buffer and count the arguments
-        cmdline[cmdlen] = '\0';
-        cmdEnd = &cmdline[cmdlen + 1];
-        for (s = cmdline,i = 0; *s != '\0' && (s < cmdEnd); i++) {
-            s += strnlen(s, (cmdEnd - s)) + 1;
-        }
-
-        if (fillArgArray(env, jinfo, i, cmdline, cmdEnd, cmdexe) < 0) {
-            break;
-        }
-
-        // Get and store the user name
-        if (fstat(fd, &stat_buf) == 0) {
-            jstring name = uidToUser(env, stat_buf.st_uid);
-            if (name != NULL) {
-                (*env)->SetObjectField(env, jinfo, ProcessHandleImpl_Info_userID, name);
-            }
-        }
-    } while (0);
-
-    if (cmdline != NULL) {
-        free(cmdline);
-    }
-    if (fd >= 0) {
-        close(fd);
-    }
-}
-
-/**
- * Read the boottime from /proc/stat.
- */
-static long long getBoottime(JNIEnv *env) {
-    FILE *fp;
-    char *line = NULL;
-    size_t len = 0;
-    long long bootTime = 0;
-
-    fp = fopen("/proc/stat", "r");
-    if (fp == NULL) {
         return -1;
     }
 
-    while (getline(&line, &len, fp) != -1) {
-        if (sscanf(line, "btime %llu", &bootTime) == 1) {
-            break;
-        }
+    ret = fread(psinfo, 1, sizeof(psinfo_t), fp);
+    fclose(fp);
+    if (ret < sizeof(psinfo_t)) {
+        return -1;
     }
-    free(line);
+    return 0;
+}
 
-    if (fp != 0) {
-        fclose(fp);
+/**
+ * Read /proc/<pid>/psinfo and return the ppid, total cputime and start time.
+ * Return: -1 is fail;  >=  0 is parent pid
+ * 'total' will contain the running time of 'pid' in nanoseconds.
+ * 'start' will contain the start time of 'pid' in milliseconds since epoch.
+ */
+pid_t unix_getParentPidAndTimings(JNIEnv *env, pid_t pid,
+                                  jlong *totalTime, jlong* startTime) {
+    psinfo_t psinfo;
+
+    if (getPsinfo(pid, &psinfo) < 0) {
+        return -1;
     }
 
-    return bootTime * 1000;
+    *totalTime = psinfo.pr_time.tv_sec * 1000000000L + psinfo.pr_time.tv_nsec;
+
+    *startTime = psinfo.pr_start.tv_sec * (jlong)1000 +
+                 psinfo.pr_start.tv_nsec / 1000000;
+
+    return (pid_t) psinfo.pr_ppid;
 }
 
-#endif  //  defined(__linux__) || defined(__AIX__)
+void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
+    psinfo_t psinfo;
+    char fn[32];
+    char exePath[PATH_MAX];
+    char prargs[PRARGSZ + 1];
+    jstring cmdexe = NULL;
+    int ret;
 
+    /*
+     * On Solaris, the full path to the executable command is the link in
+     * /proc/<pid>/paths/a.out. But it is only readable for processes we own.
+     */
+#if defined(__solaris__)
+    snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
+    if ((ret = readlink(fn, exePath, PATH_MAX - 1)) > 0) {
+        // null terminate and create String to store for command
+        exePath[ret] = '\0';
+        CHECK_NULL(cmdexe = JNU_NewStringPlatform(env, exePath));
+    }
+#endif
 
-/* Block until a child process exits and return its exit code.
-   Note, can only be called once for any given pid. */
-JNIEXPORT jint JNICALL
-Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env,
-                                              jobject junk,
-                                              jint pid)
-{
-    /* We used to use waitid() on Solaris, waitpid() on Linux, but
-     * waitpid() is more standard, so use it on all POSIX platforms. */
-    int status;
-    /* Wait for the child process to exit.  This returns immediately if
-       the child has already exited. */
-    while (waitpid(pid, &status, 0) < 0) {
-        switch (errno) {
-        case ECHILD: return 0;
-        case EINTR: break;
-        default: return -1;
-        }
+    /*
+     * Now try to open /proc/%d/psinfo
+     */
+    if (getPsinfo(pid, &psinfo) < 0) {
+        unix_fillArgArray(env, jinfo, 0, NULL, NULL, cmdexe, NULL);
+        return;
     }
 
-    if (WIFEXITED(status)) {
-        /*
-         * The child exited normally; get its exit code.
+    unix_getUserInfo(env, jinfo, psinfo.pr_uid);
+
+    /*
+     * Now read psinfo.pr_psargs which contains the first PRARGSZ characters of the
+     * argument list (i.e. arg[0] arg[1] ...). Unfortunately, PRARGSZ is usually set
+     * to 80 characters only. Nevertheless it's better than nothing :)
+     */
+    strncpy(prargs, psinfo.pr_psargs, PRARGSZ);
+    prargs[PRARGSZ] = '\0';
+    if (prargs[0] == '\0') {
+        /* If psinfo.pr_psargs didn't contain any strings, use psinfo.pr_fname
+         * (which only contains the last component of exec()ed pathname) as a
+         * last resort. This is true for AIX kernel processes for example.
          */
-        return WEXITSTATUS(status);
-    } else if (WIFSIGNALED(status)) {
-        /* The child exited because of a signal.
-         * The best value to return is 0x80 + signal number,
-         * because that is what all Unix shells do, and because
-         * it allows callers to distinguish between process exit and
-         * process death by signal.
-         * Unfortunately, the historical behavior on Solaris is to return
-         * the signal number, and we preserve this for compatibility. */
-#ifdef __solaris__
-        return WTERMSIG(status);
-#else
-        return 0x80 + WTERMSIG