Merge
authorduke
Wed, 05 Jul 2017 20:17:15 +0200
changeset 28699 06e2c7a14944
parent 28698 f9e5640d832e (current diff)
parent 28692 cf8fe951ca93 (diff)
child 28703 4adaea63f465
Merge
jdk/make/data/checkdeps/refs.allowed
jdk/make/src/classes/build/tools/deps/CheckDeps.java
jdk/src/java.base/aix/native/libnet/java/net/aix_close.c
jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java
jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c
jdk/src/java.base/unix/native/libjava/java_props_macosx.c
jdk/src/java.base/unix/native/libjava/java_props_macosx.h
jdk/src/java.base/unix/native/libnet/bsd_close.c
jdk/src/java.base/unix/native/libnet/linux_close.c
jdk/src/java.base/unix/native/libnet/solaris_close.c
jdk/src/jdk.security.auth/unix/native/libjaas/Solaris.c
jdk/test/java/lang/CharSequence/DefaultTest.java
jdk/test/java/util/ResourceBundle/Bug6287579.java
--- a/.hgtags-top-repo	Thu Jan 29 15:36:12 2015 -0800
+++ b/.hgtags-top-repo	Wed Jul 05 20:17:15 2017 +0200
@@ -290,3 +290,4 @@
 3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45
 12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46
 b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47
+0064e246d83f6f9fc245c19b6d05041ecaf4b6d4 jdk9-b48
--- a/common/autoconf/basics.m4	Thu Jan 29 15:36:12 2015 -0800
+++ b/common/autoconf/basics.m4	Wed Jul 05 20:17:15 2017 +0200
@@ -987,3 +987,26 @@
     IS_RECONFIGURE=no
   fi
 ])
+
+# Check for support for specific options in bash
+AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS],
+[
+  # Test if bash supports pipefail.
+  AC_MSG_CHECKING([if bash supports pipefail])
+  if ${BASH} -c 'set -o pipefail'; then
+    BASH_ARGS="$BASH_ARGS -o pipefail"
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+
+  AC_MSG_CHECKING([if bash supports errexit (-e)])
+  if ${BASH} -e -c 'true'; then
+    BASH_ARGS="$BASH_ARGS -e"
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+
+  AC_SUBST(BASH_ARGS)
+])
--- a/common/autoconf/bootcycle-spec.gmk.in	Thu Jan 29 15:36:12 2015 -0800
+++ b/common/autoconf/bootcycle-spec.gmk.in	Wed Jul 05 20:17:15 2017 +0200
@@ -46,8 +46,12 @@
 BOOT_JDK := $(JDK_IMAGE_DIR)
 
 # The bootcycle build has a different output directory
-BUILD_OUTPUT:=@BUILD_OUTPUT@/bootcycle-build
-SJAVAC_SERVER_DIR:=$(subst @BUILD_OUTPUT@,$(BUILD_OUTPUT),$(SJAVAC_SERVER_DIR))
+OLD_BUILD_OUTPUT:=@BUILD_OUTPUT@
+BUILD_OUTPUT:=$(OLD_BUILD_OUTPUT)/bootcycle-build
+# The HOTSPOT_DIST dir is not defined relative to BUILD_OUTPUT in spec.gmk. Must not
+# use space in this patsubst to avoid leading space in HOTSPOT_DIST.
+HOTSPOT_DIST:=$(patsubst $(OLD_BUILD_OUTPUT)%,$(BUILD_OUTPUT)%,$(HOTSPOT_DIST))
+SJAVAC_SERVER_DIR:=$(patsubst $(OLD_BUILD_OUTPUT)%, $(BUILD_OUTPUT)%, $(SJAVAC_SERVER_DIR))
 
 JAVA_CMD:=$(BOOT_JDK)/bin/java
 JAVAC_CMD:=$(BOOT_JDK)/bin/javac
--- a/common/autoconf/configure.ac	Thu Jan 29 15:36:12 2015 -0800
+++ b/common/autoconf/configure.ac	Wed Jul 05 20:17:15 2017 +0200
@@ -113,6 +113,7 @@
 
 # Setup tools that requires more complex handling, or that is not needed by the configure script.
 BASIC_SETUP_COMPLEX_TOOLS
+BASIC_CHECK_BASH_OPTIONS
 
 # Check if pkg-config is available.
 PKG_PROG_PKG_CONFIG
--- a/common/autoconf/generated-configure.sh	Thu Jan 29 15:36:12 2015 -0800
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 20:17:15 2017 +0200
@@ -853,6 +853,7 @@
 OS_VERSION_MINOR
 OS_VERSION_MAJOR
 PKG_CONFIG
+BASH_ARGS
 CODESIGN
 XATTR
 DSYMUTIL
@@ -3522,6 +3523,9 @@
 
 
 
+# Check for support for specific options in bash
+
+
 #
 # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4329,7 +4333,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1420811523
+DATE_WHEN_GENERATED=1421247827
 
 ###############################################################################
 #
@@ -19609,6 +19613,32 @@
   fi
 
 
+  # Test if bash supports pipefail.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports pipefail" >&5
+$as_echo_n "checking if bash supports pipefail... " >&6; }
+  if ${BASH} -c 'set -o pipefail'; then
+    BASH_ARGS="$BASH_ARGS -o pipefail"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports errexit (-e)" >&5
+$as_echo_n "checking if bash supports errexit (-e)... " >&6; }
+  if ${BASH} -e -c 'true'; then
+    BASH_ARGS="$BASH_ARGS -e"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+
+
+
+
 # Check if pkg-config is available.
 
 
@@ -27408,8 +27438,8 @@
     # The trailing space for everyone except PATH is no typo, but is needed due
     # to trailing \ in the Windows paths. These will be stripped later.
     $ECHO "$WINPATH_BASH -c 'echo VS_PATH="'\"$PATH\" > set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
-    $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE\;$include \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
-    $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB\;$lib \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+    $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
     $ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
     $ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
     $ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
--- a/common/autoconf/spec.gmk.in	Thu Jan 29 15:36:12 2015 -0800
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 20:17:15 2017 +0200
@@ -78,6 +78,11 @@
 OUTPUT_SYNC_SUPPORTED:=@OUTPUT_SYNC_SUPPORTED@
 OUTPUT_SYNC:=@OUTPUT_SYNC@
 
+# Override the shell with bash
+BASH:=@BASH@
+BASH_ARGS:=@BASH_ARGS@
+SHELL:=$(BASH) $(BASH_ARGS)
+
 # The "human readable" name of this configuration
 CONF_NAME:=@CONF_NAME@
 
@@ -243,7 +248,7 @@
 HOTSPOT_OUTPUTDIR=$(BUILD_OUTPUT)/hotspot
 JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk
 IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
-TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake
+TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
 MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
 
 HOTSPOT_DIST=@HOTSPOT_DIST@
@@ -495,7 +500,6 @@
 # Tools adhering to a minimal and common standard of posix compliance.
 AWK:=@AWK@
 BASENAME:=@BASENAME@
-BASH:=@BASH@
 CAT:=@CAT@
 CCACHE:=@CCACHE@
 # CD is going away, but remains to cater for legacy makefiles.
--- a/corba/.hgtags	Thu Jan 29 15:36:12 2015 -0800
+++ b/corba/.hgtags	Wed Jul 05 20:17:15 2017 +0200
@@ -290,3 +290,4 @@
 9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45
 326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46
 ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47
+a13c49c5f2899b702652a460ed7aa73123e671e6 jdk9-b48
--- a/hotspot/.hgtags	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/.hgtags	Wed Jul 05 20:17:15 2017 +0200
@@ -450,3 +450,4 @@
 5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45
 a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46
 3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47
+cc775a4a24c7f5d9e624b4205e9fbd48a17331f6 jdk9-b48
--- a/hotspot/make/aix/Makefile	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/aix/Makefile	Wed Jul 05 20:17:15 2017 +0200
@@ -246,8 +246,7 @@
 XSLT_CHECK	= $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
 # If not found then fail fast.
 check_j2se_version:
-	$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
-	if [ $$? -ne 0 ]; then \
+	$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
 	  $(REMOTE) $(RUN.JAVA) -version; \
 	  echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
 	  "to bootstrap this build" 1>&2; \
--- a/hotspot/make/aix/makefiles/xlc.make	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/aix/makefiles/xlc.make	Wed Jul 05 20:17:15 2017 +0200
@@ -74,6 +74,12 @@
 # no xlc counterpart for -fcheck-new
 # CFLAGS += -fcheck-new
 
+# We need to define this on the command line if we want to use the the
+# predefined format specifiers from "inttypes.h". Otherwise system headrs
+# can indirectly include inttypes.h before we define __STDC_FORMAT_MACROS
+# in globalDefinitions.hpp
+CFLAGS += -D__STDC_FORMAT_MACROS
+
 ARCHFLAG = -q64
 
 CFLAGS     += $(ARCHFLAG)
--- a/hotspot/make/bsd/Makefile	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/bsd/Makefile	Wed Jul 05 20:17:15 2017 +0200
@@ -240,8 +240,7 @@
 XSLT_CHECK	= $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
 # If not found then fail fast.
 check_j2se_version:
-	$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
-	if [ $$? -ne 0 ]; then \
+	$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
 	  $(REMOTE) $(RUN.JAVA) -version; \
 	  echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
 	  "to bootstrap this build" 1>&2; \
--- a/hotspot/make/bsd/makefiles/dtrace.make	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/bsd/makefiles/dtrace.make	Wed Jul 05 20:17:15 2017 +0200
@@ -179,23 +179,23 @@
 # $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
 $(JVMOFFS).h: $(GENOFFS)
 	$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -header > $@.tmp; touch $@; \
-	if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
-	then rm -f $@; mv $@.tmp $@; \
-	else rm -f $@.tmp; \
+	if diff $@.tmp $@ > /dev/null 2>&1 ; \
+	then rm -f $@.tmp; \
+	else rm -f $@; mv $@.tmp $@; \
 	fi
 
 $(JVMOFFS)Index.h: $(GENOFFS)
 	$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -index > $@.tmp; touch $@; \
-	if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
-	then rm -f $@; mv $@.tmp $@; \
-	else rm -f $@.tmp; \
+	if diff $@.tmp $@ > /dev/null 2>&1 ; \
+	then rm -f $@.tmp; \
+	else rm -f $@; mv $@.tmp $@; \
 	fi
 
 $(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
 	$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -table > $@.tmp; touch $@; \
-	if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
-	then rm -f $@; mv $@.tmp $@; \
-	else rm -f $@.tmp; \
+	if diff $@.tmp $@ > /dev/null 2>&1; \
+	then rm -f $@.tmp; \
+	else rm -f $@; mv $@.tmp $@; \
 	fi
 
 $(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp 
--- a/hotspot/make/bsd/makefiles/universal.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/bsd/makefiles/universal.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -59,7 +59,7 @@
 
 # Package built libraries in a universal binary
 $(UNIVERSAL_LIPO_LIST):
-	BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`"; \
+	BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`" || test $$? = "1"; \
 	if [ -n "$${BUILT_LIPO_FILES}" ]; then \
 	  $(MKDIR) -p $(shell dirname $@); \
 	  lipo -create -output $@ $${BUILT_LIPO_FILES}; \
@@ -70,7 +70,7 @@
 # - copies directories; including empty dirs
 # - copies files, symlinks, other non-directory files
 $(UNIVERSAL_COPY_LIST):
-	BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`"; \
+	BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`" || test $$? = "1"; \
 	if [ -n "$${BUILT_COPY_FILES}" ]; then \
 	  for i in $${BUILT_COPY_FILES}; do \
 	    $(MKDIR) -p $(shell dirname $@); \
--- a/hotspot/make/linux/Makefile	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/linux/Makefile	Wed Jul 05 20:17:15 2017 +0200
@@ -246,8 +246,7 @@
 XSLT_CHECK	= $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
 # If not found then fail fast.
 check_j2se_version:
-	$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
-	if [ $$? -ne 0 ]; then \
+	$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
 	  $(REMOTE) $(RUN.JAVA) -version; \
 	  echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
 	  "to bootstrap this build" 1>&2; \
--- a/hotspot/make/linux/makefiles/vm.make	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/linux/makefiles/vm.make	Wed Jul 05 20:17:15 2017 +0200
@@ -334,10 +334,8 @@
 	    rm -f $@.1; ln -s $@ $@.1;                                  \
             if [ \"$(CROSS_COMPILE_ARCH)\" = \"\" ] ; then                    \
 	      if [ -x /usr/sbin/selinuxenabled ] ; then                 \
-	        /usr/sbin/selinuxenabled;                               \
-                if [ $$? = 0 ] ; then					\
-		  /usr/bin/chcon -t textrel_shlib_t $@;                 \
-		  if [ $$? != 0 ]; then                                 \
+                if /usr/sbin/selinuxenabled; then			\
+		  if ! /usr/bin/chcon -t textrel_shlib_t $@; then       \
 		    echo "ERROR: Cannot chcon $@";			\
 		  fi							\
 	        fi							\
--- a/hotspot/make/sa.files	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/sa.files	Wed Jul 05 20:17:15 2017 +0200
@@ -39,6 +39,7 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/classfile/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
@@ -49,8 +50,10 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dummy/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ia64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
@@ -71,6 +74,7 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/ia64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/amd64/*.java \
@@ -101,6 +105,8 @@
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/sparc/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/x86/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_x86/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/ppc64/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/*.java \
 $(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/jcore/*.java \
--- a/hotspot/make/solaris/Makefile	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/solaris/Makefile	Wed Jul 05 20:17:15 2017 +0200
@@ -190,8 +190,7 @@
 XSLT_CHECK	= $(RUN.JAVAP) javax.xml.transform.TransformerFactory
 # If not found then fail fast.
 check_j2se_version:
-	$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
-	if [ $$? -ne 0 ]; then \
+	$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
 	  $(RUN.JAVA) -version; \
 	  echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
 	  "to bootstrap this build" 1>&2; \
--- a/hotspot/make/solaris/makefiles/dtrace.make	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/make/solaris/makefiles/dtrace.make	Wed Jul 05 20:17:15 2017 +0200
@@ -171,11 +171,11 @@
 		./lib$(GENOFFS).so
 
 CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
-	cmp -s $@ $@.tmp; \
-	case $$? in \
-	0) rm -f $@.tmp;; \
-	*) rm -f $@ && mv $@.tmp $@ && echo Updated $@;; \
-	esac
+	if cmp -s $@ $@.tmp; then \
+	  rm -f $@.tmp; \
+	else \
+	  rm -f $@ && mv $@.tmp $@ && echo Updated $@; \
+	fi
 
 # $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
 $(JVMOFFS).h: $(GENOFFS)
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -567,16 +567,21 @@
   inline void load_with_trap_null_check(Register d, int si16, Register s1);
 
   // Load heap oop and decompress. Loaded oop may not be null.
-  inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg);
+  // Specify tmp to save one cycle.
+  inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg,
+                                     Register tmp = noreg);
+  // Store heap oop and decompress.  Decompressed oop may not be null.
+  // Specify tmp register if d should not be changed.
   inline void store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1,
-                                      /*specify if d must stay uncompressed*/ Register tmp = noreg);
+                                      Register tmp = noreg);
 
   // Null allowed.
   inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1 = noreg);
 
   // Encode/decode heap oop. Oop may not be null, else en/decoding goes wrong.
+  // src == d allowed.
   inline Register encode_heap_oop_not_null(Register d, Register src = noreg);
-  inline void decode_heap_oop_not_null(Register d);
+  inline Register decode_heap_oop_not_null(Register d, Register src = noreg);
 
   // Null allowed.
   inline void decode_heap_oop(Register d);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -311,11 +311,14 @@
   ld(d, si16, s1);
 }
 
-inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) {
+inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {
   if (UseCompressedOops) {
-    lwz(d, offs, s1);
+    // In disjoint mode decoding can save a cycle if src != dst.
+    Register narrowOop = (tmp != noreg && Universe::narrow_oop_base_disjoint()) ? tmp : d;
+    lwz(narrowOop, offs, s1);
     // Attention: no null check here!
-    decode_heap_oop_not_null(d);
+    Register res = decode_heap_oop_not_null(d, narrowOop);
+    assert(res == d, "caller will not consume loaded value");
   } else {
     ld(d, offs, s1);
   }
@@ -340,26 +343,36 @@
 }
 
 inline Register MacroAssembler::encode_heap_oop_not_null(Register d, Register src) {
-  Register current = (src!=noreg) ? src : d; // Compressed oop is in d if no src provided.
-  if (Universe::narrow_oop_base() != NULL) {
+  Register current = (src != noreg) ? src : d; // Oop to be compressed is in d if no src provided.
+  if (Universe::narrow_oop_base_overlaps()) {
     sub(d, current, R30);
     current = d;
   }
   if (Universe::narrow_oop_shift() != 0) {
-    srdi(d, current, LogMinObjAlignmentInBytes);
+    rldicl(d, current, 64-Universe::narrow_oop_shift(), 32);  // Clears the upper bits.
     current = d;
   }
   return current; // Encoded oop is in this register.
 }
 
-inline void MacroAssembler::decode_heap_oop_not_null(Register d) {
+inline Register MacroAssembler::decode_heap_oop_not_null(Register d, Register src) {
+  if (Universe::narrow_oop_base_disjoint() && src != noreg && src != d &&
+      Universe::narrow_oop_shift() != 0) {
+    mr(d, R30);
+    rldimi(d, src, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
+    return d;
+  }
+
+  Register current = (src != noreg) ? src : d; // Compressed oop is in d if no src provided.
   if (Universe::narrow_oop_shift() != 0) {
-    assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
-    sldi(d, d, LogMinObjAlignmentInBytes);
+    sldi(d, current, Universe::narrow_oop_shift());
+    current = d;
   }
   if (Universe::narrow_oop_base() != NULL) {
-    add(d, d, R30);
+    add(d, current, R30);
+    current = d;
   }
+  return current; // Decoded oop is in this register.
 }
 
 inline void MacroAssembler::decode_heap_oop(Register d) {
@@ -368,13 +381,7 @@
     cmpwi(CCR0, d, 0);
     beq(CCR0, isNull);
   }
-  if (Universe::narrow_oop_shift() != 0) {
-    assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
-    sldi(d, d, LogMinObjAlignmentInBytes);
-  }
-  if (Universe::narrow_oop_base() != NULL) {
-    add(d, d, R30);
-  }
+  decode_heap_oop_not_null(d);
   bind(isNull);
 }
 
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -172,15 +172,15 @@
 
   // Load the invoker, as MH -> MH.form -> LF.vmentry
   __ verify_oop(recv);
-  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv);
+  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv, temp2);
   __ verify_oop(method_temp);
-  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp);
+  __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
   __ verify_oop(method_temp);
-  // the following assumes that a Method* is normally compressed in the vmtarget field:
+  // The following assumes that a Method* is normally compressed in the vmtarget field:
   __ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp);
 
   if (VerifyMethodHandles && !for_compiler_entry) {
-    // make sure recv is already on stack
+    // Make sure recv is already on stack.
     __ ld(temp2, in_bytes(Method::const_offset()), method_temp);
     __ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2,
                         sizeof(u2), /*is_signed*/ false);
@@ -259,8 +259,9 @@
   }
 
   if (TraceMethodHandles) {
-    if (tmp_mh != noreg)
+    if (tmp_mh != noreg) {
       __ mr(R23_method_handle, tmp_mh);  // make stub happy
+    }
     trace_method_handle_interpreter_entry(_masm, iid);
   }
 
@@ -332,7 +333,7 @@
       if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
         Label L_ok;
         Register temp2_defc = temp2;
-        __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
+        __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
         load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
         __ verify_klass_ptr(temp2_defc);
         __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -407,7 +408,7 @@
       }
 
       Register temp2_intf = temp2;
-      __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
+      __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
       load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
       __ verify_klass_ptr(temp2_intf);
 
@@ -464,7 +465,7 @@
                  strstr(adaptername, "linkTo") == NULL);    // static linkers don't have MH
   const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23";
   tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT,
-                adaptername, mh_reg_name, (intptr_t) mh, (intptr_t) entry_sp);
+                adaptername, mh_reg_name, (intptr_t) mh, entry_sp);
 
   if (Verbose) {
     tty->print_cr("Registers:");
@@ -535,23 +536,22 @@
 
   BLOCK_COMMENT("trace_method_handle {");
 
-  int nbytes_save = 10 * 8;             // 10 volatile gprs
-  __ save_LR_CR(R0);
-  __ mr(R0, R1_SP);                     // saved_sp
-  assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0");
-  // Push_frame_reg_args only uses R0 if nbytes_save is wider than 16 bit.
-  __ push_frame_reg_args(nbytes_save, R0);
-  __ save_volatile_gprs(R1_SP, frame::abi_reg_args_size); // Except R0.
+  const Register tmp = R11; // Will be preserved.
+  const int nbytes_save = 11*8; // volatile gprs except R0
+  __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
+  __ save_LR_CR(tmp); // save in old frame
 
-  __ load_const(R3_ARG1, (address)adaptername);
+  __ mr(R5_ARG3, R1_SP);     // saved_sp
+  __ push_frame_reg_args(nbytes_save, tmp);
+
+  __ load_const_optimized(R3_ARG1, (address)adaptername, tmp);
   __ mr(R4_ARG2, R23_method_handle);
-  __ mr(R5_ARG3, R0);        // saved_sp
   __ mr(R6_ARG4, R1_SP);
   __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub));
 
-  __ restore_volatile_gprs(R1_SP, 112); // Except R0.
   __ pop_frame();
-  __ restore_LR_CR(R0);
+  __ restore_LR_CR(tmp);
+  __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
 
   BLOCK_COMMENT("} trace_method_handle");
 }
--- a/hotspot/src/cpu/ppc/vm/ppc.ad	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Wed Jul 05 20:17:15 2017 +0200
@@ -1,6 +1,6 @@
 //
-// Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
-// Copyright 2012, 2014 SAP AG. All rights reserved.
+// Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+// Copyright 2012, 2015 SAP AG. All rights reserved.
 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 //
 // This code is free software; you can redistribute it and/or modify it
@@ -2698,7 +2698,7 @@
         const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
         __ relocate(a.rspec());
       } else if (constant_reloc == relocInfo::metadata_type) {
-        AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
+        AddressLiteral a = __ constant_metadata_address((Metadata *)val);
         const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
         __ relocate(a.rspec());
       } else {
@@ -2727,7 +2727,7 @@
         const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
         __ relocate(a.rspec());
       } else if (constant_reloc == relocInfo::metadata_type) {
-        AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
+        AddressLiteral a = __ constant_metadata_address((Metadata *)val);
         const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
         __ relocate(a.rspec());
       } else {  // non-oop pointers, e.g. card mark base, heap top
@@ -6029,6 +6029,20 @@
   ins_pipe(pipe_class_default);
 %}
 
+// Optimize DecodeN for disjoint base.
+// Load base of compressed oops into a register
+instruct loadBase(iRegLdst dst) %{
+  effect(DEF dst);
+
+  format %{ "MR      $dst, r30_heapbase" %}
+  size(4);
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_or);
+    __ mr($dst$$Register, R30);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 // Loading ConN must be postalloc expanded so that edges between
 // the nodes are safe. They may not interfere with a safepoint.
 // GL TODO: This needs three instructions: better put this into the constant pool.
@@ -6724,13 +6738,12 @@
   ins_pipe(pipe_class_default);
 %}
 
-// base != 0
-// 32G aligned narrow oop base.
-instruct encodeP_32GAligned(iRegNdst dst, iRegPsrc src) %{
+// Disjoint narrow oop base.
+instruct encodeP_Disjoint(iRegNdst dst, iRegPsrc src) %{
   match(Set dst (EncodeP src));
-  predicate(false /* TODO: PPC port Universe::narrow_oop_base_disjoint()*/);
-
-  format %{ "EXTRDI  $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
+  predicate(Universe::narrow_oop_base_disjoint());
+
+  format %{ "EXTRDI  $dst, $src, #32, #3 \t// encode with disjoint base" %}
   size(4);
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@@ -6745,7 +6758,7 @@
   effect(TEMP crx);
   predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull &&
             Universe::narrow_oop_shift() != 0 &&
-            true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
+            Universe::narrow_oop_base_overlaps());
 
   format %{ "EncodeP $dst, $crx, $src \t// postalloc expanded" %}
   postalloc_expand( postalloc_expand_encode_oop(dst, src, crx));
@@ -6756,7 +6769,7 @@
   match(Set dst (EncodeP src));
   predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull &&
             Universe::narrow_oop_shift() != 0 &&
-            true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
+            Universe::narrow_oop_base_overlaps());
 
   format %{ "EncodeP $dst, $src\t// $src != Null, postalloc expanded" %}
   postalloc_expand( postalloc_expand_encode_oop_not_null(dst, src) );
@@ -6876,6 +6889,7 @@
              n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
             Universe::narrow_oop_shift() != 0 &&
             Universe::narrow_oop_base() != 0);
+  ins_cost(4 * DEFAULT_COST); // Should be more expensive than decodeN_Disjoint_isel_Ex.
   effect(TEMP crx);
 
   format %{ "DecodeN $dst, $src \t// Kills $crx, postalloc expanded" %}
@@ -6897,6 +6911,106 @@
   ins_pipe(pipe_class_default);
 %}
 
+// Optimize DecodeN for disjoint base.
+// Shift narrow oop and or it into register that already contains the heap base.
+// Base == dst must hold, and is assured by construction in postaloc_expand.
+instruct decodeN_mergeDisjoint(iRegPdst dst, iRegNsrc src, iRegLsrc base) %{
+  match(Set dst (DecodeN src));
+  effect(TEMP base);
+  predicate(false);
+
+  format %{ "RLDIMI  $dst, $src, shift, 32-shift \t// DecodeN (disjoint base)" %}
+  size(4);
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_rldimi);
+    __ rldimi($dst$$Register, $src$$Register, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+// Optimize DecodeN for disjoint base.
+// This node requires only one cycle on the critical path.
+// We must postalloc_expand as we can not express use_def effects where
+// the used register is L and the def'ed register P.
+instruct decodeN_Disjoint_notNull_Ex(iRegPdst dst, iRegNsrc src) %{
+  match(Set dst (DecodeN src));
+  effect(TEMP_DEF dst);
+  predicate((n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
+             n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
+            Universe::narrow_oop_base_disjoint());
+  ins_cost(DEFAULT_COST);
+
+  format %{ "MOV     $dst, R30 \t\n"
+            "RLDIMI  $dst, $src, shift, 32-shift \t// decode with disjoint base" %}
+  postalloc_expand %{
+    loadBaseNode *n1 = new loadBaseNode();
+    n1->add_req(NULL);
+    n1->_opnds[0] = op_dst;
+
+    decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
+    n2->add_req(n_region, n_src, n1);
+    n2->_opnds[0] = op_dst;
+    n2->_opnds[1] = op_src;
+    n2->_opnds[2] = op_dst;
+    n2->_bottom_type = _bottom_type;
+
+    ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+    ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+
+    nodes->push(n1);
+    nodes->push(n2);
+  %}
+%}
+
+instruct decodeN_Disjoint_isel_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{
+  match(Set dst (DecodeN src));
+  effect(TEMP_DEF dst, TEMP crx);
+  predicate((n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
+             n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
+            Universe::narrow_oop_base_disjoint() && VM_Version::has_isel());
+  ins_cost(3 * DEFAULT_COST);
+
+  format %{ "DecodeN  $dst, $src \t// decode with disjoint base using isel" %}
+  postalloc_expand %{
+    loadBaseNode *n1 = new loadBaseNode();
+    n1->add_req(NULL);
+    n1->_opnds[0] = op_dst;
+
+    cmpN_reg_imm0Node *n_compare  = new cmpN_reg_imm0Node();
+    n_compare->add_req(n_region, n_src);
+    n_compare->_opnds[0] = op_crx;
+    n_compare->_opnds[1] = op_src;
+    n_compare->_opnds[2] = new immN_0Oper(TypeNarrowOop::NULL_PTR);
+    
+    decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
+    n2->add_req(n_region, n_src, n1);
+    n2->_opnds[0] = op_dst;
+    n2->_opnds[1] = op_src;
+    n2->_opnds[2] = op_dst;
+    n2->_bottom_type = _bottom_type;
+
+    cond_set_0_ptrNode *n_cond_set = new cond_set_0_ptrNode();
+    n_cond_set->add_req(n_region, n_compare, n2);
+    n_cond_set->_opnds[0] = op_dst;
+    n_cond_set->_opnds[1] = op_crx;
+    n_cond_set->_opnds[2] = op_dst;
+    n_cond_set->_bottom_type = _bottom_type;
+
+    assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!");
+    ra_->set_oop(n_cond_set, true);
+    
+    ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+    ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx));
+    ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+    ra_->set_pair(n_cond_set->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+
+    nodes->push(n1);
+    nodes->push(n_compare);
+    nodes->push(n2);
+    nodes->push(n_cond_set);
+  %}
+%}
+
 // src != 0, shift != 0, base != 0
 instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{
   match(Set dst (DecodeN src));
@@ -6904,6 +7018,7 @@
              n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
             Universe::narrow_oop_shift() != 0 &&
             Universe::narrow_oop_base() != 0);
+  ins_cost(2 * DEFAULT_COST);
 
   format %{ "DecodeN $dst, $src \t// $src != NULL, postalloc expanded" %}
   postalloc_expand( postalloc_expand_decode_oop_not_null(dst, src));
@@ -6973,13 +7088,12 @@
   ins_pipe(pipe_class_default);
 %}
 
-// base != 0
-// 32G aligned narrow oop base.
-instruct encodePKlass_32GAligned(iRegNdst dst, iRegPsrc src) %{
+// Disjoint narrow oop base.
+instruct encodePKlass_Disjoint(iRegNdst dst, iRegPsrc src) %{
   match(Set dst (EncodePKlass src));
   predicate(false /* TODO: PPC port Universe::narrow_klass_base_disjoint()*/);
 
-  format %{ "EXTRDI  $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
+  format %{ "EXTRDI  $dst, $src, #32, #3 \t// encode with disjoint base" %}
   size(4);
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@@ -7486,7 +7600,7 @@
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     __ cmpxchgd($crx$$CondRegister, R0, $oldVal$$Register, $newVal$$Register, $mem_ptr$$Register,
-                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_atomic_update(),
                 noreg, NULL, true);
   %}
   ins_pipe(pipe_class_default);
@@ -10476,7 +10590,7 @@
   match(Set crx (CmpN src1 src2));
 
   size(4);
-  ins_cost(DEFAULT_COST);
+  ins_cost(2);
   format %{ "CMPLW   $crx, $src1, $src2 \t// compressed ptr" %}
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_cmpl);
@@ -10488,7 +10602,7 @@
 instruct cmpN_reg_imm0(flagsReg crx, iRegNsrc src1, immN_0 src2) %{
   match(Set crx (CmpN src1 src2));
   // Make this more expensive than zeroCheckN_iReg_imm0.
-  ins_cost(DEFAULT_COST);
+  ins_cost(2);
 
   format %{ "CMPLWI  $crx, $src1, $src2 \t// compressed ptr" %}
   size(4);
@@ -10508,6 +10622,7 @@
             _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne &&
             _leaf->as_If()->_prob >= PROB_LIKELY_MAG(4) &&
             Matcher::branches_to_uncommon_trap(_leaf));
+  ins_cost(1); // Should not be cheaper than zeroCheckN.
 
   ins_is_TrapBasedCheckNode(true);
 
@@ -10889,7 +11004,7 @@
 instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P superklass,
                              iRegPdst tmp_klass, iRegPdst tmp_arrayptr) %{
   match(Set result (PartialSubtypeCheck subklass superklass));
-  effect(TEMP result, TEMP tmp_klass, TEMP tmp_arrayptr);
+  effect(TEMP_DEF result, TEMP tmp_klass, TEMP tmp_arrayptr);
   ins_cost(DEFAULT_COST*10);
 
   format %{ "PartialSubtypeCheck $result = ($subklass instanceOf $superklass) tmp: $tmp_klass, $tmp_arrayptr" %}
@@ -11000,7 +11115,7 @@
   predicate(SpecialStringIndexOf);  // type check implicit by parameter type, See Matcher::match_rule_supported
   match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
 
-  effect(TEMP result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
+  effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
 
   ins_cost(150);
   format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
@@ -11037,7 +11152,7 @@
                              iRegIdst tmp1, iRegIdst tmp2,
                              flagsRegCR0 cr0, flagsRegCR1 cr1) %{
   match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
-  effect(USE_KILL needle, /* TDEF needle, */ TEMP result,
+  effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
          TEMP tmp1, TEMP tmp2);
   // Required for EA: check if it is still a type_array.
   predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@@ -11084,7 +11199,7 @@
                             iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
                             flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
   match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
-  effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP result,
+  effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
          TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
   // Required for EA: check if it is still a type_array.
   predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@@ -11118,7 +11233,7 @@
                         flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
   match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
   effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
-         TEMP result,
+         TEMP_DEF result,
          TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
   predicate(SpecialStringIndexOf);  // See Matcher::match_rule_supported.
   ins_cost(300);
@@ -11142,7 +11257,7 @@
                            iRegPdst tmp1, iRegPdst tmp2,
                            flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{
   match(Set result (StrEquals (Binary str1 str2) cntImm));
-  effect(TEMP result, TEMP tmp1, TEMP tmp2,
+  effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
          KILL cr0, KILL cr6, KILL ctr);
   predicate(SpecialStringEquals);  // See Matcher::match_rule_supported.
   ins_cost(250);
@@ -11165,7 +11280,7 @@
                        iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5,
                        flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
   match(Set result (StrEquals (Binary str1 str2) cnt));
-  effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
+  effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
          KILL cr0, KILL cr1, KILL cr6, KILL ctr);
   predicate(SpecialStringEquals);  // See Matcher::match_rule_supported.
   ins_cost(300);
@@ -11188,7 +11303,7 @@
 instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
                         iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
   match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
-  effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP result, TEMP tmp, KILL cr0, KILL ctr);
+  effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
   ins_cost(300);
 
   ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, 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
@@ -483,15 +483,6 @@
 
 }
 
-jbyte* G1PostBarrierStub::_byte_map_base = NULL;
-
-jbyte* G1PostBarrierStub::byte_map_base_slow() {
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  assert(bs->is_a(BarrierSet::G1SATBCTLogging),
-         "Must be if we're using this.");
-  return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
-}
-
 void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
   __ bind(_entry);
 
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1374,6 +1374,7 @@
 }
 
 void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
+                                                                Register method_counters,
                                                                 Register Rtmp,
                                                                 Label &profile_continue) {
   assert(ProfileInterpreter, "must be profiling interpreter");
@@ -1386,9 +1387,8 @@
   br_notnull_short(ImethodDataPtr, Assembler::pn, done);
 
   // Test to see if we should create a method data oop
-  AddressLiteral profile_limit((address) &InvocationCounter::InterpreterProfileLimit);
-  sethi(profile_limit, Rtmp);
-  ld(Rtmp, profile_limit.low10(), Rtmp);
+  Address profile_limit(method_counters, MethodCounters::interpreter_profile_limit_offset());
+  ld(profile_limit, Rtmp);
   cmp(invocation_count, Rtmp);
   // Use long branches because call_VM() code and following code generated by
   // test_backedge_count_for_osr() is large in debug VM.
@@ -2375,6 +2375,7 @@
 
 #ifndef CC_INTERP
 void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
+                                                             Register method_counters,
                                                              Register branch_bcp,
                                                              Register Rtmp ) {
   Label did_not_overflow;
@@ -2382,8 +2383,8 @@
   assert_different_registers(backedge_count, Rtmp, branch_bcp);
   assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
 
-  AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
-  load_contents(limit, Rtmp);
+  Address limit(method_counters, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()));
+  ld(limit, Rtmp);
   cmp_and_br_short(backedge_count, Rtmp, Assembler::lessUnsigned, Assembler::pt, did_not_overflow);
 
   // When ProfileInterpreter is on, the backedge_count comes from the
@@ -2500,17 +2501,13 @@
 
 // Jump if ((*counter_addr += increment) & mask) satisfies the condition.
 void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
-                                                        int increment, int mask,
+                                                        int increment, Address mask_addr,
                                                         Register scratch1, Register scratch2,
                                                         Condition cond, Label *where) {
   ld(counter_addr, scratch1);
   add(scratch1, increment, scratch1);
-  if (is_simm13(mask)) {
-    andcc(scratch1, mask, G0);
-  } else {
-    set(mask, scratch2);
-    andcc(scratch1, scratch2,  G0);
-  }
+  ld(mask_addr, scratch2);
+  andcc(scratch1, scratch2,  G0);
   br(cond, false, Assembler::pn, *where);
   delayed()->st(scratch1, counter_addr);
 }
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -267,7 +267,7 @@
   void increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
   void increment_backedge_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
 #ifndef CC_INTERP
-  void test_backedge_count_for_osr( Register backedge_count, Register branch_bcp, Register Rtmp );
+  void test_backedge_count_for_osr(Register backedge_count, Register method_counters, Register branch_bcp, Register Rtmp );
 
 #endif /* CC_INTERP */
   // Object locking
@@ -280,7 +280,7 @@
   void set_method_data_pointer_for_bcp();
   void test_method_data_pointer(Label& zero_continue);
   void verify_method_data_pointer();
-  void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
+  void test_invocation_counter_for_mdp(Register invocation_count, Register method_counters, Register Rtmp, Label &profile_continue);
 
   void set_mdp_data_at(int constant, Register value);
   void increment_mdp_data_at(Address counter, Register bumped_count,
@@ -291,7 +291,7 @@
                              Register bumped_count, Register scratch2,
                              bool decrement = false);
   void increment_mask_and_jump(Address counter_addr,
-                               int increment, int mask,
+                               int increment, Address mask_addr,
                                Register scratch1, Register scratch2,
                                Condition cond, Label *where);
   void set_mdp_flag_at(int flag_constant, Register scratch);
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -282,12 +282,11 @@
 void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
   // Note: In tiered we increment either counters in MethodCounters* or in
   // MDO depending if we're profiling or not.
-  const Register Rcounters = G3_scratch;
+  const Register G3_method_counters = G3_scratch;
   Label done;
 
   if (TieredCompilation) {
     const int increment = InvocationCounter::count_increment;
-    const int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
     Label no_mdo;
     if (ProfileInterpreter) {
       // If no method data exists, go to profile_continue.
@@ -297,6 +296,7 @@
       Address mdo_invocation_counter(G4_scratch,
                                      in_bytes(MethodData::invocation_counter_offset()) +
                                      in_bytes(InvocationCounter::counter_offset()));
+      Address mask(G4_scratch, in_bytes(MethodData::invoke_mask_offset()));
       __ increment_mask_and_jump(mdo_invocation_counter, increment, mask,
                                  G3_scratch, Lscratch,
                                  Assembler::zero, overflow);
@@ -305,20 +305,21 @@
 
     // Increment counter in MethodCounters*
     __ bind(no_mdo);
-    Address invocation_counter(Rcounters,
+    Address invocation_counter(G3_method_counters,
             in_bytes(MethodCounters::invocation_counter_offset()) +
             in_bytes(InvocationCounter::counter_offset()));
-    __ get_method_counters(Lmethod, Rcounters, done);
+    __ get_method_counters(Lmethod, G3_method_counters, done);
+    Address mask(G3_method_counters, in_bytes(MethodCounters::invoke_mask_offset()));
     __ increment_mask_and_jump(invocation_counter, increment, mask,
                                G4_scratch, Lscratch,
                                Assembler::zero, overflow);
     __ bind(done);
-  } else {
+  } else { // not TieredCompilation
     // Update standard invocation counters
-    __ get_method_counters(Lmethod, Rcounters, done);
-    __ increment_invocation_counter(Rcounters, O0, G4_scratch);
+    __ get_method_counters(Lmethod, G3_method_counters, done);
+    __ increment_invocation_counter(G3_method_counters, O0, G4_scratch);
     if (ProfileInterpreter) {
-      Address interpreter_invocation_counter(Rcounters,
+      Address interpreter_invocation_counter(G3_method_counters,
             in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
       __ ld(interpreter_invocation_counter, G4_scratch);
       __ inc(G4_scratch);
@@ -327,16 +328,16 @@
 
     if (ProfileInterpreter && profile_method != NULL) {
       // Test to see if we should create a method data oop
-      AddressLiteral profile_limit((address)&InvocationCounter::InterpreterProfileLimit);
-      __ load_contents(profile_limit, G3_scratch);
-      __ cmp_and_br_short(O0, G3_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
+      Address profile_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_profile_limit_offset()));
+      __ ld(profile_limit, G1_scratch);
+      __ cmp_and_br_short(O0, G1_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
 
       // if no method data exists, go to profile_method
       __ test_method_data_pointer(*profile_method);
     }
 
-    AddressLiteral invocation_limit((address)&InvocationCounter::InterpreterInvocationLimit);
-    __ load_contents(invocation_limit, G3_scratch);
+    Address invocation_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_invocation_limit_offset()));
+    __ ld(invocation_limit, G3_scratch);
     __ cmp(O0, G3_scratch);
     __ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
     __ delayed()->nop();
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1599,13 +1599,12 @@
     // Bump bytecode pointer by displacement (take the branch)
     __ delayed()->add( O1_disp, Lbcp, Lbcp );     // add to bc addr
 
-    const Register Rcounters = G3_scratch;
-    __ get_method_counters(Lmethod, Rcounters, Lforward);
+    const Register G3_method_counters = G3_scratch;
+    __ get_method_counters(Lmethod, G3_method_counters, Lforward);
 
     if (TieredCompilation) {
       Label Lno_mdo, Loverflow;
       int increment = InvocationCounter::count_increment;
-      int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
       if (ProfileInterpreter) {
         // If no method data exists, go to profile_continue.
         __ ld_ptr(Lmethod, Method::method_data_offset(), G4_scratch);
@@ -1614,6 +1613,7 @@
         // Increment backedge counter in the MDO
         Address mdo_backedge_counter(G4_scratch, in_bytes(MethodData::backedge_counter_offset()) +
                                                  in_bytes(InvocationCounter::counter_offset()));
+        Address mask(G4_scratch, in_bytes(MethodData::backedge_mask_offset()));
         __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, O0,
                                    Assembler::notZero, &Lforward);
         __ ba_short(Loverflow);
@@ -1621,9 +1621,10 @@
 
       // If there's no MDO, increment counter in MethodCounters*
       __ bind(Lno_mdo);
-      Address backedge_counter(Rcounters,
+      Address backedge_counter(G3_method_counters,
               in_bytes(MethodCounters::backedge_counter_offset()) +
               in_bytes(InvocationCounter::counter_offset()));
+      Address mask(G3_method_counters, in_bytes(MethodCounters::backedge_mask_offset()));
       __ increment_mask_and_jump(backedge_counter, increment, mask, G4_scratch, O0,
                                  Assembler::notZero, &Lforward);
       __ bind(Loverflow);
@@ -1663,18 +1664,19 @@
       __ jmp(O2, G0);
       __ delayed()->nop();
 
-    } else {
+    } else { // not TieredCompilation
       // Update Backedge branch separately from invocations
       const Register G4_invoke_ctr = G4;
-      __ increment_backedge_counter(Rcounters, G4_invoke_ctr, G1_scratch);
+      __ increment_backedge_counter(G3_method_counters, G4_invoke_ctr, G1_scratch);
       if (ProfileInterpreter) {
-        __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
+        __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_method_counters, G1_scratch, Lforward);
         if (UseOnStackReplacement) {
-          __ test_backedge_count_for_osr(O2_bumped_count, l_cur_bcp, G3_scratch);
+
+          __ test_backedge_count_for_osr(O2_bumped_count, G3_method_counters, l_cur_bcp, G1_scratch);
         }
       } else {
         if (UseOnStackReplacement) {
-          __ test_backedge_count_for_osr(G4_invoke_ctr, l_cur_bcp, G3_scratch);
+          __ test_backedge_count_for_osr(G4_invoke_ctr, G3_method_counters, l_cur_bcp, G1_scratch);
         }
       }
     }
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, 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
@@ -541,15 +541,6 @@
 
 }
 
-jbyte* G1PostBarrierStub::_byte_map_base = NULL;
-
-jbyte* G1PostBarrierStub::byte_map_base_slow() {
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  assert(bs->is_a(BarrierSet::G1SATBCTLogging),
-         "Must be if we're using this.");
-  return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
-}
-
 void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
   __ bind(_entry);
   assert(addr()->is_register(), "Precondition.");
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1360,7 +1360,7 @@
 
 // Jump if ((*counter_addr += increment) & mask) satisfies the condition.
 void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
-                                                        int increment, int mask,
+                                                        int increment, Address mask,
                                                         Register scratch, bool preloaded,
                                                         Condition cond, Label* where) {
   if (!preloaded) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -182,7 +182,7 @@
   void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
                              bool decrement = false);
   void increment_mask_and_jump(Address counter_addr,
-                               int increment, int mask,
+                               int increment, Address mask,
                                Register scratch, bool preloaded,
                                Condition cond, Label* where);
   void set_mdp_flag_at(Register mdp_in, int flag_constant);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1426,7 +1426,7 @@
 
 // Jump if ((*counter_addr += increment) & mask) satisfies the condition.
 void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
-                                                        int increment, int mask,
+                                                        int increment, Address mask,
                                                         Register scratch, bool preloaded,
                                                         Condition cond, Label* where) {
   if (!preloaded) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -191,7 +191,7 @@
   void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
                              bool decrement = false);
   void increment_mask_and_jump(Address counter_addr,
-                               int increment, int mask,
+                               int increment, Address mask,
                                Register scratch, bool preloaded,
                                Condition cond, Label* where);
   void set_mdp_flag_at(Register mdp_in, int flag_constant);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -346,7 +346,6 @@
   // depending if we're profiling or not.
   if (TieredCompilation) {
     int increment = InvocationCounter::count_increment;
-    int mask = ((1 << Tier0InvokeNotifyFreqLog)  - 1) << InvocationCounter::count_shift;
     Label no_mdo;
     if (ProfileInterpreter) {
       // Are we profiling?
@@ -356,6 +355,7 @@
       // Increment counter in the MDO
       const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
                                                 in_bytes(InvocationCounter::counter_offset()));
+      const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
       __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
       __ jmp(done);
     }
@@ -366,11 +366,12 @@
                   InvocationCounter::counter_offset());
 
     __ get_method_counters(rbx, rax, done);
+    const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
     __ increment_mask_and_jump(invocation_counter, increment, mask,
                                rcx, false, Assembler::zero, overflow);
     __ bind(done);
-  } else {
-    const Address backedge_counter  (rax,
+  } else { // not TieredCompilation
+    const Address backedge_counter(rax,
                   MethodCounters::backedge_counter_offset() +
                   InvocationCounter::counter_offset());
     const Address invocation_counter(rax,
@@ -400,16 +401,16 @@
 
     if (ProfileInterpreter && profile_method != NULL) {
       // Test to see if we should create a method data oop
-      __ cmp32(rcx,
-               ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
+      __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+      __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
       __ jcc(Assembler::less, *profile_method_continue);
 
       // if no method data exists, go to profile_method
       __ test_method_data_pointer(rax, *profile_method);
     }
 
-    __ cmp32(rcx,
-             ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
+    __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+    __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
     __ jcc(Assembler::aboveEqual, *overflow);
     __ bind(done);
   }
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -299,7 +299,6 @@
   // Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
   if (TieredCompilation) {
     int increment = InvocationCounter::count_increment;
-    int mask = ((1 << Tier0InvokeNotifyFreqLog)  - 1) << InvocationCounter::count_shift;
     Label no_mdo;
     if (ProfileInterpreter) {
       // Are we profiling?
@@ -309,6 +308,7 @@
       // Increment counter in the MDO
       const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
                                                 in_bytes(InvocationCounter::counter_offset()));
+      const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
       __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
       __ jmp(done);
     }
@@ -318,10 +318,11 @@
                   MethodCounters::invocation_counter_offset() +
                   InvocationCounter::counter_offset());
     __ get_method_counters(rbx, rax, done);
+    const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
     __ increment_mask_and_jump(invocation_counter, increment, mask, rcx,
                                false, Assembler::zero, overflow);
     __ bind(done);
-  } else {
+  } else { // not TieredCompilation
     const Address backedge_counter(rax,
                   MethodCounters::backedge_counter_offset() +
                   InvocationCounter::counter_offset());
@@ -350,14 +351,16 @@
 
     if (ProfileInterpreter && profile_method != NULL) {
       // Test to see if we should create a method data oop
-      __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
+      __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+      __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
       __ jcc(Assembler::less, *profile_method_continue);
 
       // if no method data exists, go to profile_method
       __ test_method_data_pointer(rax, *profile_method);
     }
 
-    __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
+    __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+    __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
     __ jcc(Assembler::aboveEqual, *overflow);
     __ bind(done);
   }
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1621,7 +1621,6 @@
     if (TieredCompilation) {
       Label no_mdo;
       int increment = InvocationCounter::count_increment;
-      int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
       if (ProfileInterpreter) {
         // Are we profiling?
         __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@@ -1630,6 +1629,7 @@
         // Increment the MDO backedge counter
         const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
                                                 in_bytes(InvocationCounter::counter_offset()));
+        const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
         __ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
                                    rax, false, Assembler::zero, &backedge_counter_overflow);
         __ jmp(dispatch);
@@ -1637,9 +1637,10 @@
       __ bind(no_mdo);
       // Increment backedge counter in MethodCounters*
       __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
+      const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
       __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
                                  rax, false, Assembler::zero, &backedge_counter_overflow);
-    } else {
+    } else { // not TieredCompilation
       // increment counter
       __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
       __ movl(rax, Address(rcx, be_offset));        // load backedge counter
@@ -1653,8 +1654,7 @@
 
       if (ProfileInterpreter) {
         // Test to see if we should create a method data oop
-        __ cmp32(rax,
-                 ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
+        __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
         __ jcc(Assembler::less, dispatch);
 
         // if no method data exists, go to profile method
@@ -1662,8 +1662,7 @@
 
         if (UseOnStackReplacement) {
           // check for overflow against rbx, which is the MDO taken count
-          __ cmp32(rbx,
-                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+          __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
           __ jcc(Assembler::below, dispatch);
 
           // When ProfileInterpreter is on, the backedge_count comes from the
@@ -1678,8 +1677,7 @@
       } else {
         if (UseOnStackReplacement) {
           // check for overflow against rax, which is the sum of the counters
-          __ cmp32(rax,
-                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+          __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
           __ jcc(Assembler::aboveEqual, backedge_counter_overflow);
 
         }
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1642,7 +1642,6 @@
     if (TieredCompilation) {
       Label no_mdo;
       int increment = InvocationCounter::count_increment;
-      int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
       if (ProfileInterpreter) {
         // Are we profiling?
         __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@@ -1651,6 +1650,7 @@
         // Increment the MDO backedge counter
         const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
                                            in_bytes(InvocationCounter::counter_offset()));
+        const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
         __ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
                                    rax, false, Assembler::zero, &backedge_counter_overflow);
         __ jmp(dispatch);
@@ -1658,9 +1658,10 @@
       __ bind(no_mdo);
       // Increment backedge counter in MethodCounters*
       __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
+         const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
       __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
                                  rax, false, Assembler::zero, &backedge_counter_overflow);
-    } else {
+    } else { // not TieredCompilation
       // increment counter
       __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
       __ movl(rax, Address(rcx, be_offset));        // load backedge counter
@@ -1674,8 +1675,7 @@
 
       if (ProfileInterpreter) {
         // Test to see if we should create a method data oop
-        __ cmp32(rax,
-                 ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
+        __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
         __ jcc(Assembler::less, dispatch);
 
         // if no method data exists, go to profile method
@@ -1683,8 +1683,7 @@
 
         if (UseOnStackReplacement) {
           // check for overflow against ebx which is the MDO taken count
-          __ cmp32(rbx,
-                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+          __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
           __ jcc(Assembler::below, dispatch);
 
           // When ProfileInterpreter is on, the backedge_count comes
@@ -1702,8 +1701,7 @@
         if (UseOnStackReplacement) {
           // check for overflow against eax, which is the sum of the
           // counters
-          __ cmp32(rax,
-                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+          __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
           __ jcc(Assembler::aboveEqual, backedge_counter_overflow);
 
         }
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -31,6 +31,7 @@
 #include "os_aix.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/perfMemory.hpp"
+#include "services/memTracker.hpp"
 #include "utilities/exceptions.hpp"
 
 // put OS-includes here
@@ -196,12 +197,37 @@
   return pid;
 }
 
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+static bool is_statbuf_secure(struct stat *statp) {
+  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+    // The path represents a link or some non-directory file type,
+    // which is not what we expected. Declare it insecure.
+    //
+    return false;
+  }
+  // We have an existing directory, check if the permissions are safe.
+  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+    // The directory is open for writing and could be subjected
+    // to a symlink or a hard link attack. Declare it insecure.
+    return false;
+  }
+  // See if the uid of the directory matches the effective uid of the process.
+  //
+  if (statp->st_uid != geteuid()) {
+    // The directory was not created by this user, declare it insecure.
+    return false;
+  }
+  return true;
+}
 
-// check if the given path is considered a secure directory for
+
+// Check if the given path is considered a secure directory for
 // the backing store files. Returns true if the directory exists
 // and is considered a secure location. Returns false if the path
 // is a symbolic link or if an error occurred.
-//
 static bool is_directory_secure(const char* path) {
   struct stat statbuf;
   int result = 0;
@@ -211,38 +237,276 @@
     return false;
   }
 
-  // the path exists, now check it's mode
-  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
-    // the path represents a link or some non-directory file type,
-    // which is not what we expected. declare it insecure.
-    //
+  // The path exists, see if it is secure.
+  return is_statbuf_secure(&statbuf);
+}
+
+// (Taken over from Solaris to support the O_NOFOLLOW case on AIX.)
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+static bool is_dirfd_secure(int dir_fd) {
+  struct stat statbuf;
+  int result = 0;
+
+  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  // The path exists, now check its mode.
+  return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+static bool is_same_fsobject(int fd1, int fd2) {
+  struct stat statbuf1;
+  struct stat statbuf2;
+  int result = 0;
+
+  RESTARTABLE(::fstat(fd1, &statbuf1), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+  RESTARTABLE(::fstat(fd2, &statbuf2), result);
+  if (result == OS_ERR) {
+    return false;
+  }
+
+  if ((statbuf1.st_ino == statbuf2.st_ino) &&
+      (statbuf1.st_dev == statbuf2.st_dev)) {
+    return true;
+  } else {
     return false;
   }
-  else {
-    // we have an existing directory, check if the permissions are safe.
-    //
-    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
-      // the directory is open for writing and could be subjected
-      // to a symlnk attack. declare it insecure.
-      //
-      return false;
+}
+
+// Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1.
+// We use the jdk6 implementation here.
+#ifndef O_NOFOLLOW
+// The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour
+// was done in jdk 5/6 hotspot by Oracle this way
+static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) {
+  struct stat orig_st;
+  struct stat new_st;
+  bool create;
+  int error;
+  int fd;
+
+  create = false;
+
+  if (lstat(path, &orig_st) != 0) {
+    if (errno == ENOENT && (oflag & O_CREAT) != 0) {
+      // File doesn't exist, but_we want to create it, add O_EXCL flag
+      // to make sure no-one creates it (or a symlink) before us
+      // This works as we expect with symlinks, from posix man page:
+      // 'If O_EXCL  and  O_CREAT  are set, and path names a symbolic
+      // link, open() shall fail and set errno to [EEXIST]'.
+      oflag |= O_EXCL;
+      create = true;
+    } else {
+      // File doesn't exist, and we are not creating it.
+      return OS_ERR;
+    }
+  } else {
+    // Lstat success, check if existing file is a link.
+    if ((orig_st.st_mode & S_IFMT) == S_IFLNK)  {
+      // File is a symlink.
+      errno = ELOOP;
+      return OS_ERR;
+    }
+  }
+
+  if (use_mode == true) {
+    fd = open(path, oflag, mode);
+  } else {
+    fd = open(path, oflag);
+  }
+
+  if (fd == OS_ERR) {
+    return fd;
+  }
+
+  // Can't do inode checks on before/after if we created the file.
+  if (create == false) {
+    if (fstat(fd, &new_st) != 0) {
+      // Keep errno from fstat, in case close also fails.
+      error = errno;
+      ::close(fd);
+      errno = error;
+      return OS_ERR;
+    }
+
+    if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) {
+      // File was tampered with during race window.
+      ::close(fd);
+      errno = EEXIST;
+      if (PrintMiscellaneous && Verbose) {
+        warning("possible file tampering attempt detected when opening %s", path);
+      }
+      return OS_ERR;
     }
   }
+
+  return fd;
+}
+
+static int open_o_nofollow(const char* path, int oflag, mode_t mode) {
+  return open_o_nofollow_impl(path, oflag, mode, true);
+}
+
+static int open_o_nofollow(const char* path, int oflag) {
+  return open_o_nofollow_impl(path, oflag, 0, false);
+}
+#endif
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+static DIR *open_directory_secure(const char* dirname) {
+  // Open the directory using open() so that it can be verified
+  // to be secure by calling is_dirfd_secure(), opendir() and then check
+  // to see if they are the same file system object.  This method does not
+  // introduce a window of opportunity for the directory to be attacked that
+  // calling opendir() and is_directory_secure() does.
+  int result;
+  DIR *dirp = NULL;
+
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+  // so provide a workaround in this case.
+#ifdef O_NOFOLLOW
+  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+#else
+  // workaround (jdk6 coding)
+  RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
+#endif
+
+  if (result == OS_ERR) {
+    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+    if (PrintMiscellaneous && Verbose) {
+      if (errno == ELOOP) {
+        warning("directory %s is a symlink and is not secure\n", dirname);
+      } else {
+        warning("could not open directory %s: %s\n", dirname, strerror(errno));
+      }
+    }
+    return dirp;
+  }
+  int fd = result;
+
+  // Determine if the open directory is secure.
+  if (!is_dirfd_secure(fd)) {
+    // The directory is not a secure directory.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Open the directory.
+  dirp = ::opendir(dirname);
+  if (dirp == NULL) {
+    // The directory doesn't exist, close fd and return.
+    os::close(fd);
+    return dirp;
+  }
+
+  // Check to make sure fd and dirp are referencing the same file system object.
+  if (!is_same_fsobject(fd, dirp->dd_fd)) {
+    // The directory is not secure.
+    os::close(fd);
+    os::closedir(dirp);
+    dirp = NULL;
+    return dirp;
+  }
+
+  // Close initial open now that we know directory is secure
+  os::close(fd);
+
+  return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions.  Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+  // Open the directory.
+  DIR* dirp = open_directory_secure(dirname);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+    return dirp;
+  }
+  int fd = dirp->dd_fd;
+
+  // Open a fd to the cwd and save it off.
+  int result;
+  RESTARTABLE(::open(".", O_RDONLY), result);
+  if (result == OS_ERR) {
+    *saved_cwd_fd = -1;
+  } else {
+    *saved_cwd_fd = result;
+  }
+
+  // Set the current directory to dirname by using the fd of the directory.
+  result = fchdir(fd);
+
+  return dirp;
+}
+
+// Close the directory and restore the current working directory.
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+  int result;
+  // If we have a saved cwd change back to it and close the fd.
+  if (saved_cwd_fd != -1) {
+    result = fchdir(saved_cwd_fd);
+    ::close(saved_cwd_fd);
+  }
+
+  // Close the directory.
+  os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+static bool is_file_secure(int fd, const char *filename) {
+
+  int result;
+  struct stat statbuf;
+
+  // Determine if the file is secure.
+  RESTARTABLE(::fstat(fd, &statbuf), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("fstat failed on %s: %s\n", filename, strerror(errno));
+    }
+    return false;
+  }
+  if (statbuf.st_nlink > 1) {
+    // A file with multiple links is not expected.
+    if (PrintMiscellaneous && Verbose) {
+      warning("file %s has multiple links\n", filename);
+    }
+    return false;
+  }
   return true;
 }
 
-
-// return the user name for the given user id
+// Return the user name for the given user id.
 //
-// the caller is expected to free the allocated memory.
-//
+// The caller is expected to free the allocated memory.
 static char* get_user_name(uid_t uid) {
 
   struct passwd pwent;
 
-  // determine the max pwbuf size from sysconf, and hardcode
+  // Determine the max pwbuf size from sysconf, and hardcode
   // a default if this not available through sysconf.
-  //
   long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
   if (bufsize == -1)
     bufsize = 1024;
@@ -344,7 +608,8 @@
     strcat(usrdir_name, "/");
     strcat(usrdir_name, dentry->d_name);
 
-    DIR* subdirp = os::opendir(usrdir_name);
+    // Open the user directory.
+    DIR* subdirp = open_directory_secure(usrdir_name);
 
     if (subdirp == NULL) {
       FREE_C_HEAP_ARRAY(char, usrdir_name);
@@ -464,28 +729,7 @@
   }
 }
 
-
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
-  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
-  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
-  strcpy(path, dirname);
-  strcat(path, "/");
-  strcat(path, filename);
-
-  remove_file(path);
-
-  FREE_C_HEAP_ARRAY(char, path);
-}
-
-
-// cleanup stale shared memory resources
+// Cleanup stale shared memory resources
 //
 // This method attempts to remove all stale shared memory files in
 // the named user temporary directory. It scans the named directory
@@ -493,33 +737,26 @@
 // process id is extracted from the file name and a test is run to
 // determine if the process is alive. If the process is not alive,
 // any stale file resources are removed.
-//
 static void cleanup_sharedmem_resources(const char* dirname) {
 
-  // open the user temp directory
-  DIR* dirp = os::opendir(dirname);
-
+  int saved_cwd_fd;
+  // Open the directory.
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   if (dirp == NULL) {
-    // directory doesn't exist, so there is nothing to cleanup
+     // Directory doesn't exist or is insecure, so there is nothing to cleanup.
     return;
   }
 
-  if (!is_directory_secure(dirname)) {
-    // the directory is not a secure directory
-    os::closedir(dirp);
-    return;
-  }
-
-  // for each entry in the directory that matches the expected file
+  // For each entry in the directory that matches the expected file
   // name pattern, determine if the file resources are stale and if
   // so, remove the file resources. Note, instrumented HotSpot processes
   // for this user may start and/or terminate during this search and
   // remove or create new files in this directory. The behavior of this
   // loop under these conditions is dependent upon the implementation of
   // opendir/readdir.
-  //
   struct dirent* entry;
   char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
   errno = 0;
   while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
 
@@ -529,56 +766,55 @@
 
       if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
 
-        // attempt to remove all unexpected files, except "." and ".."
-        remove_file(dirname, entry->d_name);
+        // Attempt to remove all unexpected files, except "." and "..".
+        unlink(entry->d_name);
       }
 
       errno = 0;
       continue;
     }
 
-    // we now have a file name that converts to a valid integer
+    // We now have a file name that converts to a valid integer
     // that could represent a process id . if this process id
     // matches the current process id or the process is not running,
     // then remove the stale file resources.
     //
-    // process liveness is detected by sending signal number 0 to
+    // Process liveness is detected by sending signal number 0 to
     // the process id (see kill(2)). if kill determines that the
     // process does not exist, then the file resources are removed.
     // if kill determines that that we don't have permission to
     // signal the process, then the file resources are assumed to
     // be stale and are removed because the resources for such a
     // process should be in a different user specific directory.
-    //
     if ((pid == os::current_process_id()) ||
         (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
 
-        remove_file(dirname, entry->d_name);
+        unlink(entry->d_name);
     }
     errno = 0;
   }
-  os::closedir(dirp);
-  FREE_C_HEAP_ARRAY(char, dbuf);
+
+  // Close the directory and reset the current working directory.
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
+
+  FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
 }
 
-// make the user specific temporary directory. Returns true if
+// Make the user specific temporary directory. Returns true if
 // the directory exists and is secure upon return. Returns false
 // if the directory exists but is either a symlink, is otherwise
 // insecure, or if an error occurred.
-//
 static bool make_user_tmp_dir(const char* dirname) {
 
-  // create the directory with 0755 permissions. note that the directory
+  // Create the directory with 0755 permissions. note that the directory
   // will be owned by euid::egid, which may not be the same as uid::gid.
-  //
   if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
     if (errno == EEXIST) {
       // The directory already exists and was probably created by another
       // JVM instance. However, this could also be the result of a
       // deliberate symlink. Verify that the existing directory is safe.
-      //
       if (!is_directory_secure(dirname)) {
-        // directory is not secure
+        // Directory is not secure.
         if (PrintMiscellaneous && Verbose) {
           warning("%s directory is insecure\n", dirname);
         }
@@ -614,19 +850,63 @@
     return -1;
   }
 
+  int saved_cwd_fd;
+  // Open the directory and set the current working directory to it.
+  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+  if (dirp == NULL) {
+    // Directory doesn't exist or is insecure, so cannot create shared
+    // memory file.
+    return -1;
+  }
+
+  // Open the filename in the current directory.
+  // Cannot use O_TRUNC here; truncation of an existing file has to happen
+  // after the is_file_secure() check below.
   int result;
 
-  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+  // so provide a workaround in this case.
+#ifdef O_NOFOLLOW
+  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
+#else
+  // workaround function (jdk6 code)
+  RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
+#endif
+
   if (result == OS_ERR) {
     if (PrintMiscellaneous && Verbose) {
-      warning("could not create file %s: %s\n", filename, strerror(errno));
+      if (errno == ELOOP) {
+        warning("file %s is a symlink and is not secure\n", filename);
+      } else {
+        warning("could not create file %s: %s\n", filename, strerror(errno));
+      }
     }
+    // Close the directory and reset the current working directory.
+    close_directory_secure_cwd(dirp, saved_cwd_fd);
+
     return -1;
   }
+  // Close the directory and reset the current working directory.
+  close_directory_secure_cwd(dirp, saved_cwd_fd);
 
   // save the file descriptor
   int fd = result;
 
+  // Check to see if the file is secure.
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  // Truncate the file to get rid of any existing data.
+  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+  if (result == OS_ERR) {
+    if (PrintMiscellaneous && Verbose) {
+      warning("could not truncate shared memory file: %s\n", strerror(errno));
+    }
+    ::close(fd);
+    return -1;
+  }
   // set the file size
   RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   if (result == OS_ERR) {
@@ -648,7 +928,14 @@
 
   // open the file
   int result;
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+  // so provide a workaround in this case
+#ifdef O_NOFOLLOW
   RESTARTABLE(::open(filename, oflags), result);
+#else
+  RESTARTABLE(::open_o_nofollow(filename, oflags), result);
+#endif
+
   if (result == OS_ERR) {
     if (errno == ENOENT) {
       THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -662,8 +949,15 @@
       THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
     }
   }
+  int fd = result;
 
-  return result;
+  // Check to see if the file is secure.
+  if (!is_file_secure(fd, filename)) {
+    ::close(fd);
+    return -1;
+  }
+
+  return fd;
 }
 
 // create a named shared memory region. returns the address of the
@@ -695,13 +989,21 @@
   char* dirname = get_user_tmp_dir(user_name);
   char* filename = get_sharedmem_filename(dirname, vmid);
 
+  // Get the short filename.
+  char* short_filename = strrchr(filename, '/');
+  if (short_filename == NULL) {
+    short_filename = filename;
+  } else {
+    short_filename++;
+  }
+
   // cleanup any stale shared memory files
   cleanup_sharedmem_resources(dirname);
 
   assert(((size > 0) && (size % os::vm_page_size() == 0)),
          "unexpected PerfMemory region size");
 
-  fd = create_sharedmem_resources(dirname, filename, size);
+  fd = create_sharedmem_resources(dirname, short_filename, size);
 
   FREE_C_HEAP_ARRAY(char, user_name);
   FREE_C_HEAP_ARRAY(char, dirname);
@@ -733,6 +1035,9 @@
   // clear the shared memory region
   (void)::memset((void*) mapAddress, 0, size);
 
+  // It does not go through os api, the operation has to record from here.
+  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
   return mapAddress;
 }
 
@@ -807,7 +1112,7 @@
   char* mapAddress;
   int result;
   int fd;
-  size_t size;
+  size_t size = 0;
   const char* luser = NULL;
 
   int mmap_prot;
@@ -819,12 +1124,18 @@
   // constructs for the file and the shared memory mapping.
   if (mode == PerfMemory::PERF_MODE_RO) {
     mmap_prot = PROT_READ;
+
+  // No O_NOFOLLOW defined at buildtime, and it is not documented for open.
+#ifdef O_NOFOLLOW
+    file_flags = O_RDONLY | O_NOFOLLOW;
+#else
     file_flags = O_RDONLY;
+#endif
   }
   else if (mode == PerfMemory::PERF_MODE_RW) {
 #ifdef LATER
     mmap_prot = PROT_READ | PROT_WRITE;
-    file_flags = O_RDWR;
+    file_flags = O_RDWR | O_NOFOLLOW;
 #else
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Unsupported access mode");
@@ -853,9 +1164,9 @@
   // store file, we don't follow them when attaching either.
   //
   if (!is_directory_secure(dirname)) {
-    FREE_C_HEAP_ARRAY(char, dirname);
+    FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
     if (luser != user) {
-      FREE_C_HEAP_ARRAY(char, luser);
+      FREE_C_HEAP_ARRAY(char, luser, mtInternal);
     }
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
               "Process not found");
@@ -901,6 +1212,9 @@
               "Could not map PerfMemory");
   }
 
+  // It does not go through os api, the operation has to record from here.
+  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
   *addr = mapAddress;
   *sizep = size;
 
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -428,9 +428,9 @@
   }
 
   // Diagnostic code to investigate JDK-6573254
-  int res = 50115;  // non-java thread
+  int res = 30115;  // non-java thread
   if (thread->is_Java_thread()) {
-    res = 40115;    // java thread
+    res = 20115;    // java thread
   }
 
   // Install a win32 structured exception handler around every thread created
@@ -3791,6 +3791,7 @@
 
     static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
     static CRITICAL_SECTION crit_sect;
+    static volatile jint process_exiting = 0;
     int i, j;
     DWORD res;
     HANDLE hproc, hthr;
@@ -3798,10 +3799,10 @@
     // The first thread that reached this point, initializes the critical section.
     if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
       warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
-    } else {
+    } else if (OrderAccess::load_acquire(&process_exiting) == 0) {
       EnterCriticalSection(&crit_sect);
 
-      if (what == EPT_THREAD) {
+      if (what == EPT_THREAD && OrderAccess::load_acquire(&process_exiting) == 0) {
         // Remove from the array those handles of the threads that have completed exiting.
         for (i = 0, j = 0; i < handle_count; ++i) {
           res = WaitForSingleObject(handles[i], 0 /* don't wait */);
@@ -3856,7 +3857,7 @@
         // The current exiting thread has stored its handle in the array, and now
         // should leave the critical section before calling _endthreadex().
 
-      } else { // what != EPT_THREAD
+      } else if (what != EPT_THREAD) {
         if (handle_count > 0) {
           // Before ending the process, make sure all the threads that had called
           // _endthreadex() completed.
@@ -3882,24 +3883,28 @@
           handle_count = 0;
         }
 
-        // End the process, not leaving critical section.
-        // This makes sure no other thread executes exit-related code at the same
-        // time, thus a race is avoided.
-        if (what == EPT_PROCESS) {
-          ::exit(exit_code);
-        } else {
-          _exit(exit_code);
-        }
+        OrderAccess::release_store(&process_exiting, 1);
       }
 
       LeaveCriticalSection(&crit_sect);
     }
+
+    if (what == EPT_THREAD) {
+      while (OrderAccess::load_acquire(&process_exiting) != 0) {
+        // Some other thread is about to call exit(), so we
+        // don't let the current thread proceed to _endthreadex()
+        SuspendThread(GetCurrentThread());
+        // Avoid busy-wait loop, if SuspendThread() failed.
+        Sleep(EXIT_TIMEOUT);
+      }
+    }
   }
 
   // We are here if either
   // - there's no 'race at exit' bug on this OS release;
   // - initialization of the critical section failed (unlikely);
-  // - the current thread has stored its handle and left the critical section.
+  // - the current thread has stored its handle and left the critical section;
+  // - the process-exiting thread has raised the flag and left the critical section.
   if (what == EPT_THREAD) {
     _endthreadex((unsigned)exit_code);
   } else if (what == EPT_PROCESS) {
--- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, 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
@@ -601,15 +601,6 @@
   LIR_Opr _addr;
   LIR_Opr _new_val;
 
-  static jbyte* _byte_map_base;
-  static jbyte* byte_map_base_slow();
-  static jbyte* byte_map_base() {
-    if (_byte_map_base == NULL) {
-      _byte_map_base = byte_map_base_slow();
-    }
-    return _byte_map_base;
-  }
-
  public:
   // addr (the address of the object head) and new_val must be registers.
   G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -32,6 +32,7 @@
 #include "ci/ciArrayKlass.hpp"
 #include "ci/ciInstance.hpp"
 #include "ci/ciObjArray.hpp"
+#include "runtime/arguments.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/vm_version.hpp"
@@ -3351,7 +3352,12 @@
   if (!x->inlinee()->is_accessor()) {
     CodeEmitInfo* info = state_for(x, x->state(), true);
     // Notify the runtime very infrequently only to take care of counter overflows
-    increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true);
+    int freq_log = Tier23InlineeNotifyFreqLog;
+    double scale;
+    if (_method->has_option_value("CompileThresholdScaling", scale)) {
+      freq_log = Arguments::scaled_freq_log(freq_log, scale);
+    }
+    increment_event_counter_impl(info, x->inlinee(), right_n_bits(freq_log), InvocationEntryBci, false, true);
   }
 }
 
@@ -3366,7 +3372,11 @@
     ShouldNotReachHere();
   }
   // Increment the appropriate invocation/backedge counter and notify the runtime.
-  increment_event_counter_impl(info, info->scope()->method(), (1 << freq_log) - 1, bci, backedge, true);
+  double scale;
+  if (_method->has_option_value("CompileThresholdScaling", scale)) {
+    freq_log = Arguments::scaled_freq_log(freq_log, scale);
+  }
+  increment_event_counter_impl(info, info->scope()->method(), right_n_bits(freq_log), bci, backedge, true);
 }
 
 void LIRGenerator::decrement_age(CodeEmitInfo* info) {
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp	Wed Jul 05 20:17:15 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
@@ -221,6 +221,30 @@
   return (const char*)end;
 }
 
+template <class T, class N> void CompactHashtable<T, N>::symbols_do(SymbolClosure *cl) {
+  assert(!DumpSharedSpaces, "run-time only");
+  for (juint i = 0; i < _bucket_count; i ++) {
+    juint bucket_info = _buckets[i];
+    juint bucket_offset = BUCKET_OFFSET(bucket_info);
+    int   bucket_type = BUCKET_TYPE(bucket_info);
+    juint* bucket = _buckets + bucket_offset;
+    juint* bucket_end = _buckets;
+
+    Symbol* sym;
+    if (bucket_type == COMPACT_BUCKET_TYPE) {
+      sym = (Symbol*)((void*)(_base_address + bucket[0]));
+      cl->do_symbol(&sym);
+    } else {
+      bucket_end += BUCKET_OFFSET(_buckets[i + 1]);
+      while (bucket < bucket_end) {
+        sym = (Symbol*)((void*)(_base_address + bucket[1]));
+        cl->do_symbol(&sym);
+        bucket += 2;
+      }
+    }
+  }
+}
+
 // Explicitly instantiate these types
 template class CompactHashtable<Symbol*, char>;
 
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp	Wed Jul 05 20:17:15 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
@@ -249,6 +249,9 @@
     }
     return NULL;
   }
+
+  // iterate over symbols
+  void symbols_do(SymbolClosure *cl);
 };
 
 ////////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 20:17:15 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
@@ -82,6 +82,10 @@
 
 // Call function for all symbols in the symbol table.
 void SymbolTable::symbols_do(SymbolClosure *cl) {
+  // all symbols from shared table
+  _shared_table.symbols_do(cl);
+
+  // all symbols from the dynamic table
   const int n = the_table()->table_size();
   for (int i = 0; i < n; i++) {
     for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -1546,10 +1546,15 @@
           no_control_flow = true; break;
         case Bytecodes::_getstatic :
         case Bytecodes::_putstatic :
+          // pass TRUE, operand can be an array type for getstatic/putstatic.
+          verify_field_instructions(
+            &bcs, &current_frame, cp, true, CHECK_VERIFY(this));
+          no_control_flow = false; break;
         case Bytecodes::_getfield :
         case Bytecodes::_putfield :
+          // pass FALSE, operand can't be an array type for getfield/putfield.
           verify_field_instructions(
-            &bcs, &current_frame, cp, CHECK_VERIFY(this));
+            &bcs, &current_frame, cp, false, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_invokevirtual :
         case Bytecodes::_invokespecial :
@@ -2107,6 +2112,7 @@
 void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs,
                                               StackMapFrame* current_frame,
                                               constantPoolHandle cp,
+                                              bool allow_arrays,
                                               TRAPS) {
   u2 index = bcs->get_index_u2();
   verify_cp_type(bcs->bci(), index, cp,
@@ -2126,8 +2132,8 @@
   // Get referenced class type
   VerificationType ref_class_type = cp_ref_index_to_type(
     index, cp, CHECK_VERIFY(this));
-  if (!ref_class_type.is_object()) {
-    /* Unreachable?  Class file parser verifies Fieldref contents */
+  if (!ref_class_type.is_object() &&
+    (!allow_arrays || !ref_class_type.is_array())) {
     verify_error(ErrorContext::bad_type(bcs->bci(),
         TypeOrigin::cp(index, ref_class_type)),
         "Expecting reference to class in class %s at constant pool index %d",
--- a/hotspot/src/share/vm/classfile/verifier.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -297,7 +297,7 @@
 
   void verify_field_instructions(
     RawBytecodeStream* bcs, StackMapFrame* current_frame,
-    constantPoolHandle cp, TRAPS);
+    constantPoolHandle cp, bool allow_arrays, TRAPS);
 
   void verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
--- a/hotspot/src/share/vm/code/codeCache.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -233,8 +233,8 @@
 ReservedCodeSpace CodeCache::reserve_heap_memory(size_t size) {
   // Determine alignment
   const size_t page_size = os::can_execute_large_page_memory() ?
-          MIN2(os::page_size_for_region(InitialCodeCacheSize, 8),
-               os::page_size_for_region(size, 8)) :
+          MIN2(os::page_size_for_region_aligned(InitialCodeCacheSize, 8),
+               os::page_size_for_region_aligned(size, 8)) :
           os::vm_page_size();
   const size_t granularity = os::vm_allocation_granularity();
   const size_t r_align = MAX2(page_size, granularity);
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1470,7 +1470,9 @@
 
   // The method may be explicitly excluded by the user.
   bool quietly;
-  if (CompilerOracle::should_exclude(method, quietly)) {
+  double scale;
+  if (CompilerOracle::should_exclude(method, quietly)
+      || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
     if (!quietly) {
       // This does not happen quietly...
       ResourceMark rm;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -162,8 +162,8 @@
          "we should have already filtered out humongous regions");
   assert(_end == orig_end(),
          "we should have already filtered out humongous regions");
-
-  _in_collection_set = false;
+  assert(!_in_collection_set,
+         err_msg("Should not clear heap region %u in the collection set", hrm_index()));
 
   set_allocation_context(AllocationContext::system());
   set_young_index_in_cset(-1);
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1194,8 +1194,10 @@
         return real_forwardee(old);
     }
 
-    new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
-                                       old, m, sz);
+    if (!_promotion_failed) {
+      new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
+                                        old, m, sz);
+    }
 
     if (new_obj == NULL) {
       // promotion failed, forward to self
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -61,9 +61,9 @@
 
 void GenerationSizer::initialize_size_info() {
   trace_gen_sizes("ps heap raw");
-  const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8);
+  const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8);
   const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
-  const size_t min_page_sz = os::page_size_for_region(_min_heap_byte_size, min_pages);
+  const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages);
   const size_t page_sz = MIN2(max_page_sz, min_page_sz);
 
   // Can a page size be something else than a power of two?
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -41,7 +41,7 @@
 
   const size_t words = bits / BitsPerWord;
   const size_t raw_bytes = words * sizeof(idx_t);
-  const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
+  const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10);
   const size_t granularity = os::vm_allocation_granularity();
   _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -403,7 +403,7 @@
 ParallelCompactData::create_vspace(size_t count, size_t element_size)
 {
   const size_t raw_bytes = count * element_size;
-  const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
+  const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10);
   const size_t granularity = os::vm_allocation_granularity();
   _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
 
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -53,7 +53,7 @@
 /*
  * USELABELS - If using GCC, then use labels for the opcode dispatching
  * rather -then a switch statement. This improves performance because it
- * gives us the oportunity to have the instructions that calculate the
+ * gives us the opportunity to have the instructions that calculate the
  * next opcode to jump to be intermixed with the rest of the instructions
  * that implement the opcode (see UPDATE_PC_AND_TOS_AND_CONTINUE macro).
  */
--- a/hotspot/src/share/vm/interpreter/invocationCounter.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/invocationCounter.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -36,7 +36,7 @@
 // Implementation notes: For space reasons, state & counter are both encoded in one word,
 // The state is encoded using some of the least significant bits, the counter is using the
 // more significant bits. The counter is incremented before a method is activated and an
-// action is triggered when when count() > limit().
+// action is triggered when count() > limit().
 
 class InvocationCounter VALUE_OBJ_CLASS_SPEC {
   friend class VMStructs;
@@ -48,7 +48,6 @@
     number_of_state_bits = 2,
     number_of_carry_bits = 1,
     number_of_noncount_bits = number_of_state_bits + number_of_carry_bits,
-    number_of_count_bits = BitsPerInt - number_of_noncount_bits,
     state_limit          = nth_bit(number_of_state_bits),
     count_grain          = nth_bit(number_of_state_bits + number_of_carry_bits),
     carry_mask           = right_n_bits(number_of_carry_bits) << number_of_state_bits,
@@ -68,6 +67,7 @@
     count_increment      = count_grain,          // use this value to increment the 32bit _counter word
     count_mask_value     = count_mask,           // use this value to mask the backedge counter
     count_shift          = number_of_noncount_bits,
+    number_of_count_bits = BitsPerInt - number_of_noncount_bits,
     count_limit          = nth_bit(number_of_count_bits - 1)
   };
 
--- a/hotspot/src/share/vm/memory/heap.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/memory/heap.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -104,8 +104,8 @@
   size_t page_size = os::vm_page_size();
   if (os::can_execute_large_page_memory()) {
     const size_t min_pages = 8;
-    page_size = MIN2(os::page_size_for_region(committed_size, min_pages),
-                     os::page_size_for_region(rs.size(), min_pages));
+    page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages),
+                     os::page_size_for_region_aligned(rs.size(), min_pages));
   }
 
   const size_t granularity = os::vm_allocation_granularity();
--- a/hotspot/src/share/vm/oops/method.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -412,15 +412,14 @@
   }
 
   methodHandle mh(m);
-  ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
-  MethodCounters* counters = MethodCounters::allocate(loader_data, THREAD);
+  MethodCounters* counters = MethodCounters::allocate(mh, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CompileBroker::log_metaspace_failure();
     ClassLoaderDataGraph::set_metaspace_oom(true);
     return NULL;   // return the exception (which is cleared)
   }
   if (!mh->init_method_counters(counters)) {
-    MetadataFactory::free_metadata(loader_data, counters);
+    MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters);
   }
   return mh->method_counters();
 }
--- a/hotspot/src/share/vm/oops/methodCounters.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -23,10 +23,11 @@
  */
 #include "precompiled.hpp"
 #include "oops/methodCounters.hpp"
-#include "runtime/thread.inline.hpp"
+#include "runtime/handles.inline.hpp"
 
-MethodCounters* MethodCounters::allocate(ClassLoaderData* loader_data, TRAPS) {
-  return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters();
+MethodCounters* MethodCounters::allocate(methodHandle mh, TRAPS) {
+  ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
+  return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters(mh);
 }
 
 void MethodCounters::clear_counters() {
--- a/hotspot/src/share/vm/oops/methodCounters.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -26,7 +26,9 @@
 #define SHARE_VM_OOPS_METHODCOUNTERS_HPP
 
 #include "oops/metadata.hpp"
+#include "compiler/compilerOracle.hpp"
 #include "interpreter/invocationCounter.hpp"
+#include "runtime/arguments.hpp"
 
 class MethodCounters: public MetaspaceObj {
  friend class VMStructs;
@@ -45,7 +47,11 @@
   // 3. (INT_MIN..0]                  - method is hot and will deopt and get
   //                                    recompiled without the counters
   int               _nmethod_age;
-
+  int               _interpreter_invocation_limit;        // per-method InterpreterInvocationLimit
+  int               _interpreter_backward_branch_limit;   // per-method InterpreterBackwardBranchLimit
+  int               _interpreter_profile_limit;           // per-method InterpreterProfileLimit
+  int               _invoke_mask;                         // per-method Tier0InvokeNotifyFreqLog
+  int               _backedge_mask;                       // per-method Tier0BackedgeNotifyFreqLog
 #ifdef TIERED
   float             _rate;                        // Events (invocation and backedge counter increments) per millisecond
   jlong             _prev_time;                   // Previous time the rate was acquired
@@ -53,15 +59,15 @@
   u1                _highest_osr_comp_level;      // Same for OSR level
 #endif
 
-  MethodCounters() : _interpreter_invocation_count(0),
-                     _interpreter_throwout_count(0),
-                     _number_of_breakpoints(0),
-                     _nmethod_age(INT_MAX)
+  MethodCounters(methodHandle mh) : _interpreter_invocation_count(0),
+                                    _interpreter_throwout_count(0),
+                                    _number_of_breakpoints(0),
+                                    _nmethod_age(INT_MAX)
 #ifdef TIERED
-                   , _rate(0),
-                     _prev_time(0),
-                     _highest_comp_level(0),
-                     _highest_osr_comp_level(0)
+                                 , _rate(0),
+                                   _prev_time(0),
+                                   _highest_comp_level(0),
+                                   _highest_osr_comp_level(0)
 #endif
   {
     invocation_counter()->init();
@@ -70,10 +76,28 @@
     if (StressCodeAging) {
       set_nmethod_age(HotMethodDetectionLimit);
     }
+
+    // Set per-method thresholds.
+    double scale = 1.0;
+    CompilerOracle::has_option_value(mh, "CompileThresholdScaling", scale);
+
+    int compile_threshold = Arguments::scaled_compile_threshold(CompileThreshold, scale);
+    _interpreter_invocation_limit = compile_threshold << InvocationCounter::count_shift;
+    if (ProfileInterpreter) {
+      // If interpreter profiling is enabled, the backward branch limit
+      // is compared against the method data counter rather than an invocation
+      // counter, therefore no shifting of bits is required.
+      _interpreter_backward_branch_limit = (compile_threshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100;
+    } else {
+      _interpreter_backward_branch_limit = ((compile_threshold * OnStackReplacePercentage) / 100) << InvocationCounter::count_shift;
+    }
+    _interpreter_profile_limit = ((compile_threshold * InterpreterProfilePercentage) / 100) << InvocationCounter::count_shift;
+    _invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+    _backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
   }
 
  public:
-  static MethodCounters* allocate(ClassLoaderData* loader_data, TRAPS);
+  static MethodCounters* allocate(methodHandle mh, TRAPS);
 
   void deallocate_contents(ClassLoaderData* loader_data) {}
   DEBUG_ONLY(bool on_stack() { return false; })  // for template
@@ -161,5 +185,24 @@
     return offset_of(MethodCounters, _interpreter_invocation_count);
   }
 
+  static ByteSize interpreter_invocation_limit_offset() {
+    return byte_offset_of(MethodCounters, _interpreter_invocation_limit);
+  }
+
+  static ByteSize interpreter_backward_branch_limit_offset() {
+    return byte_offset_of(MethodCounters, _interpreter_backward_branch_limit);
+  }
+
+  static ByteSize interpreter_profile_limit_offset() {
+    return byte_offset_of(MethodCounters, _interpreter_profile_limit);
+  }
+
+  static ByteSize invoke_mask_offset() {
+    return byte_offset_of(MethodCounters, _invoke_mask);
+  }
+
+  static ByteSize backedge_mask_offset() {
+    return byte_offset_of(MethodCounters, _backedge_mask);
+  }
 };
 #endif //SHARE_VM_OOPS_METHODCOUNTERS_HPP
--- a/hotspot/src/share/vm/oops/methodData.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -31,6 +31,7 @@
 #include "memory/heapInspection.hpp"
 #include "oops/methodData.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
+#include "runtime/arguments.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
@@ -1131,6 +1132,13 @@
   _backedge_counter.init();
   _invocation_counter_start = 0;
   _backedge_counter_start = 0;
+
+  // Set per-method invoke- and backedge mask.
+  double scale = 1.0;
+  CompilerOracle::has_option_value(_method, "CompileThresholdScaling", scale);
+  _invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+  _backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+
   _tenure_traps = 0;
   _num_loops = 0;
   _num_blocks = 0;
--- a/hotspot/src/share/vm/oops/methodData.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -2088,6 +2088,8 @@
   int               _invocation_counter_start;
   int               _backedge_counter_start;
   uint              _tenure_traps;
+  int               _invoke_mask;      // per-method Tier0InvokeNotifyFreqLog
+  int               _backedge_mask;    // per-method Tier0BackedgeNotifyFreqLog
 
 #if INCLUDE_RTM_OPT
   // State of RTM code generation during compilation of the method
@@ -2447,10 +2449,19 @@
   static ByteSize invocation_counter_offset() {
     return byte_offset_of(MethodData, _invocation_counter);
   }
+
   static ByteSize backedge_counter_offset() {
     return byte_offset_of(MethodData, _backedge_counter);
   }
 
+  static ByteSize invoke_mask_offset() {
+    return byte_offset_of(MethodData, _invoke_mask);
+  }
+
+  static ByteSize backedge_mask_offset() {
+    return byte_offset_of(MethodData, _backedge_mask);
+  }
+
   static ByteSize parameters_type_data_di_offset() {
     return byte_offset_of(MethodData, _parameters_type_data_di);
   }
--- a/hotspot/src/share/vm/opto/chaitin.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/chaitin.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -582,6 +582,9 @@
   // Peephole remove copies
   post_allocate_copy_removal();
 
+  // Merge multidefs if multiple defs representing the same value are used in a single block.
+  merge_multidefs();
+
 #ifdef ASSERT
   // Veify the graph after RA.
   verify(&live_arena);
--- a/hotspot/src/share/vm/opto/chaitin.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/chaitin.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -681,6 +681,32 @@
   // Extend the node to LRG mapping
   void add_reference( const Node *node, const Node *old_node);
 
+  // Record the first use of a def in the block for a register.
+  class RegDefUse {
+    Node* _def;
+    Node* _first_use;
+  public:
+    RegDefUse() : _def(NULL), _first_use(NULL) { }
+    Node* def() const       { return _def;       }
+    Node* first_use() const { return _first_use; }
+
+    void update(Node* def, Node* use) {
+      if (_def != def) {
+        _def = def;
+        _first_use = use;
+      }
+    }
+    void clear() {
+      _def = NULL;
+      _first_use = NULL;
+    }
+  };
+  typedef GrowableArray<RegDefUse> RegToDefUseMap;
+  int possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse);
+
+  // Merge nodes that are a part of a multidef lrg and produce the same value within a block.
+  void merge_multidefs();
+
 private:
 
   static int _final_loads, _final_stores, _final_copies, _final_memoves;
--- a/hotspot/src/share/vm/opto/doCall.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -94,7 +94,7 @@
   if (log != NULL) {
     int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1;
     int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
-    log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
+    log->begin_elem("call method='%d' count='%d' prof_factor='%f'",
                     log->identify(callee), site_count, prof_factor);
     if (call_does_dispatch)  log->print(" virtual='1'");
     if (allow_inline)     log->print(" inline='1'");
--- a/hotspot/src/share/vm/opto/escape.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -2010,14 +2010,9 @@
         bt = field->layout_type();
       } else {
         // Check for unsafe oop field access
-        for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-          int opcode = n->fast_out(i)->Opcode();
-          if (opcode == Op_StoreP || opcode == Op_LoadP ||
-              opcode == Op_StoreN || opcode == Op_LoadN) {
-            bt = T_OBJECT;
-            (*unsafe) = true;
-            break;
-          }
+        if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
+          bt = T_OBJECT;
+          (*unsafe) = true;
         }
       }
     } else if (adr_type->isa_aryptr()) {
@@ -2031,13 +2026,8 @@
       }
     } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
       // Allocation initialization, ThreadLocal field access, unsafe access
-      for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-        int opcode = n->fast_out(i)->Opcode();
-        if (opcode == Op_StoreP || opcode == Op_LoadP ||
-            opcode == Op_StoreN || opcode == Op_LoadN) {
-          bt = T_OBJECT;
-          break;
-        }
+      if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
+        bt = T_OBJECT;
       }
     }
   }
@@ -3092,13 +3082,7 @@
         continue;
     } else if (n->Opcode() == Op_EncodeISOArray) {
       // get the memory projection
-      for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-        Node *use = n->fast_out(i);
-        if (use->Opcode() == Op_SCMemProj) {
-          n = use;
-          break;
-        }
-      }
+      n = n->find_out_with(Op_SCMemProj);
       assert(n->Opcode() == Op_SCMemProj, "memory projection required");
     } else {
       assert(n->is_Mem(), "memory node required.");
@@ -3122,13 +3106,7 @@
         continue;  // don't push users
       } else if (n->is_LoadStore()) {
         // get the memory projection
-        for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-          Node *use = n->fast_out(i);
-          if (use->Opcode() == Op_SCMemProj) {
-            n = use;
-            break;
-          }
-        }
+        n = n->find_out_with(Op_SCMemProj);
         assert(n->Opcode() == Op_SCMemProj, "memory projection required");
       }
     }
--- a/hotspot/src/share/vm/opto/ifg.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/ifg.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -535,12 +535,8 @@
       // The method add_input_to_liveout() keeps such nodes alive (put them on liveout list)
       // when it sees SCMemProj node in a block. Unfortunately SCMemProj node could be placed
       // in block in such order that KILL MachProj nodes are processed first.
-      uint cnt = def->outcnt();
-      for (uint i = 0; i < cnt; i++) {
-        Node* proj = def->raw_out(i);
-        if (proj->Opcode() == Op_SCMemProj) {
-          return false;
-        }
+      if (def->has_out_with(Op_SCMemProj)) {
+        return false;
       }
     }
     b->remove_node(location);
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -2057,10 +2057,9 @@
   }
   Node *main_cmp = main_bol->in(1);
   if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
-    _igvn.hash_delete(main_bol);
     main_cmp = main_cmp->clone();// Clone a private CmpNode
     register_new_node( main_cmp, main_cle->in(0) );
-    main_bol->set_req(1,main_cmp);
+    _igvn.replace_input_of(main_bol, 1, main_cmp);
   }
   // Hack the now-private loop bounds
   _igvn.replace_input_of(main_cmp, 2, main_limit);
--- a/hotspot/src/share/vm/opto/machnode.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/machnode.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -616,6 +616,29 @@
 #endif
 };
 
+// MachMergeNode is similar to a PhiNode in a sense it merges multiple values,
+// however it doesn't have a control input and is more like a MergeMem.
+// It is inserted after the register allocation is done to ensure that nodes use single
+// definition of a multidef lrg in a block.
+class MachMergeNode : public MachIdealNode {
+public:
+  MachMergeNode(Node *n1) {
+    init_class_id(Class_MachMerge);
+    add_req(NULL);
+    add_req(n1);
+  }
+  virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); }
+  virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); }
+  virtual const class Type *bottom_type() const { return in(1)->bottom_type(); }
+  virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); }
+  virtual uint oper_input_base() const { return 1; }
+  virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
+  virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
+#ifndef PRODUCT
+  virtual const char *Name() const { return "MachMerge"; }
+#endif
+};
+
 //------------------------------MachBranchNode--------------------------------
 // Abstract machine branch Node
 class MachBranchNode : public MachIdealNode {
--- a/hotspot/src/share/vm/opto/macro.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/macro.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -258,14 +258,7 @@
     // Search for CastP2X->Xor->URShift->Cmp path which
     // checks if the store done to a different from the value's region.
     // And replace Cmp with #0 (false) to collapse G1 post barrier.
-    Node* xorx = NULL;
-    for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
-      Node* u = p2x->fast_out(i);
-      if (u->Opcode() == Op_XorX) {
-        xorx = u;
-        break;
-      }
-    }
+    Node* xorx = p2x->find_out_with(Op_XorX);
     assert(xorx != NULL, "missing G1 post barrier");
     Node* shift = xorx->unique_out();
     Node* cmpx = shift->unique_out();
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -2609,7 +2609,6 @@
     return false; // if not a distinct instance, there may be aliases of the address
   for (DUIterator_Fast imax, i = adr->fast_outs(imax); i < imax; i++) {
     Node *use = adr->fast_out(i);
-    int opc = use->Opcode();
     if (use->is_Load() || use->is_LoadStore()) {
       return false;
     }
--- a/hotspot/src/share/vm/opto/node.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/node.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -881,6 +881,34 @@
     return (Node*) this;
 }
 
+// Find out of current node that matches opcode.
+Node* Node::find_out_with(int opcode) {
+  for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+    Node* use = fast_out(i);
+    if (use->Opcode() == opcode) {
+      return use;
+    }
+  }
+  return NULL;
+}
+
+// Return true if the current node has an out that matches opcode.
+bool Node::has_out_with(int opcode) {
+  return (find_out_with(opcode) != NULL);
+}
+
+// Return true if the current node has an out that matches any of the opcodes.
+bool Node::has_out_with(int opcode1, int opcode2, int opcode3, int opcode4) {
+  for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+      int opcode = fast_out(i)->Opcode();
+      if (opcode == opcode1 || opcode == opcode2 || opcode == opcode3 || opcode == opcode4) {
+        return true;
+      }
+  }
+  return false;
+}
+
+
 //---------------------------uncast_helper-------------------------------------
 Node* Node::uncast_helper(const Node* p) {
 #ifdef ASSERT
--- a/hotspot/src/share/vm/opto/node.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/node.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -98,6 +98,7 @@
 class MachSafePointNode;
 class MachSpillCopyNode;
 class MachTempNode;
+class MachMergeNode;
 class Matcher;
 class MemBarNode;
 class MemBarStoreStoreNode;
@@ -436,6 +437,13 @@
     return (this->uncast() == n->uncast());
   }
 
+  // Find out of current node that matches opcode.
+  Node* find_out_with(int opcode);
+  // Return true if the current node has an out that matches opcode.
+  bool has_out_with(int opcode);
+  // Return true if the current node has an out that matches any of the opcodes.
+  bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
+
 private:
   static Node* uncast_helper(const Node* n);
 
@@ -507,18 +515,25 @@
 
 //----------------- Other Node Properties
 
-  // Generate class id for some ideal nodes to avoid virtual query
-  // methods is_<Node>().
-  // Class id is the set of bits corresponded to the node class and all its
-  // super classes so that queries for super classes are also valid.
-  // Subclasses of the same super class have different assigned bit
-  // (the third parameter in the macro DEFINE_CLASS_ID).
-  // Classes with deeper hierarchy are declared first.
-  // Classes with the same hierarchy depth are sorted by usage frequency.
+  // Generate class IDs for (some) ideal nodes so that it is possible to determine
+  // the type of a node using a non-virtual method call (the method is_<Node>() below).
+  //
+  // A class ID of an ideal node is a set of bits. In a class ID, a single bit determines
+  // the type of the node the ID represents; another subset of an ID's bits are reserved
+  // for the superclasses of the node represented by the ID.
+  //
+  // By design, if A is a supertype of B, A.is_B() returns true and B.is_A()
+  // returns false. A.is_A() returns true.
   //
-  // The query method masks the bits to cut off bits of subclasses
-  // and then compare the result with the class id
-  // (see the macro DEFINE_CLASS_QUERY below).
+  // If two classes, A and B, have the same superclass, a different bit of A's class id
+  // is reserved for A's type than for B's type. That bit is specified by the third
+  // parameter in the macro DEFINE_CLASS_ID.
+  //
+  // By convention, classes with deeper hierarchy are declared first. Moreover,
+  // classes with the same hierarchy depth are sorted by usage frequency.
+  //
+  // The query method masks the bits to cut off bits of subclasses and then compares
+  // the result with the class id (see the macro DEFINE_CLASS_QUERY below).
   //
   //  Class_MachCall=30, ClassMask_MachCall=31
   // 12               8               4               0
@@ -592,6 +607,7 @@
       DEFINE_CLASS_ID(MachTemp,         Mach, 3)
       DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
       DEFINE_CLASS_ID(MachConstant,     Mach, 5)
+      DEFINE_CLASS_ID(MachMerge,        Mach, 6)
 
     DEFINE_CLASS_ID(Type,  Node, 2)
       DEFINE_CLASS_ID(Phi,   Type, 0)
@@ -763,6 +779,7 @@
   DEFINE_CLASS_QUERY(MachSafePoint)
   DEFINE_CLASS_QUERY(MachSpillCopy)
   DEFINE_CLASS_QUERY(MachTemp)
+  DEFINE_CLASS_QUERY(MachMerge)
   DEFINE_CLASS_QUERY(Mem)
   DEFINE_CLASS_QUERY(MemBar)
   DEFINE_CLASS_QUERY(MemBarStoreStore)
--- a/hotspot/src/share/vm/opto/parse1.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -441,7 +441,7 @@
 
   CompileLog* log = C->log();
   if (log != NULL) {
-    log->begin_head("parse method='%d' uses='%g'",
+    log->begin_head("parse method='%d' uses='%f'",
                     log->identify(parse_method), expected_uses);
     if (depth() == 1 && C->is_osr_compilation()) {
       log->print(" osr_bci='%d'", C->entry_bci());
--- a/hotspot/src/share/vm/opto/parse2.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -832,7 +832,7 @@
       sprintf(prob_str_buf, "%g", prob);
       prob_str = prob_str_buf;
     }
-    C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%g' prob='%s'",
+    C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%f' prob='%s'",
                    iter().get_dest(), taken, not_taken, cnt, prob_str);
   }
   return prob;
--- a/hotspot/src/share/vm/opto/phase.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/phase.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -110,6 +110,7 @@
     tty->print_cr ("         Compute Liveness:    %7.3f s", timers[_t_computeLive].seconds());
     tty->print_cr ("         Regalloc Split:      %7.3f s", timers[_t_regAllocSplit].seconds());
     tty->print_cr ("         Postalloc Copy Rem:  %7.3f s", timers[_t_postAllocCopyRemoval].seconds());
+    tty->print_cr ("         Merge multidefs:     %7.3f s", timers[_t_mergeMultidefs].seconds());
     tty->print_cr ("         Fixup Spills:        %7.3f s", timers[_t_fixupSpills].seconds());
     tty->print_cr ("         Compact:             %7.3f s", timers[_t_chaitinCompact].seconds());
     tty->print_cr ("         Coalesce 1:          %7.3f s", timers[_t_chaitinCoalesce1].seconds());
@@ -126,6 +127,7 @@
        timers[_t_computeLive].seconds() +
        timers[_t_regAllocSplit].seconds() +
        timers[_t_postAllocCopyRemoval].seconds() +
+       timers[_t_mergeMultidefs].seconds() +
        timers[_t_fixupSpills].seconds() +
        timers[_t_chaitinCompact].seconds() +
        timers[_t_chaitinCoalesce1].seconds() +
--- a/hotspot/src/share/vm/opto/phase.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/phase.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -88,6 +88,7 @@
       _t_computeLive,
       _t_regAllocSplit,
       _t_postAllocCopyRemoval,
+      _t_mergeMultidefs,
       _t_fixupSpills,
       _t_chaitinCompact,
       _t_chaitinCoalesce1,
--- a/hotspot/src/share/vm/opto/postaloc.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/postaloc.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -263,20 +263,6 @@
   // intermediate copies might be illegal, i.e., value is stored down to stack
   // then reloaded BUT survives in a register the whole way.
   Node *val = skip_copies(n->in(k));
-
-  if (val == x && nk_idx != 0 &&
-      regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
-      _lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) {
-    // When rematerialzing nodes and stretching lifetimes, the
-    // allocator will reuse the original def for multidef LRG instead
-    // of the current reaching def because it can't know it's safe to
-    // do so.  After allocation completes if they are in the same LRG
-    // then it should use the current reaching def instead.
-    n->set_req(k, regnd[nk_reg]);
-    blk_adjust += yank_if_dead(val, current_block, &value, &regnd);
-    val = skip_copies(n->in(k));
-  }
-
   if (val == x) return blk_adjust; // No progress?
 
   int n_regs = RegMask::num_registers(val->ideal_reg());
@@ -382,6 +368,94 @@
   return false;
 }
 
+// The algorithms works as follows:
+// We traverse the block top to bottom. possibly_merge_multidef() is invoked for every input edge k
+// of the instruction n. We check to see if the input is a multidef lrg. If it is, we record the fact that we've
+// seen a definition (coming as an input) and add that fact to the reg2defuse array. The array maps registers to their
+// current reaching definitions (we track only multidefs though). With each definition we also associate the first
+// instruction we saw use it. If we encounter the situation when we observe an def (an input) that is a part of the
+// same lrg but is different from the previous seen def we merge the two with a MachMerge node and substitute
+// all the uses that we've seen so far to use the merge. After that we keep replacing the new defs in the same lrg
+// as they get encountered with the merge node and keep adding these defs to the merge inputs.
+void PhaseChaitin::merge_multidefs() {
+  Compile::TracePhase tp("mergeMultidefs", &timers[_t_mergeMultidefs]);
+  ResourceMark rm;
+  // Keep track of the defs seen in registers and collect their uses in the block.
+  RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse());
+  for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
+    Block* block = _cfg.get_block(i);
+    for (uint j = 1; j < block->number_of_nodes(); j++) {
+      Node* n = block->get_node(j);
+      if (n->is_Phi()) continue;
+      for (uint k = 1; k < n->req(); k++) {
+        j += possibly_merge_multidef(n, k, block, reg2defuse);
+      }
+      // Null out the value produced by the instruction itself, since we're only interested in defs
+      // implicitly defined by the uses. We are actually interested in tracking only redefinitions
+      // of the multidef lrgs in the same register. For that matter it's enough to track changes in
+      // the base register only and ignore other effects of multi-register lrgs and fat projections.
+      // It is also ok to ignore defs coming from singledefs. After an implicit overwrite by one of
+      // those our register is guaranteed to be used by another lrg and we won't attempt to merge it.
+      uint lrg = _lrg_map.live_range_id(n);
+      if (lrg > 0 && lrgs(lrg).is_multidef()) {
+        OptoReg::Name reg = lrgs(lrg).reg();
+        reg2defuse.at(reg).clear();
+      }
+    }
+    // Clear reg->def->use tracking for the next block
+    for (int j = 0; j < reg2defuse.length(); j++) {
+      reg2defuse.at(j).clear();
+    }
+  }
+}
+
+int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) {
+  int blk_adjust = 0;
+
+  uint lrg = _lrg_map.live_range_id(n->in(k));
+  if (lrg > 0 && lrgs(lrg).is_multidef()) {
+    OptoReg::Name reg = lrgs(lrg).reg();
+
+    Node* def = reg2defuse.at(reg).def();
+    if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) {
+      // Same lrg but different node, we have to merge.
+      MachMergeNode* merge;
+      if (def->is_MachMerge()) { // is it already a merge?
+        merge = def->as_MachMerge();
+      } else {
+        merge = new MachMergeNode(def);
+
+        // Insert the merge node into the block before the first use.
+        uint use_index = block->find_node(reg2defuse.at(reg).first_use());
+        block->insert_node(merge, use_index++);
+
+        // Let the allocator know about the new node, use the same lrg
+        _lrg_map.extend(merge->_idx, lrg);
+        blk_adjust++;
+
+        // Fixup all the uses (there is at least one) that happened between the first
+        // use and before the current one.
+        for (; use_index < block->number_of_nodes(); use_index++) {
+          Node* use = block->get_node(use_index);
+          if (use == n) {
+            break;
+          }
+          use->replace_edge(def, merge);
+        }
+      }
+      if (merge->find_edge(n->in(k)) == -1) {
+        merge->add_req(n->in(k));
+      }
+      n->set_req(k, merge);
+    }
+
+    // update the uses
+    reg2defuse.at(reg).update(n->in(k), n);
+  }
+
+  return blk_adjust;
+}
+
 
 //------------------------------post_allocate_copy_removal---------------------
 // Post-Allocation peephole copy removal.  We do this in 1 pass over the
--- a/hotspot/src/share/vm/opto/stringopts.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/opto/stringopts.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1507,10 +1507,12 @@
       }
       case StringConcat::StringMode: {
         const Type* type = kit.gvn().type(arg);
+        Node* count = NULL;
         if (type == TypePtr::NULL_PTR) {
           // replace the argument with the null checked version
           arg = null_string;
           sc->set_argument(argi, arg);
+          count = kit.load_String_length(kit.control(), arg);
         } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
           // s = s != null ? s : "null";
           // length = length + (s.count - s.offset);
@@ -1533,10 +1535,13 @@
           // replace the argument with the null checked version
           arg = phi;
           sc->set_argument(argi, arg);
+          count = kit.load_String_length(kit.control(), arg);
+        } else {
+          // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP
+          // kit.control might be a different test, that can be hoisted above the actual nullcheck
+          // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck.
+          count = kit.load_String_length(NULL, arg);
         }
-
-        Node* count = kit.load_String_length(kit.control(), arg);
-
         length = __ AddI(length, count);
         string_sizes->init_req(argi, NULL);
         break;
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -68,11 +68,11 @@
 
   ~JvmtiConstantPoolReconstituter() {
     if (_symmap != NULL) {
-      os::free(_symmap);
+      delete _symmap;
       _symmap = NULL;
     }
     if (_classmap != NULL) {
-      os::free(_classmap);
+      delete _classmap;
       _classmap = NULL;
     }
   }
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1046,10 +1046,16 @@
 {
   assert(str->klass() == SystemDictionary::String_klass(), "not a string");
 
+  typeArrayOop s_value = java_lang_String::value(str);
+
+  // JDK-6584008: the value field may be null if a String instance is
+  // partially constructed.
+  if (s_value == NULL) {
+    return 0;
+  }
   // get the string value and length
   // (string value may be offset from the base)
   int s_len = java_lang_String::length(str);
-  typeArrayOop s_value = java_lang_String::value(str);
   int s_offset = java_lang_String::offset(str);
   jchar* value;
   if (s_len > 0) {
--- a/hotspot/src/share/vm/prims/perf.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/prims/perf.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -100,6 +100,11 @@
 
   PerfWrapper("Perf_Detach");
 
+  if (!UsePerfData) {
+    // With -XX:-UsePerfData, detach is just a NOP
+    return;
+  }
+
   void* address = 0;
   jlong capacity = 0;
 
--- a/hotspot/src/share/vm/prims/unsafe.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/prims/unsafe.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, 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
@@ -1104,43 +1104,6 @@
 
 
 
-UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
-  UnsafeWrapper("Unsafe_MonitorEnter");
-  {
-    if (jobj == NULL) {
-      THROW(vmSymbols::java_lang_NullPointerException());
-    }
-    Handle obj(thread, JNIHandles::resolve_non_null(jobj));
-    ObjectSynchronizer::jni_enter(obj, CHECK);
-  }
-UNSAFE_END
-
-
-UNSAFE_ENTRY(jboolean, Unsafe_TryMonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
-  UnsafeWrapper("Unsafe_TryMonitorEnter");
-  {
-    if (jobj == NULL) {
-      THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
-    }
-    Handle obj(thread, JNIHandles::resolve_non_null(jobj));
-    bool res = ObjectSynchronizer::jni_try_enter(obj, CHECK_0);
-    return (res ? JNI_TRUE : JNI_FALSE);
-  }
-UNSAFE_END
-
-
-UNSAFE_ENTRY(void, Unsafe_MonitorExit(JNIEnv *env, jobject unsafe, jobject jobj))
-  UnsafeWrapper("Unsafe_MonitorExit");
-  {
-    if (jobj == NULL) {
-      THROW(vmSymbols::java_lang_NullPointerException());
-    }
-    Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
-    ObjectSynchronizer::jni_exit(obj(), CHECK);
-  }
-UNSAFE_END
-
-
 UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr))
   UnsafeWrapper("Unsafe_ThrowException");
   {
@@ -1365,8 +1328,6 @@
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
     {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
-    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
-    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
     {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)}
 };
 
@@ -1411,8 +1372,6 @@
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
     {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
-    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
-    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
     {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)}
 
 };
@@ -1461,8 +1420,6 @@
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
     {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
-    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
-    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
     {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)},
     {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)},
     {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)},
@@ -1515,9 +1472,6 @@
     {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
     {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
-    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
-    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
-    {CC"tryMonitorEnter",    CC"("OBJ")Z",               FN_PTR(Unsafe_TryMonitorEnter)},
     {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)},
     {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)},
     {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)},
@@ -1571,9 +1525,6 @@
 
     {CC"defineClass",        CC"("DC_Args")"CLS,         FN_PTR(Unsafe_DefineClass)},
     {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
-    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
-    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
-    {CC"tryMonitorEnter",    CC"("OBJ")Z",               FN_PTR(Unsafe_TryMonitorEnter)},
     {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)},
     {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)},
     {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)},
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -155,7 +155,7 @@
   if (mdo != NULL) {
     int i = mdo->invocation_count_delta();
     int b = mdo->backedge_count_delta();
-    return call_predicate_helper<CompLevel_full_profile>(i, b, 1);
+    return call_predicate_helper<CompLevel_full_profile>(i, b, 1, method);
   }
   return false;
 }
@@ -229,32 +229,32 @@
 // Tier?LoadFeedback is basically a coefficient that determines of
 // how many methods per compiler thread can be in the queue before
 // the threshold values double.
-bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
+bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
   case CompLevel_none:
   case CompLevel_limited_profile: {
     double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
-    return loop_predicate_helper<CompLevel_none>(i, b, k);
+    return loop_predicate_helper<CompLevel_none>(i, b, k, method);
   }
   case CompLevel_full_profile: {
     double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
-    return loop_predicate_helper<CompLevel_full_profile>(i, b, k);
+    return loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
   }
   default:
     return true;
   }
 }
 
-bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
+bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
   case CompLevel_none:
   case CompLevel_limited_profile: {
     double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
-    return call_predicate_helper<CompLevel_none>(i, b, k);
+    return call_predicate_helper<CompLevel_none>(i, b, k, method);
   }
   case CompLevel_full_profile: {
     double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
-    return call_predicate_helper<CompLevel_full_profile>(i, b, k);
+    return call_predicate_helper<CompLevel_full_profile>(i, b, k, method);
   }
   default:
     return true;
@@ -271,7 +271,7 @@
     int i = method->invocation_count();
     int b = method->backedge_count();
     double k = Tier0ProfilingStartPercentage / 100.0;
-    return call_predicate_helper<CompLevel_none>(i, b, k) || loop_predicate_helper<CompLevel_none>(i, b, k);
+    return call_predicate_helper<CompLevel_none>(i, b, k, method) || loop_predicate_helper<CompLevel_none>(i, b, k, method);
   }
   return false;
 }
@@ -348,7 +348,7 @@
       // If we were at full profile level, would we switch to full opt?
       if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
         next_level = CompLevel_full_optimization;
-      } else if ((this->*p)(i, b, cur_level)) {
+      } else if ((this->*p)(i, b, cur_level, method)) {
         // C1-generated fully profiled code is about 30% slower than the limited profile
         // code that has only invocation and backedge counters. The observation is that
         // if C2 queue is large enough we can spend too much time in the fully profiled code
@@ -374,7 +374,7 @@
           if (mdo->would_profile()) {
             if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
                                      Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
-                                     (this->*p)(i, b, cur_level))) {
+                                     (this->*p)(i, b, cur_level, method))) {
               next_level = CompLevel_full_profile;
             }
           } else {
@@ -390,7 +390,7 @@
           if (mdo->would_profile()) {
             int mdo_i = mdo->invocation_count_delta();
             int mdo_b = mdo->backedge_count_delta();
-            if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+            if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
               next_level = CompLevel_full_optimization;
             }
           } else {
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -84,7 +84,7 @@
  *   invocation and backedge notifications. Basically every n-th invocation or backedge a mutator thread
  *   makes a call into the runtime.
  *
- * - Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
+ * - Tier?InvocationThreshold, Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
  *   compilation thresholds.
  *   Level 2 thresholds are not used and are provided for option-compatibility and potential future use.
  *   Other thresholds work as follows:
@@ -100,7 +100,9 @@
  *   The same predicate is used to control the transition from level 3 to level 4 (C2). It should be
  *   noted though that the thresholds are relative. Moreover i and b for the 0->3 transition come
  *   from Method* and for 3->4 transition they come from MDO (since profiled invocations are
- *   counted separately).
+ *   counted separately). Finally, if a method does not contain anything worth profiling, a transition
+ *   from level 3 to level 4 occurs without considering thresholds (e.g., with fewer invocations than
+ *   what is specified by Tier4InvocationThreshold).
  *
  *   OSR transitions are controlled simply with b > TierXBackEdgeThreshold * s predicates.
  *
@@ -164,9 +166,9 @@
   // Call and loop predicates determine whether a transition to a higher compilation
   // level should be performed (pointers to predicate functions are passed to common().
   // Predicates also take compiler load into account.
-  typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
-  bool call_predicate(int i, int b, CompLevel cur_level);
-  bool loop_predicate(int i, int b, CompLevel cur_level);
+  typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
+  bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
+  bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
   // Common transition function. Given a predicate determines if a method should transition to another level.
   CompLevel common(Predicate p, Method* method, CompLevel cur_level, bool disable_feedback = false);
   // Transition functions.
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1126,16 +1126,35 @@
 }
 #endif
 
-// Returns threshold scaled with CompileThresholdScaling
-intx Arguments::get_scaled_compile_threshold(intx threshold) {
-  return (intx)(threshold * CompileThresholdScaling);
+intx Arguments::scaled_compile_threshold(intx threshold, double scale) {
+  if (scale == 1.0 || scale < 0.0) {
+    return threshold;
+  } else {
+    return (intx)(threshold * scale);
+  }
 }
 
 // Returns freq_log scaled with CompileThresholdScaling
-intx Arguments::get_scaled_freq_log(intx freq_log) {
-  intx scaled_freq = get_scaled_compile_threshold((intx)1 << freq_log);
-  if (scaled_freq == 0) {
-    return 0;
+intx Arguments::scaled_freq_log(intx freq_log, double scale) {
+  // Check if scaling is necessary or negative value was specified.
+  if (scale == 1.0 || scale < 0.0) {
+    return freq_log;
+  }
+
+  // Check value to avoid calculating log2 of 0.
+  if (scale == 0.0) {
+    return 1;
+  }
+
+  intx scaled_freq = scaled_compile_threshold((intx)1 << freq_log, scale);
+  // Determine the maximum notification frequency value currently supported.
+  // The largest mask value that the interpreter/C1 can handle is
+  // of length InvocationCounter::number_of_count_bits. Mask values are always
+  // one bit shorter then the value of the notification frequency. Set
+  // max_freq_bits accordingly.
+  intx max_freq_bits = InvocationCounter::number_of_count_bits + 1;
+  if (scaled_freq > nth_bit(max_freq_bits)) {
+    return max_freq_bits;
   } else {
     return log2_intptr(scaled_freq);
   }
@@ -1180,31 +1199,36 @@
     Tier3InvokeNotifyFreqLog = 0;
     Tier4InvocationThreshold = 0;
   }
+
+  if (CompileThresholdScaling < 0) {
+    vm_exit_during_initialization("Negative value specified for CompileThresholdScaling", NULL);
+  }
+
   // Scale tiered compilation thresholds
   if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
-    FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, get_scaled_freq_log(Tier0InvokeNotifyFreqLog));
-    FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, get_scaled_freq_log(Tier0BackedgeNotifyFreqLog));
-
-    FLAG_SET_ERGO(intx, Tier3InvocationThreshold, get_scaled_compile_threshold(Tier3InvocationThreshold));
-    FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, get_scaled_compile_threshold(Tier3MinInvocationThreshold));
-    FLAG_SET_ERGO(intx, Tier3CompileThreshold, get_scaled_compile_threshold(Tier3CompileThreshold));
-    FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, get_scaled_compile_threshold(Tier3BackEdgeThreshold));
+    FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, scaled_freq_log(Tier0InvokeNotifyFreqLog));
+    FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, scaled_freq_log(Tier0BackedgeNotifyFreqLog));
+
+    FLAG_SET_ERGO(intx, Tier3InvocationThreshold, scaled_compile_threshold(Tier3InvocationThreshold));
+    FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, scaled_compile_threshold(Tier3MinInvocationThreshold));
+    FLAG_SET_ERGO(intx, Tier3CompileThreshold, scaled_compile_threshold(Tier3CompileThreshold));
+    FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, scaled_compile_threshold(Tier3BackEdgeThreshold));
 
     // Tier2{Invocation,MinInvocation,Compile,Backedge}Threshold should be scaled here
     // once these thresholds become supported.
 
-    FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, get_scaled_freq_log(Tier2InvokeNotifyFreqLog));
-    FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, get_scaled_freq_log(Tier2BackedgeNotifyFreqLog));
-
-    FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, get_scaled_freq_log(Tier3InvokeNotifyFreqLog));
-    FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, get_scaled_freq_log(Tier3BackedgeNotifyFreqLog));
-
-    FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, get_scaled_freq_log(Tier23InlineeNotifyFreqLog));
-
-    FLAG_SET_ERGO(intx, Tier4InvocationThreshold, get_scaled_compile_threshold(Tier4InvocationThreshold));
-    FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, get_scaled_compile_threshold(Tier4MinInvocationThreshold));
-    FLAG_SET_ERGO(intx, Tier4CompileThreshold, get_scaled_compile_threshold(Tier4CompileThreshold));
-    FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, get_scaled_compile_threshold(Tier4BackEdgeThreshold));
+    FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, scaled_freq_log(Tier2InvokeNotifyFreqLog));
+    FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, scaled_freq_log(Tier2BackedgeNotifyFreqLog));
+
+    FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, scaled_freq_log(Tier3InvokeNotifyFreqLog));
+    FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, scaled_freq_log(Tier3BackedgeNotifyFreqLog));
+
+    FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, scaled_freq_log(Tier23InlineeNotifyFreqLog));
+
+    FLAG_SET_ERGO(intx, Tier4InvocationThreshold, scaled_compile_threshold(Tier4InvocationThreshold));
+    FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, scaled_compile_threshold(Tier4MinInvocationThreshold));
+    FLAG_SET_ERGO(intx, Tier4CompileThreshold, scaled_compile_threshold(Tier4CompileThreshold));
+    FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, scaled_compile_threshold(Tier4BackEdgeThreshold));
   }
 }
 
@@ -3456,7 +3480,7 @@
   }
 
   if ((TieredCompilation && CompileThresholdScaling == 0)
-      || (!TieredCompilation && get_scaled_compile_threshold(CompileThreshold) == 0)) {
+      || (!TieredCompilation && scaled_compile_threshold(CompileThreshold) == 0)) {
     set_mode_flags(_int);
   }
 
@@ -3896,7 +3920,7 @@
     }
     // Scale CompileThreshold
     if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
-      FLAG_SET_ERGO(intx, CompileThreshold, get_scaled_compile_threshold(CompileThreshold));
+      FLAG_SET_ERGO(intx, CompileThreshold, scaled_compile_threshold(CompileThreshold));
     }
   }
 
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -328,9 +328,6 @@
   static bool _ClipInlining;
   static bool _CIDynamicCompilePriority;
 
-  // Scale compile thresholds
-  static intx get_scaled_compile_threshold(intx threshold);
-  static intx get_scaled_freq_log(intx freq_log);
   // Tiered
   static void set_tiered_flags();
   static int  get_min_number_of_compiler_threads();
@@ -452,6 +449,18 @@
   static char*  SharedArchivePath;
 
  public:
+  // Scale compile thresholds
+  // Returns threshold scaled with CompileThresholdScaling
+  static intx scaled_compile_threshold(intx threshold, double scale);
+  static intx scaled_compile_threshold(intx threshold) {
+    return scaled_compile_threshold(threshold, CompileThresholdScaling);
+  }
+  // Returns freq_log scaled with CompileThresholdScaling
+  static intx scaled_freq_log(intx freq_log, double scale);
+  static intx scaled_freq_log(intx freq_log) {
+    return scaled_freq_log(freq_log, CompileThresholdScaling);
+  }
+
   // Parses the arguments, first phase
   static jint parse(const JavaVMInitArgs* args);
   // Apply ergonomics
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -2477,7 +2477,7 @@
           "Number of compiler threads to run")                              \
                                                                             \
   product(intx, CompilationPolicyChoice, 0,                                 \
-          "which compilation policy (0/1)")                                 \
+          "which compilation policy (0-3)")                                 \
                                                                             \
   develop(bool, UseStackBanging, true,                                      \
           "use stack banging for stack overflow checks (required for "      \
@@ -3528,7 +3528,16 @@
                                                                             \
   product(double, CompileThresholdScaling, 1.0,                             \
           "Factor to control when first compilation happens "               \
-          "(both with and without tiered compilation)")                     \
+          "(both with and without tiered compilation): "                    \
+          "values greater than 1.0 delay counter overflow, "                \
+          "values between 0 and 1.0 rush counter overflow, "                \
+          "value of 1.0 leave compilation thresholds unchanged "            \
+          "value of 0.0 is equivalent to -Xint. "                           \
+          ""                                                                \
+          "Flag can be set as per-method option. "                          \
+          "If a value is specified for a method, compilation thresholds "   \
+          "for that method are scaled by both the value of the global flag "\
+          "and the value of the per-method flag.")                          \
                                                                             \
   product(intx, Tier0InvokeNotifyFreqLog, 7,                                \
           "Interpreter (tier 0) invocation notification frequency")         \
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1401,15 +1401,17 @@
   return (sp > (stack_limit + reserved_area));
 }
 
-size_t os::page_size_for_region(size_t region_size, size_t min_pages) {
+size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) {
   assert(min_pages > 0, "sanity");
   if (UseLargePages) {
     const size_t max_page_size = region_size / min_pages;
 
     for (size_t i = 0; _page_sizes[i] != 0; ++i) {
       const size_t page_size = _page_sizes[i];
-      if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) {
-        return page_size;
+      if (page_size <= max_page_size) {
+        if (!must_be_aligned || is_size_aligned(region_size, page_size)) {
+          return page_size;
+        }
       }
     }
   }
@@ -1417,6 +1419,14 @@
   return vm_page_size();
 }
 
+size_t os::page_size_for_region_aligned(size_t region_size, size_t min_pages) {
+  return page_size_for_region(region_size, min_pages, true);
+}
+
+size_t os::page_size_for_region_unaligned(size_t region_size, size_t min_pages) {
+  return page_size_for_region(region_size, min_pages, false);
+}
+
 #ifndef PRODUCT
 void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count)
 {
@@ -1665,17 +1675,17 @@
 
   static size_t large_page_size() {
     const size_t large_page_size_example = 4 * M;
-    return os::page_size_for_region(large_page_size_example, 1);
+    return os::page_size_for_region_aligned(large_page_size_example, 1);
   }
 
-  static void test_page_size_for_region() {
+  static void test_page_size_for_region_aligned() {
     if (UseLargePages) {
       const size_t small_page = small_page_size();
       const size_t large_page = large_page_size();
 
       if (large_page > small_page) {
         size_t num_small_pages_in_large = large_page / small_page;
-        size_t page = os::page_size_for_region(large_page, num_small_pages_in_large);
+        size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large);
 
         assert_eq(page, small_page);
       }
@@ -1688,21 +1698,53 @@
       const size_t large_page = large_page_size();
       if (large_page > small_page) {
         const size_t unaligned_region = large_page + 17;
-        size_t page = os::page_size_for_region(unaligned_region, 1);
+        size_t page = os::page_size_for_region_aligned(unaligned_region, 1);
         assert_eq(page, small_page);
 
         const size_t num_pages = 5;
         const size_t aligned_region = large_page * num_pages;
-        page = os::page_size_for_region(aligned_region, num_pages);
+        page = os::page_size_for_region_aligned(aligned_region, num_pages);
         assert_eq(page, large_page);
       }
     }
   }
 
+  static void test_page_size_for_region_unaligned() {
+    if (UseLargePages) {
+      // Given exact page size, should return that page size.
+      for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
+        size_t expected = os::_page_sizes[i];
+        size_t actual = os::page_size_for_region_unaligned(expected, 1);
+        assert_eq(expected, actual);
+      }
+
+      // Given slightly larger size than a page size, return the page size.
+      for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
+        size_t expected = os::_page_sizes[i];
+        size_t actual = os::page_size_for_region_unaligned(expected + 17, 1);
+        assert_eq(expected, actual);
+      }
+
+      // Given a slightly smaller size than a page size,
+      // return the next smaller page size.
+      if (os::_page_sizes[1] > os::_page_sizes[0]) {
+        size_t expected = os::_page_sizes[0];
+        size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1);
+        assert_eq(actual, expected);
+      }
+
+      // Return small page size for values less than a small page.
+      size_t small_page = small_page_size();
+      size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1);
+      assert_eq(small_page, actual);
+    }
+  }
+
  public:
   static void run_tests() {
-    test_page_size_for_region();
+    test_page_size_for_region_aligned();
     test_page_size_for_region_alignment();
+    test_page_size_for_region_unaligned();
   }
 };
 
--- a/hotspot/src/share/vm/runtime/os.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -148,6 +148,7 @@
   static void   pd_free_memory(char *addr, size_t bytes, size_t alignment_hint);
   static void   pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint);
 
+  static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
 
  public:
   static void init(void);                      // Called before command line parsing
@@ -267,8 +268,13 @@
 
   // Returns the page size to use for a region of memory.
   // region_size / min_pages will always be greater than or equal to the
-  // returned value.
-  static size_t page_size_for_region(size_t region_size, size_t min_pages);
+  // returned value. The returned value will divide region_size.
+  static size_t page_size_for_region_aligned(size_t region_size, size_t min_pages);
+
+  // Returns the page size to use for a region of memory.
+  // region_size / min_pages will always be greater than or equal to the
+  // returned value. The returned value might not divide region_size.
+  static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages);
 
   // Return the largest page size that can be used
   static size_t max_page_size() {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -257,28 +257,28 @@
 // Call and loop predicates determine whether a transition to a higher
 // compilation level should be performed (pointers to predicate functions
 // are passed to common() transition function).
-bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
+bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
   case CompLevel_none:
   case CompLevel_limited_profile: {
-    return loop_predicate_helper<CompLevel_none>(i, b, 1.0);
+    return loop_predicate_helper<CompLevel_none>(i, b, 1.0, method);
   }
   case CompLevel_full_profile: {
-    return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
+    return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
   }
   default:
     return true;
   }
 }
 
-bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
+bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
   switch(cur_level) {
   case CompLevel_none:
   case CompLevel_limited_profile: {
-    return call_predicate_helper<CompLevel_none>(i, b, 1.0);
+    return call_predicate_helper<CompLevel_none>(i, b, 1.0, method);
   }
   case CompLevel_full_profile: {
-    return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
+    return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
   }
   default:
     return true;
@@ -293,8 +293,8 @@
     int i = mdo->invocation_count();
     int b = mdo->backedge_count();
     double k = ProfileMaturityPercentage / 100.0;
-    return call_predicate_helper<CompLevel_full_profile>(i, b, k) ||
-           loop_predicate_helper<CompLevel_full_profile>(i, b, k);
+    return call_predicate_helper<CompLevel_full_profile>(i, b, k, method) ||
+           loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
   }
   return false;
 }
@@ -313,7 +313,7 @@
       // If we were at full profile level, would we switch to full opt?
       if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) {
         next_level = CompLevel_full_optimization;
-      } else if ((this->*p)(i, b, cur_level)) {
+      } else if ((this->*p)(i, b, cur_level, method)) {
         next_level = CompLevel_full_profile;
       }
       break;
@@ -325,7 +325,7 @@
           if (mdo->would_profile()) {
             int mdo_i = mdo->invocation_count_delta();
             int mdo_b = mdo->backedge_count_delta();
-            if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+            if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
               next_level = CompLevel_full_optimization;
             }
           } else {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -43,9 +43,9 @@
   // Call and loop predicates determine whether a transition to a higher compilation
   // level should be performed (pointers to predicate functions are passed to common_TF().
   // Predicates also take compiler load into account.
-  typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
-  bool call_predicate(int i, int b, CompLevel cur_level);
-  bool loop_predicate(int i, int b, CompLevel cur_level);
+  typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
+  bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
+  bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
   // Common transition function. Given a predicate determines if a method should transition to another level.
   CompLevel common(Predicate p, Method* method, CompLevel cur_level);
   // Transition functions.
@@ -76,8 +76,8 @@
 
   // Predicate helpers are used by .*_predicate() methods as well as others.
   // They check the given counter values, multiplied by the scale against the thresholds.
-  template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale);
-  template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale);
+  template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale, Method* method);
+  template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale, Method* method);
 
   // Get a compilation level for a given method.
   static CompLevel comp_level(Method* method) {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -25,8 +25,14 @@
 #ifndef SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
 #define SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
 
+#include "compiler/compilerOracle.hpp"
+
 template<CompLevel level>
-bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale) {
+bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale, Method* method) {
+  double threshold_scaling;
+  if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
+    scale *= threshold_scaling;
+  }
   switch(level) {
   case CompLevel_none:
   case CompLevel_limited_profile:
@@ -40,7 +46,11 @@
 }
 
 template<CompLevel level>
-bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale) {
+bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale, Method* method) {
+  double threshold_scaling;
+  if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
+    scale *= threshold_scaling;
+  }
   switch(level) {
   case CompLevel_none:
   case CompLevel_limited_profile:
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -276,18 +276,6 @@
   THREAD->set_current_pending_monitor_is_from_java(true);
 }
 
-// NOTE: must use heavy weight monitor to handle jni monitor enter
-bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) {
-  if (UseBiasedLocking) {
-    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
-    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
-  }
-
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate_helper(obj());
-  return monitor->try_enter(THREAD);
-}
-
-
 // NOTE: must use heavy weight monitor to handle jni monitor exit
 void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
   TEVENT(jni_exit);
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -65,7 +65,6 @@
   // Used only to handle jni locks or other unmatched monitor enter/exit
   // Internally they will use heavy weight monitor.
   static void jni_enter(Handle obj, TRAPS);
-  static bool jni_try_enter(Handle obj, Thread* THREAD); // Implements Unsafe.tryMonitorEnter
   static void jni_exit(oop obj, Thread* THREAD);
 
   // Handle all interpreter, compiler and jni cases
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -38,7 +38,8 @@
 }
 
 ReservedSpace::ReservedSpace(size_t size) {
-  size_t page_size = os::page_size_for_region(size, 1);
+  // Want to use large pages where possible and pad with small pages.
+  size_t page_size = os::page_size_for_region_unaligned(size, 1);
   bool large_pages = page_size != (size_t)os::vm_page_size();
   // Don't force the alignment to be large page aligned,
   // since that will waste memory.
@@ -617,7 +618,7 @@
 
 
 bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
-  const size_t max_commit_granularity = os::page_size_for_region(rs.size(), 1);
+  const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1);
   return initialize_with_granularity(rs, committed_size, max_commit_granularity);
 }
 
@@ -1239,7 +1240,7 @@
     case Disable:
       return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
     case Commit:
-      return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), 1));
+      return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1));
     }
   }
 
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 20:17:15 2017 +0200
@@ -351,11 +351,18 @@
   nonstatic_field(MethodData,           _arg_stack,                                    intx)                                  \
   nonstatic_field(MethodData,           _arg_returned,                                 intx)                                  \
   nonstatic_field(MethodData,           _tenure_traps,                                 uint)                                  \
+  nonstatic_field(MethodData,           _invoke_mask,                                  int)                                   \
+  nonstatic_field(MethodData,           _backedge_mask,                                int)                                   \
   nonstatic_field(DataLayout,           _header._struct._tag,                          u1)                                    \
   nonstatic_field(DataLayout,           _header._struct._flags,                        u1)                                    \
   nonstatic_field(DataLayout,           _header._struct._bci,                          u2)                                    \
   nonstatic_field(DataLayout,           _cells[0],                                     intptr_t)                              \
   nonstatic_field(MethodCounters,       _nmethod_age,                                  int)                                   \
+  nonstatic_field(MethodCounters,       _interpreter_invocation_limit,                 int)                                   \
+  nonstatic_field(MethodCounters,       _interpreter_backward_branch_limit,            int)                                   \
+  nonstatic_field(MethodCounters,       _interpreter_profile_limit,                    int)                                   \
+  nonstatic_field(MethodCounters,       _invoke_mask,                                  int)                                   \
+  nonstatic_field(MethodCounters,       _backedge_mask,                                int)                                   \
   nonstatic_field(MethodCounters,       _interpreter_invocation_count,                 int)                                   \
   nonstatic_field(MethodCounters,       _interpreter_throwout_count,                   u2)                                    \
   nonstatic_field(MethodCounters,       _number_of_breakpoints,                        u2)                                    \
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp	Wed Jul 05 20:17:15 2017 +0200
@@ -1142,17 +1142,18 @@
   return ((x != NoLongBits) && (mask_long_bits(x, x - 1) == NoLongBits));
 }
 
-//* largest i such that 2^i <= x
-//  A negative value of 'x' will return '31'
+// Returns largest i such that 2^i <= x.
+// If x < 0, the function returns 31 on a 32-bit machine and 63 on a 64-bit machine.
+// If x == 0, the function returns -1.
 inline int log2_intptr(intptr_t x) {
   int i = -1;
-  uintptr_t p =  1;
+  uintptr_t p = 1;
   while (p != 0 && p <= (uintptr_t)x) {
     // p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x)
     i++; p *= 2;
   }
   // p = 2^(i+1) && x < p (i.e., 2^i <= x < 2^(i+1))
-  // (if p = 0 then overflow occurred and i = 31)
+  // If p = 0, overflow has occurred and i = 31 or i = 63 (depending on the machine word size).
   return i;
 }
 
--- a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java	Wed Jul 05 20:17:15 2017 +0200
@@ -54,7 +54,7 @@
     //
     // Tier0InvokeNotifyFreqLog, Tier0BackedgeNotifyFreqLog,
     // Tier3InvocationThreshold, Tier3MinInvocationThreshold,
-    // Tier3CompileThreshold, and Tier3BackEdgeThreshold,
+    // Tier3CompileThreshold, Tier3BackEdgeThreshold,
     // Tier2InvokeNotifyFreqLog, Tier2BackedgeNotifyFreqLog,
     // Tier3InvokeNotifyFreqLog, Tier3BackedgeNotifyFreqLog,
     // Tier23InlineeNotifyFreqLog, Tier4InvocationThreshold,
--- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -98,11 +98,13 @@
             return false;
         });
         for (BlobType bt : BlobType.getAvailable()) {
-            int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
-            Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
-                    expectedNotificationsAmount, String.format("Unexpected "
-                            + "amount of notifications for pool: %s",
-                            bt.getMemoryPool().getName()));
+            if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+                int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
+                Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
+                        expectedNotificationsAmount, String.format("Unexpected "
+                                + "amount of notifications for pool: %s",
+                                bt.getMemoryPool().getName()));
+            }
         }
         try {
             ((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
--- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -52,7 +52,9 @@
 
     public static void main(String[] args) {
         for (BlobType bt : BlobType.getAvailable()) {
-            new ThresholdNotificationsTest(bt).runTest();
+            if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+                new ThresholdNotificationsTest(bt).runTest();
+            }
         }
     }
 
--- a/hotspot/test/compiler/loopopts/7052494/Test7052494.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/compiler/loopopts/7052494/Test7052494.java	Wed Jul 05 20:17:15 2017 +0200
@@ -25,7 +25,6 @@
 /**
  * @test
  * @bug 7052494
- * @ignore 7154567
  * @summary Eclipse test fails on JDK 7 b142
  *
  * @run main/othervm -Xbatch Test7052494
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stringopts/TestOptimizeStringConcat.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 SAP AG.  All Rights Reserved.
+ * 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 8068909
+ * @key regression
+ * @summary test that string optimizations produce code, that doesn't lead to a crash.
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestOptimizeStringConcat
+ * @author axel.siebenborn@sap.com
+ */
+public class TestOptimizeStringConcat {
+
+    static boolean checkArgumentSyntax(String value, String allowedchars, String notallowedchars, String logmsg) {
+        String rc = null;
+
+        int maxchar = 99999;
+        int minchar = 1;
+        if ((allowedchars != null && notallowedchars != null) || minchar > maxchar) {
+            rc = "internal error";
+        } else {
+            if (value == null) {
+                rc = "the value null is not allowed, it is missing";
+            } else if (value != null && minchar > 0 && value.trim().equals("")) {
+                rc = "the value must not be empty";
+            } else if (value != null) {
+                if (value.length() < minchar || value.length() > maxchar) {
+                    if (rc == null) {
+                        rc = "the value length must be between +minchar+ and +maxchar";
+                    }
+                }
+                char[] _value = value.toCharArray();
+                boolean dotfound = false;
+                int i = 1;
+                if (_value[i] == '.' && !dotfound) {
+                    dotfound = true;
+                } else if (allowedchars != null && allowedchars.indexOf(_value[i]) == -1) {
+                    if (rc == null) {
+                        rc = "the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+                    } else {
+                        rc += " / the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+                    }
+                } else if (notallowedchars != null && notallowedchars.indexOf(_value[i]) != -1) {
+                    if (rc == null) {
+                        rc = "the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+                    } else {
+                        rc += " / the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+                    }
+                }
+            }
+        }
+
+        if (rc != null) {
+            System.out.println(logmsg + " ==> " + rc);
+            return false;
+        }
+        return true;
+    }
+
+    public static void main(String[] args) {
+        boolean failed = false;
+        for (int i = 0; i < 10000; i++) {
+            failed |= !checkArgumentSyntax("theName", null, "\"<&", "Error consistencyCheck: name in component definition");
+            failed |= !checkArgumentSyntax(null, null, "\"<&", "Error consistencyCheck: name in component definition");
+            failed |= !checkArgumentSyntax("42", "0123456789.", null, "Error consistencyCheck: counter in component definition");
+        }
+        System.out.println(failed);
+    }
+}
--- a/hotspot/test/compiler/testlibrary/rtm/BusyLock.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -24,9 +24,6 @@
 
 package rtm;
 
-import com.oracle.java.testlibrary.Utils;
-import sun.misc.Unsafe;
-
 import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.CyclicBarrier;
 
@@ -42,7 +39,6 @@
     // Following field have to be static in order to avoid escape analysis.
     @SuppressWarnings("UnsuedDeclaration")
     private static int field = 0;
-    private static final Unsafe UNSAFE = Utils.getUnsafe();
     protected final Object monitor;
     protected final int timeout;
 
@@ -59,18 +55,9 @@
     @Override
     public void run() {
         try {
-            // wait until forceAbort leave monitor
-            barrier.await();
-            if (UNSAFE.tryMonitorEnter(monitor)) {
-                try {
-                    barrier.await();
-                    Thread.sleep(timeout);
-                } finally {
-                    UNSAFE.monitorExit(monitor);
-                }
-            } else {
-                throw new RuntimeException("Monitor should be entered by " +
-                                           "::run() first.");
+            synchronized (monitor) {
+                barrier.await();
+                Thread.sleep(timeout);
             }
         } catch (InterruptedException | BrokenBarrierException e) {
             throw new RuntimeException("Synchronization error happened.", e);
@@ -79,7 +66,6 @@
 
     public void syncAndTest() {
         try {
-            barrier.await();
             // wait until monitor is locked by a ::run method
             barrier.await();
         } catch (InterruptedException | BrokenBarrierException e) {
--- a/hotspot/test/gc/TestNUMAPageSize.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/gc/TestNUMAPageSize.java	Wed Jul 05 20:17:15 2017 +0200
@@ -25,6 +25,7 @@
  * @test TestNUMAPageSize
  * @summary Make sure that start up with NUMA support does not cause problems.
  * @bug 8061467
+ * @requires (vm.opt.AggressiveOpts == null) | (vm.opt.AggressiveOpts == false)
  * @key gc
  * @key regression
  * @run main/othervm -Xmx8M -XX:+UseNUMA TestNUMAPageSize
--- a/hotspot/test/gc/TestSmallHeap.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/gc/TestSmallHeap.java	Wed Jul 05 20:17:15 2017 +0200
@@ -25,6 +25,7 @@
  * @test TestSmallHeap
  * @bug 8067438
  * @requires vm.gc=="null"
+ * @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false")
  * @summary Verify that starting the VM with a small heap works
  * @library /testlibrary /../../test/lib
  * @build TestSmallHeap
@@ -33,8 +34,9 @@
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseSerialGC TestSmallHeap
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseG1GC TestSmallHeap
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseConcMarkSweepGC TestSmallHeap
- *
- * Note: It would be nice to verify the minimal supported heap size (2m) here,
+ */
+
+/* Note: It would be nice to verify the minimal supported heap size (2m) here,
  * but we align the heap size based on the card table size. And the card table
  * size is aligned based on the minimal pages size provided by the os. This
  * means that on most platforms, where the minimal page size is 4k, we get a
--- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java	Wed Jul 05 20:17:15 2017 +0200
@@ -116,7 +116,14 @@
 
     ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
-    output.shouldHaveExitValue(0);
+    try {
+        output.shouldHaveExitValue(0);
+    } catch (RuntimeException e) {
+        // It's ok if there is no client vm in the jdk.
+        if (output.firstMatch("Unrecognized option: -client") == null) {
+            throw e;
+        }
+    }
 
     return output;
   }
--- a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -44,7 +44,7 @@
 
     public static void main(String[] args) throws Exception {
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-            "-Xmx64m", "-XX:-TransmitErrorReport", Crasher.class.getName());
+            "-Xmx64m", "-XX:-TransmitErrorReport", "-XX:-CreateMinidumpOnCrash", Crasher.class.getName());
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldNotMatch("error occurred during error reporting \\(printing problematic frame\\)");
     }
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -25,6 +25,7 @@
  * @test CompilerQueueTest
  * @bug 8054889
  * @library ..
+ * @ignore 8069160
  * @build DcmdUtil CompilerQueueTest
  * @run main CompilerQueueTest
  * @run main/othervm -XX:-TieredCompilation CompilerQueueTest
--- a/jdk/.hgtags	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/.hgtags	Wed Jul 05 20:17:15 2017 +0200
@@ -290,3 +290,4 @@
 9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 jdk9-b45
 efedac7f44ed41cea2b1038138047271f55aacba jdk9-b46
 b641c14730ac05d9ec8b4f66e6fca3dc21adb403 jdk9-b47
+ebb2eb7f1aec78eb6d8cc4c96f018afa11093cde jdk9-b48
--- a/jdk/make/Tools.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/Tools.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -34,28 +34,23 @@
 include NativeCompilation.gmk
 include SetupJavaCompilers.gmk
 
-# The exception handling of swing beaninfo which have the own tool directory
-ifeq (, $(BUILD_TOOLS_JDK))
-  $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
-      SETUP := GENERATE_OLDBYTECODE, \
-      ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
-      SRC := $(JDK_TOPDIR)/make/src/classes, \
-      BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
-      COPY := boot.modules ext.modules))
-endif
+################################################################################
+
+$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
+    SETUP := GENERATE_OLDBYTECODE, \
+    ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
+    SRC := $(JDK_TOPDIR)/make/src/classes, \
+    BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
+    COPY := boot.modules ext.modules))
 
-$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/%.template: \
-    $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/%.template
-	$(call install-file)
-
-BUILD_TOOLS_JDK += $(foreach i, $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template), $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/$(notdir $i))
+$(eval $(call SetupCopyFiles,COPY_NIMBUS_TEMPLATES, \
+    SRC := $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus, \
+    DEST := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources, \
+    FILES := $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template)))
 
-# Resource used by CheckDeps tool
-$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed: \
-    $(JDK_TOPDIR)/make/data/checkdeps/refs.allowed
-	$(call install-file)
+BUILD_TOOLS_JDK += $(COPY_NIMBUS_TEMPLATES)
 
-BUILD_TOOLS_JDK += $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed
+################################################################################
 
 # Add a checksum ("jsum") to the end of a text file. Prevents trivial tampering with class lists.
 TOOL_ADDJSUM = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
@@ -130,10 +125,6 @@
 TOOL_CLDRCONVERTER = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
     build.tools.cldrconverter.CLDRConverter
 
-TOOL_CHECKDEPS = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
-    -cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
-    build.tools.deps.CheckDeps
-
 TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
     -cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
     build.tools.module.GenJdepsModulesXml
@@ -161,25 +152,25 @@
 # Tools needed on solaris because OBJCOPY is broken.
 
 ifeq ($(OPENJDK_TARGET_OS), solaris)
-$(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
-    SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
-    LANG := C, \
-    CC := $(BUILD_CC), \
-    LDEXE := $(BUILD_LD), \
-    LDFLAGS := -lelf, \
-    OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
-    OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
-    PROGRAM := add_gnu_debuglink))
+  $(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
+      SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
+      LANG := C, \
+      CC := $(BUILD_CC), \
+      LDEXE := $(BUILD_LD), \
+      LDFLAGS := -lelf, \
+      OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
+      OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
+      PROGRAM := add_gnu_debuglink))
 
-$(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
-    SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
-    LANG := C, \
-    CC := $(BUILD_CC), \
-    LDEXE := $(BUILD_LD), \
-    LDFLAGS := -lelf, \
-    OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
-    OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
-    PROGRAM := fix_empty_sec_hdr_flags))
+  $(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
+      SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
+      LANG := C, \
+      CC := $(BUILD_CC), \
+      LDEXE := $(BUILD_LD), \
+      LDFLAGS := -lelf, \
+      OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
+      OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
+      PROGRAM := fix_empty_sec_hdr_flags))
 endif
 
 $(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE)
--- a/jdk/make/data/checkdeps/refs.allowed	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# This properties-formatted file contains the names of the non-existent types
-# that are allowed to be referenced from classes in a profiles image.
-#
-# The property key is a type that does not exist. The property value is one or
-# more types that reference the missing type. The property value also encodes
-# the names of the profiles where this reference is allowed.
-
-# jsse.jar is not subsetted by the profiles build. For compact1 and compact2
-# then this means that there are references to Kerberos types that do not
-# exist. These references are harmless.
-#
-javax.security.auth.kerberos.KerberosKey=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.KerberosPrincipal=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.KerberosTicket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-javax.security.auth.kerberos.KeyTab=sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.ServicePermission=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.GSSCaller=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.krb5.Krb5Util=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.krb5.ServiceCreds=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.EncryptedData= sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.EncryptionKey=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.crypto.KeyUsage=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.EncTicketPart=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.Krb5=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.Ticket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.KrbException=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.PrincipalName=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.Realm=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-
-# Residual references to java.beans.
-# The RemoveMethods tool does not yet purge the constant pool.
-#
-java.beans.PropertyChangeListener=java.util.logging.LogManager,compact1,compact2,compact3
--- a/jdk/make/gensrc/GensrcMisc.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/gensrc/GensrcMisc.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -28,6 +28,13 @@
 # string and the runtime name into the Version.java file.
 # To be printed by java -version
 
+# These dependencies should ideally be added to prerequesites for Version.java
+# but skip for now until we have better incremental build for java.
+#    $(call DependOnVariable, LAUNCHER_NAME) \
+#    $(call DependOnVariable, RELEASE) \
+#    $(call DependOnVariable, FULL_VERSION) \
+#    $(call DependOnVariable, RUNTIME_VERSION)
+
 $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java: \
     $(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template
 	$(MKDIR) -p $(@D)
--- a/jdk/make/lib/CoreLibraries.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -74,8 +74,6 @@
 
 ##########################################################################################
 
-BUILD_LIBVERIFY_SRC := check_code.c check_format.c
-
 ifeq ($(OPENJDK_TARGET_OS), solaris)
   ifneq ($(OPENJDK_TARGET_CPU), x86_64)
     BUILD_LIBVERIFY_REORDER := $(JDK_TOPDIR)/make/mapfiles/libverify/reorder-$(OPENJDK_TARGET_CPU)
@@ -116,10 +114,6 @@
 
 LIBJAVA_SRC_DIRS := $(call FindSrcDirsForLib, java.base, java)
 
-ifeq ($(OPENJDK_TARGET_OS), macosx)
-  LIBJAVA_EXCLUDE_FILES += $(JDK_TOPDIR)/src/java.base/unix/native/libjava/HostLocaleProviderAdapter_md.c
-endif
-
 LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \
     -I$(JDK_TOPDIR)/src/java.base/share/native/libfdlibm \
     -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
@@ -134,9 +128,7 @@
   LIBJAVA_CFLAGS += -DJDK_UPDATE_VERSION='"$(JDK_UPDATE_VERSION)"'
 endif
 
-ifneq ($(OPENJDK_TARGET_OS), macosx)
-  LIBJAVA_EXCLUDE_FILES += java_props_macosx.c
-else
+ifeq ($(OPENJDK_TARGET_OS), macosx)
   BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
   BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
 endif
@@ -151,8 +143,6 @@
     LIBRARY := java, \
     OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
     SRC := $(LIBJAVA_SRC_DIRS), \
-    EXCLUDES := fdlibm/src zip prefs, \
-    EXCLUDE_FILES := $(LIBJAVA_EXCLUDE_FILES), \
     LANG := C, \
     OPTIMIZATION := HIGH, \
     CFLAGS := $(CFLAGS_JDKLIB) \
@@ -247,19 +237,10 @@
 
 ##########################################################################################
 
-BUILD_LIBJLI_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libjli \
-    $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli
+LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli)
 
 LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
 
-BUILD_LIBJLI_FILES := \
-    java.c \
-    splashscreen_stubs.c \
-    parse_manifest.c \
-    version_comp.c \
-    wildcard.c \
-    jli_util.c
-
 ifeq ($(JVM_VARIANT_ZERO), true)
   ERGO_FAMILY := zero
 else
@@ -269,68 +250,55 @@
     ERGO_FAMILY := $(OPENJDK_TARGET_CPU_ARCH)
   endif
 endif
+LIBJLI_ALL_ERGO := $(wildcard $(addsuffix /ergo_*.c, $(LIBJLI_SRC_DIRS)))
+LIBJLI_EXCLUDE_ERGO := $(filter-out %/ergo_$(ERGO_FAMILY).c, $(LIBJLI_ALL_ERGO))
+# If all specialized ergo files are excluded, use generic ergo
+ifeq ($(LIBJLI_ALL_ERGO), $(LIBJLI_EXCLUDE_ERGO))
+  LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
+endif
+LIBJLI_EXCLUDE_FILES += $(notdir $(LIBJLI_EXCLUDE_ERGO))
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
-  BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/macosx/native/libjli
-  BUILD_LIBJLI_FILES += java_md_common.c java_md_macosx.c
+  LIBJLI_EXCLUDE_FILES += java_md_solinux.c ergo.c
 
   BUILD_LIBJLI_java_md_macosx.c_CFLAGS := -x objective-c
   BUILD_LIBJLI_STATIC_java_md_macosx.c_CFLAGS := -x objective-c
+
+  LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\"
 endif
 
 ifeq ($(OPENJDK_TARGET_OS), windows)
-  BUILD_LIBJLI_FILES += java_md.c \
-      cmdtoargs.c
   # Staticically link with c runtime on windows.
   LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
-else ifneq ($(OPENJDK_TARGET_OS), macosx)
-
-  BUILD_LIBJLI_FILES += java_md_common.c
-  BUILD_LIBJLI_FILES += java_md_solinux.c ergo.c
-
-  ERGO_ARCH_FILE = ergo_$(ERGO_FAMILY).c
-
-  # if the architecture specific ergo file exists then
-  # use it, else use the generic definitions from ergo.c
-  ifneq ($(wildcard $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli/$(ERGO_ARCH_FILE)), )
-    BUILD_LIBJLI_FILES += $(ERGO_ARCH_FILE)
-  else # !ERGO_ARCH_FILE
-    LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
-  endif # ERGO_ARCH_FILE
-endif #WINDOWS
-
-LIBJLI_CFLAGS += $(foreach dir, $(BUILD_LIBJLI_SRC_DIRS), -I$(dir))
-
-# Append defines depending on target platform
-LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
-
-ifeq ($(OPENJDK_TARGET_OS), macosx)
-  LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\"
-endif
-
-ifneq ($(USE_EXTERNAL_LIBZ), true)
-  BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8
-  LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
-  BUILD_LIBJLI_FILES += \
-      inflate.c \
-      inftrees.c \
-      inffast.c \
-      zadler32.c \
-      zcrc32.c \
-      zutil.c
-endif
-
-ifeq ($(OPENJDK_TARGET_OS), windows)
   LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)
 else
   LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli
 endif
 
+LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS))
+
+# Append defines depending on target platform
+LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
+
+ifneq ($(USE_EXTERNAL_LIBZ), true)
+  LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
+  LIBJLI_EXTRA_FILES += \
+      $(addprefix $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8/, \
+          inflate.c \
+          inftrees.c \
+          inffast.c \
+          zadler32.c \
+          zcrc32.c \
+          zutil.c \
+      )
+endif
+
 $(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
     LIBRARY := jli, \
     OUTPUT_DIR := $(LIBJLI_OUTPUT_DIR), \
-    SRC := $(BUILD_LIBJLI_SRC_DIRS), \
-    INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+    SRC := $(LIBJLI_SRC_DIRS), \
+    EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+    EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
     LANG := C, \
     OPTIMIZATION := HIGH, \
     CFLAGS := $(LIBJLI_CFLAGS), \
@@ -376,8 +344,9 @@
   $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
       STATIC_LIBRARY := jli_static, \
       OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
-      SRC := $(BUILD_LIBJLI_SRC_DIRS), \
-      INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+      SRC := $(LIBJLI_SRC_DIRS), \
+      EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+      EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
       LANG := C, \
       OPTIMIZATION := HIGH, \
       CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
@@ -395,8 +364,9 @@
   $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
       LIBRARY := jli_static, \
       OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
-      SRC := $(BUILD_LIBJLI_SRC_DIRS), \
-      INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+      SRC := $(LIBJLI_SRC_DIRS), \
+      EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+      EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
       LANG := C, \
       OPTIMIZATION := HIGH, \
       CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \
@@ -411,16 +381,17 @@
 
 else ifeq ($(OPENJDK_TARGET_OS), aix)
   # AIX also requires a static libjli because the compiler doesn't support '-rpath'
-  $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC,\
-      STATIC_LIBRARY:=jli_static,\
-      OUTPUT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE),\
-      SRC:=$(BUILD_LIBJLI_SRC_DIRS),\
-      INCLUDE_FILES:=$(BUILD_LIBJLI_FILES),\
-      LANG:=C,\
-      OPTIMIZATION:=HIGH, \
-      CFLAGS:=$(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS),\
-      ARFLAGS:=$(ARFLAGS),\
-      OBJECT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
+  $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
+      STATIC_LIBRARY := jli_static, \
+      OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
+      SRC := $(LIBJLI_SRC_DIRS), \
+      EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+      EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
+      LANG := C, \
+      OPTIMIZATION := HIGH, \
+      CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
+      ARFLAGS := $(ARFLAGS), \
+      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
 
   TARGETS += $(BUILD_LIBJLI_STATIC)
 
--- a/jdk/make/lib/Lib-jdk.attach.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/lib/Lib-jdk.attach.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -31,7 +31,7 @@
 $(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
     LIBRARY := attach, \
     OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-    SRC := $(JDK_TOPDIR)/src/jdk.attach/$(OPENJDK_TARGET_OS)/native/libattach, \
+    SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \
     LANG := C, \
     OPTIMIZATION := LOW, \
     CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
--- a/jdk/make/lib/Lib-jdk.security.auth.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/lib/Lib-jdk.security.auth.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -28,9 +28,7 @@
 ################################################################################
 
 LIBJAAS_MAPFILE :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
-  LIBJAAS_EXCLUDE_FILES := Solaris.c
-else
+ifeq ($(OPENJDK_TARGET_OS), solaris)
   # only on solaris...wonder why
   LIBJAAS_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjaas/mapfile-vers
 endif
@@ -43,7 +41,7 @@
 $(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
     LIBRARY := $(LIBJAAS_NAME), \
     OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-    SRC := $(JDK_TOPDIR)/src/jdk.security.auth/$(OPENJDK_TARGET_OS_TYPE)/native/libjaas, \
+    SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \
     LANG := C, \
     OPTIMIZATION := LOW, \
     CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \
@@ -53,7 +51,6 @@
     LDFLAGS_windows := netapi32.lib user32.lib mpr.lib advapi32.lib, \
     LDFLAGS_SUFFIX_windows := $(LDFLAGS_JDKLIB_SUFFIX), \
     LDFLAGS_SUFFIX_solaris := -lc, \
-    EXCLUDE_FILES := $(LIBJAAS_EXCLUDE_FILES), \
     VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
     RC_FLAGS := $(RC_FLAGS) \
         -D "JDK_FNAME=$(LIBJAAS_NAME).dll" \
--- a/jdk/make/lib/NetworkingLibraries.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/lib/NetworkingLibraries.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -23,39 +23,16 @@
 # questions.
 #
 
-LIBNET_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libnet \
-    $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnet
-LIBNET_CFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
-    $(LIBJAVA_HEADER_FLAGS)
-
-LIBNET_CFLAGS += $(foreach dir, $(LIBNET_SRC_DIRS), -I$(dir))
-
-LIBNET_EXCLUDE_FILES :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
-  LIBNET_EXCLUDE_FILES += solaris_close.c
-endif
-
-ifneq ($(OPENJDK_TARGET_OS), linux)
-  LIBNET_EXCLUDE_FILES += linux_close.c
-endif
-
-ifneq ($(OPENJDK_TARGET_OS), macosx)
-  LIBNET_EXCLUDE_FILES += bsd_close.c
-endif
-
-ifeq ($(OPENJDK_TARGET_OS), aix)
-  LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnet/java/net/
-endif
+LIBNET_SRC_DIRS := $(call FindSrcDirsForLib, java.base, net)
 
 $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
     LIBRARY := net, \
     OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
     SRC := $(LIBNET_SRC_DIRS), \
-    EXCLUDE_FILES := $(LIBNET_EXCLUDE_FILES), \
     LANG := C, \
     OPTIMIZATION := LOW, \
-    CFLAGS := $(CFLAGS_JDKLIB) \
-        $(LIBNET_CFLAGS), \
+    CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+        $(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \
     MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnet/mapfile-vers, \
     LDFLAGS := $(LDFLAGS_JDKLIB) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/jdk/make/lib/NioLibraries.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/lib/NioLibraries.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -65,7 +65,6 @@
     OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
     SRC := $(BUILD_LIBNIO_SRC), \
     EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \
-    EXCLUDES := sctp, \
     LANG := C, \
     OPTIMIZATION := HIGH, \
     CFLAGS := $(CFLAGS_JDKLIB) \
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 20:17:15 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
@@ -214,10 +214,10 @@
 		Java_java_lang_Throwable_fillInStackTrace;
                 Java_java_lang_Throwable_getStackTraceDepth;
                 Java_java_lang_Throwable_getStackTraceElement;
-		Java_java_lang_UNIXProcess_init;
-		Java_java_lang_UNIXProcess_waitForProcessExit;
-		Java_java_lang_UNIXProcess_forkAndExec;
-		Java_java_lang_UNIXProcess_destroyProcess;
+		Java_java_lang_ProcessImpl_init;
+		Java_java_lang_ProcessImpl_waitForProcessExit;
+		Java_java_lang_ProcessImpl_forkAndExec;
+		Java_java_lang_ProcessImpl_destroyProcess;
                 Java_java_nio_Bits_copyFromShortArray;
                 Java_java_nio_Bits_copyToShortArray;
                 Java_java_nio_Bits_copyFromIntArray;
--- a/jdk/make/src/classes/build/tools/deps/CheckDeps.java	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-package build.tools.deps;
-
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.charset.StandardCharsets;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.classfile.Dependencies;
-import com.sun.tools.classfile.Dependency;
-
-/**
- * A simple tool to check the JAR files in a JRE image to ensure that there
- * aren't any references to types that do not exist. The tool is intended to
- * be used in the JDK "profiles" build to help ensure that the profile
- * definitions are kept up to date.
- */
-
-public class CheckDeps {
-
-    // classfile API for finding dependencies
-    static final Dependency.Finder finder = Dependencies.getClassDependencyFinder();
-
-    // "known types", found in rt.jar or other JAR files
-    static final Set<String> knownTypes = new HashSet<>();
-
-    // References to unknown types. The map key is the unknown type, the
-    // map value is the set of classes that reference it.
-    static final Map<String,Set<String>> unknownRefs = new HashMap<>();
-
-    // The property name is the name of an unknown type that is allowed to be
-    // references. The property value is a comma separated list of the types
-    // that are allowed to reference it. The list also includes the names of
-    // the profiles that the reference is allowed.
-    static final Properties allowedBadRefs = new Properties();
-
-    /**
-     * Returns the class name for the given class file. In the case of inner
-     * classes then the enclosing class is returned in order to keep the
-     * rules simple.
-     */
-    static String toClassName(String s) {
-        int i = s.indexOf('$');
-        if (i > 0)
-            s = s.substring(0, i);
-        return s.replace("/", ".");
-    }
-
-    /**
-     * Analyze the dependencies of all classes in the given JAR file. The
-     * method updates knownTypes and unknownRefs as part of the analysis.
-     */
-    static void analyzeDependencies(Path jarpath) throws Exception {
-        System.out.format("Analyzing %s%n", jarpath);
-        try (JarFile jf = new JarFile(jarpath.toFile())) {
-            Enumeration<JarEntry> entries = jf.entries();
-            while (entries.hasMoreElements()) {
-                JarEntry e = entries.nextElement();
-                String name = e.getName();
-                if (name.endsWith(".class")) {
-                    ClassFile cf = ClassFile.read(jf.getInputStream(e));
-                    for (Dependency d : finder.findDependencies(cf)) {
-                        String origin = toClassName(d.getOrigin().getName());
-                        String target = toClassName(d.getTarget().getName());
-
-                        // origin is now known
-                        unknownRefs.remove(origin);
-                        knownTypes.add(origin);
-
-                        // if the target is not known then record the reference
-                        if (!knownTypes.contains(target)) {
-                            Set<String> refs = unknownRefs.get(target);
-                            if (refs == null) {
-                                // first time seeing this unknown type
-                                refs = new HashSet<>();
-                                unknownRefs.put(target, refs);
-                            }
-                            refs.add(origin);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * We have closure (no references to types that do not exist) if
-     * unknownRefs is empty. When unknownRefs is not empty then it should
-     * only contain references that are allowed to be present (these are
-     * loaded from the refs.allowed properties file).
-     *
-     * @param the profile that is being tested, this determines the exceptions
-     *   in {@code allowedBadRefs} that apply.
-     *
-     * @return {@code true} if there are no missing types or the only references
-     *   to missing types are described by {@code allowedBadRefs}.
-     */
-    static boolean checkClosure(String profile) {
-        // process the references to types that do not exist.
-        boolean fail = false;
-        for (Map.Entry<String,Set<String>> entry: unknownRefs.entrySet()) {
-            String target = entry.getKey();
-            for (String origin: entry.getValue()) {
-                // check if origin -> target allowed
-                String value = allowedBadRefs.getProperty(target);
-                if (value == null) {
-                    System.err.format("%s -> %s (unknown type)%n", origin, target);
-                    fail = true;
-                } else {
-                    // target is known, check if the origin is one that we
-                    // expect and that the exception applies to the profile.
-                    boolean found = false;
-                    boolean applicable = false;
-                    for (String s: value.split(",")) {
-                        s = s.trim();
-                        if (s.equals(origin))
-                            found = true;
-                        if (s.equals(profile))
-                            applicable = true;
-                    }
-                    if (!found || !applicable) {
-                        if (!found) {
-                            System.err.format("%s -> %s (not allowed)%n", origin, target);
-                        } else {
-                            System.err.format("%s -> %s (reference not applicable to %s)%n",
-                                origin, target, profile);
-                        }
-                        fail = true;
-                    }
-                }
-
-            }
-        }
-
-        return !fail;
-    }
-
-    static void fail(URL url) throws Exception {
-        System.err.println("One or more unexpected references encountered");
-        if (url != null)
-            System.err.format("Check %s is up to date%n", Paths.get(url.toURI()));
-        System.exit(-1);
-    }
-
-    public static void main(String[] args) throws Exception {
-        // load properties file so that we know what missing types that are
-        // allowed to be referenced.
-        URL url = CheckDeps.class.getResource("refs.allowed");
-        if (url != null) {
-            try (InputStream in = url.openStream()) {
-                allowedBadRefs.load(new InputStreamReader(in, StandardCharsets.UTF_8));
-            }
-        }
-
-        if (args.length != 2) {
-            System.err.println("Usage: java CheckDeps <image> <profile>");
-            System.exit(-1);
-        }
-
-        String image = args[0];
-        String profile = args[1];
-
-        // process JAR files on boot class path
-        Path lib = Paths.get(image, "lib");
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(lib, "*.jar")) {
-            for (Path jarpath: stream) {
-                analyzeDependencies(jarpath);
-            }
-        }
-
-        // classes on boot class path should not reference other types
-        boolean okay = checkClosure(profile);
-        if (!okay)
-            fail(url);
-
-        // process JAR files in the extensions directory
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(lib.resolve("ext"), "*.jar")) {
-            for (Path jarpath: stream) {
-                analyzeDependencies(jarpath);
-            }
-        }
-
-        // re-check to ensure that the extensions doesn't reference types that
-        // do not exist.
-        okay = checkClosure(profile);
-        if (!okay)
-            fail(url);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/aix/native/libnet/aix_close.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2001, 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.
+ */
+
+/*
+ * This file contains implementations of NET_... functions. The NET_.. functions are
+ * wrappers for common file- and socket functions plus provisions for non-blocking IO.
+ *
+ * (basically, the layers remember all  file descriptors waiting for a particular fd;
+ *  all threads waiting on a certain fd can be woken up by sending them a signal; this
+ *  is done e.g. when the fd is closed.)
+ *
+ * This was originally copied from the linux_close.c implementation.
+ *
+ * Side Note: This coding needs initialization. Under Linux this is done
+ * automatically via __attribute((constructor)), on AIX this is done manually
+ * (see aix_close_init).
+ *
+ */
+
+/*
+   AIX needs a workaround for I/O cancellation, see:
+   http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
+   ...
+   The close subroutine is blocked until all subroutines which use the file
+   descriptor return to usr space. For example, when a thread is calling close
+   and another thread is calling select with the same file descriptor, the
+   close subroutine does not return until the select call returns.
+   ...
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+    pthread_t thr;                      /* this thread */
+    struct threadEntry *next;           /* next thread */
+    int intr;                           /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+    pthread_mutex_t lock;               /* fd lock */
+    threadEntry_t *threads;             /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = (SIGRTMAX - 1);
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable = NULL;
+static int fdCount = 0;
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ *
+ * On AIX we don't have __attribute((constructor)) so we need to initialize
+ * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c')
+ */
+void aix_close_init() {
+    struct rlimit nbr_files;
+    sigset_t sigset;
+    struct sigaction sa;
+
+    /* Check already initialized */
+    if (fdCount > 0 && fdTable != NULL) {
+        return;
+    }
+
+    /*
+     * Allocate table based on the maximum number of
+     * file descriptors.
+     */
+    if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
+        fprintf(stderr, "library initialization failed - "
+                "unable to get max # of allocated fds\n");
+        abort();
+    }
+    fdCount = nbr_files.rlim_max;
+    /*
+     * We have a conceptual problem here, when the number of files is
+     * unlimited. As a kind of workaround, we ensure the table is big
+     * enough for handle even a large number of files. Since SAP itself
+     * recommends a limit of 32000 files, we just use 64000 as 'infinity'.
+     */
+    if (nbr_files.rlim_max == RLIM_INFINITY) {
+        fdCount = 64000;
+    }
+    fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+    if (fdTable == NULL) {
+        fprintf(stderr, "library initialization failed - "
+                "unable to allocate file descriptor table - out of memory");
+        abort();
+    }
+
+    {
+        int i;
+        for (i=0; i < fdCount; i++) {
+            pthread_mutex_init(&fdTable[i].lock, NULL);
+        }
+    }
+
+    /*
+     * Setup the signal handler
+     */
+    sa.sa_handler = sig_wakeup;
+    sa.sa_flags   = 0;
+    sigemptyset(&sa.sa_mask);
+    sigaction(sigWakeup, &sa, NULL);
+
+    sigemptyset(&sigset);
+    sigaddset(&sigset, sigWakeup);
+    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+    if (fd < 0 || fd >= fdCount) {
+        return NULL;
+    }
+    return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ *    Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+    self->thr = pthread_self();
+    self->intr = 0;
+
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        self->next = fdEntry->threads;
+        fdEntry->threads = self;
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ *     Remove thread from thread list for the fd
+ *     If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+    (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+    int orig_errno = errno;
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        threadEntry_t *curr, *prev=NULL;
+        curr = fdEntry->threads;
+        while (curr != NULL) {
+            if (curr == self) {
+                if (curr->intr) {
+                    orig_errno = EBADF;
+                }
+                if (prev == NULL) {
+                    fdEntry->threads = curr->next;
+                } else {
+                    prev->next = curr->next;
+                }
+                break;
+            }
+            prev = curr;
+            curr = curr->next;
+        }
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ *      fd1 < 0    => close(fd2)
+ *      fd1 >= 0   => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+    int rv, orig_errno;
+    fdEntry_t *fdEntry = getFdEntry(fd2);
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /*
+     * Lock the fd to hold-off additional I/O on this fd.
+     */
+    pthread_mutex_lock(&(fdEntry->lock));
+
+    {
+        /* On fast machines we see that we enter dup2 before the
+         * accepting thread had a chance to get and process the signal.
+         * So in case we woke a thread up, give it some time to cope.
+         * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */
+        int num_woken = 0;
+
+        /*
+         * Send a wakeup signal to all threads blocked on this
+         * file descriptor.
+         */
+        threadEntry_t *curr = fdEntry->threads;
+        while (curr != NULL) {
+            curr->intr = 1;
+            pthread_kill( curr->thr, sigWakeup );
+            num_woken ++;
+            curr = curr->next;
+        }
+
+        if (num_woken > 0) {
+          usleep(num_woken * 50);
+        }
+
+        /*
+         * And close/dup the file descriptor
+         * (restart if interrupted by signal)
+         */
+        do {
+            if (fd1 < 0) {
+                rv = close(fd2);
+            } else {
+                rv = dup2(fd1, fd2);
+            }
+        } while (rv == -1 && errno == EINTR);
+    }
+
+    /*
+     * Unlock without destroying errno
+     */
+    orig_errno = errno;
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+
+    return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+    if (fd < 0) {
+        errno = EBADF;
+        return -1;
+    }
+    return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+    return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
+    int ret;                                    \
+    threadEntry_t self;                         \
+    fdEntry_t *fdEntry = getFdEntry(FD);        \
+    if (fdEntry == NULL) {                      \
+        errno = EBADF;                          \
+        return -1;                              \
+    }                                           \
+    do {                                        \
+        startOp(fdEntry, &self);                \
+        ret = FUNC;                             \
+        endOp(fdEntry, &self);                  \
+    } while (ret == -1 && errno == EINTR);      \
+    return ret;                                 \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+    BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+       struct sockaddr *from, int *fromlen) {
+    socklen_t socklen = *fromlen;
+    BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
+    *fromlen = socklen;
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+    BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len,  unsigned  int
+       flags, const struct sockaddr *to, int tolen) {
+    BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
+    socklen_t socklen = *addrlen;
+    BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
+    *addrlen = socklen;
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+    int crc = -1, prc = -1;
+    threadEntry_t self;
+    fdEntry_t* fdEntry = getFdEntry(s);
+
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /* On AIX, when the system call connect() is interrupted, the connection
+     * is not aborted and it will be established asynchronously by the kernel.
+     * Hence, no need to restart connect() when EINTR is received
+     */
+    startOp(fdEntry, &self);
+    crc = connect(s, addr, addrlen);
+    endOp(fdEntry, &self);
+
+    if (crc == -1 && errno == EINTR) {
+        struct pollfd s_pollfd;
+        int sockopt_arg = 0;
+        socklen_t len;
+
+        s_pollfd.fd = s;
+        s_pollfd.events = POLLOUT | POLLERR;
+
+        /* poll the file descriptor */
+        do {
+            startOp(fdEntry, &self);
+            prc = poll(&s_pollfd, 1, -1);
+            endOp(fdEntry, &self);
+        } while (prc == -1  && errno == EINTR);
+
+        if (prc < 0)
+            return prc;
+
+        len = sizeof(sockopt_arg);
+
+        /* Check whether the connection has been established */
+        if (getsockopt(s, SOL_SOCKET, SO_ERROR, &sockopt_arg, &len) == -1)
+            return -1;
+
+        if (sockopt_arg != 0 ) {
+            errno = sockopt_arg;
+            return -1;
+        }
+    } else {
+        return crc;
+    }
+
+    /* At this point, fd is connected. Set successful return code */
+    return 0;
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+    BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+
+/*
+ * Wrapper for poll(s, timeout).
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+    long prevtime = 0, newtime;
+    struct timeval t;
+    fdEntry_t *fdEntry = getFdEntry(s);
+
+    /*
+     * Check that fd hasn't been closed.
+     */
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /*
+     * Pick up current time as may need to adjust timeout
+     */
+    if (timeout > 0) {
+        gettimeofday(&t, NULL);
+        prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
+    }
+
+    for(;;) {
+        struct pollfd pfd;
+        int rv;
+        threadEntry_t self;
+
+        /*
+         * Poll the fd. If interrupted by our wakeup signal
+         * errno will be set to EBADF.
+         */
+        pfd.fd = s;
+        pfd.events = POLLIN | POLLERR;
+
+        startOp(fdEntry, &self);
+        rv = poll(&pfd, 1, timeout);
+        endOp(fdEntry, &self);
+
+        /*
+         * If interrupted then adjust timeout. If timeout
+         * has expired return 0 (indicating timeout expired).
+         */
+        if (rv < 0 && errno == EINTR) {
+            if (timeout > 0) {
+                gettimeofday(&t, NULL);
+                newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
+                timeout -= newtime - prevtime;
+                if (timeout <= 0) {
+                    return 0;
+                }
+                prevtime = newtime;
+            }
+        } else {
+            return rv;
+        }
+
+    }
+}
--- a/jdk/src/java.base/aix/native/libnet/java/net/aix_close.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- */
-
-/*
- * This file contains implementations of NET_... functions. The NET_.. functions are
- * wrappers for common file- and socket functions plus provisions for non-blocking IO.
- *
- * (basically, the layers remember all  file descriptors waiting for a particular fd;
- *  all threads waiting on a certain fd can be woken up by sending them a signal; this
- *  is done e.g. when the fd is closed.)
- *
- * This was originally copied from the linux_close.c implementation.
- *
- * Side Note: This coding needs initialization. Under Linux this is done
- * automatically via __attribute((constructor)), on AIX this is done manually
- * (see aix_close_init).
- *
- */
-
-/*
-   AIX needs a workaround for I/O cancellation, see:
-   http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
-   ...
-   The close subroutine is blocked until all subroutines which use the file
-   descriptor return to usr space. For example, when a thread is calling close
-   and another thread is calling select with the same file descriptor, the
-   close subroutine does not return until the select call returns.
-   ...
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-/*
- * Stack allocated by thread when doing blocking operation
- */
-typedef struct threadEntry {
-    pthread_t thr;                      /* this thread */
-    struct threadEntry *next;           /* next thread */
-    int intr;                           /* interrupted */
-} threadEntry_t;
-
-/*
- * Heap allocated during initialized - one entry per fd
- */
-typedef struct {
-    pthread_mutex_t lock;               /* fd lock */
-    threadEntry_t *threads;             /* threads blocked on fd */
-} fdEntry_t;
-
-/*
- * Signal to unblock thread
- */
-static int sigWakeup = (SIGRTMAX - 1);
-
-/*
- * The fd table and the number of file descriptors
- */
-static fdEntry_t *fdTable = NULL;
-static int fdCount = 0;
-
-/*
- * Null signal handler
- */
-static void sig_wakeup(int sig) {
-}
-
-/*
- * Initialization routine (executed when library is loaded)
- * Allocate fd tables and sets up signal handler.
- *
- * On AIX we don't have __attribute((constructor)) so we need to initialize
- * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c')
- */
-void aix_close_init() {
-    struct rlimit nbr_files;
-    sigset_t sigset;
-    struct sigaction sa;
-
-    /* Check already initialized */
-    if (fdCount > 0 && fdTable != NULL) {
-        return;
-    }
-
-    /*
-     * Allocate table based on the maximum number of
-     * file descriptors.
-     */
-    if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
-        fprintf(stderr, "library initialization failed - "
-                "unable to get max # of allocated fds\n");
-        abort();
-    }
-    fdCount = nbr_files.rlim_max;
-    /*
-     * We have a conceptual problem here, when the number of files is
-     * unlimited. As a kind of workaround, we ensure the table is big
-     * enough for handle even a large number of files. Since SAP itself
-     * recommends a limit of 32000 files, we just use 64000 as 'infinity'.
-     */
-    if (nbr_files.rlim_max == RLIM_INFINITY) {
-        fdCount = 64000;
-    }
-    fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
-    if (fdTable == NULL) {
-        fprintf(stderr, "library initialization failed - "
-                "unable to allocate file descriptor table - out of memory");
-        abort();
-    }
-
-    {
-        int i;
-        for (i=0; i < fdCount; i++) {
-            pthread_mutex_init(&fdTable[i].lock, NULL);
-        }
-    }
-
-    /*
-     * Setup the signal handler
-     */
-    sa.sa_handler = sig_wakeup;
-    sa.sa_flags   = 0;
-    sigemptyset(&sa.sa_mask);
-    sigaction(sigWakeup, &sa, NULL);
-
-    sigemptyset(&sigset);
-    sigaddset(&sigset, sigWakeup);
-    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-}
-
-/*
- * Return the fd table for this fd or NULL is fd out
- * of range.
- */
-static inline fdEntry_t *getFdEntry(int fd)
-{
-    if (fd < 0 || fd >= fdCount) {
-        return NULL;
-    }
-    return &fdTable[fd];
-}
-
-/*
- * Start a blocking operation :-
- *    Insert thread onto thread list for the fd.
- */
-static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
-{
-    self->thr = pthread_self();
-    self->intr = 0;
-
-    pthread_mutex_lock(&(fdEntry->lock));
-    {
-        self->next = fdEntry->threads;
-        fdEntry->threads = self;
-    }
-    pthread_mutex_unlock(&(fdEntry->lock));
-}
-
-/*
- * End a blocking operation :-
- *     Remove thread from thread list for the fd
- *     If fd has been interrupted then set errno to EBADF
- */
-static inline void endOp
-    (fdEntry_t *fdEntry, threadEntry_t *self)
-{
-    int orig_errno = errno;
-    pthread_mutex_lock(&(fdEntry->lock));
-    {
-        threadEntry_t *curr, *prev=NULL;
-        curr = fdEntry->threads;
-        while (curr != NULL) {
-            if (curr == self) {
-                if (curr->intr) {
-                    orig_errno = EBADF;
-                }
-                if (prev == NULL) {
-                    fdEntry->threads = curr->next;
-                } else {
-                    prev->next = curr->next;
-                }
-                break;
-            }
-            prev = curr;
-            curr = curr->next;
-        }
-    }
-    pthread_mutex_unlock(&(fdEntry->lock));
-    errno = orig_errno;
-}
-
-/*
- * Close or dup2 a file descriptor ensuring that all threads blocked on
- * the file descriptor are notified via a wakeup signal.
- *
- *      fd1 < 0    => close(fd2)
- *      fd1 >= 0   => dup2(fd1, fd2)
- *
- * Returns -1 with errno set if operation fails.
- */
-static int closefd(int fd1, int fd2) {
-    int rv, orig_errno;
-    fdEntry_t *fdEntry = getFdEntry(fd2);
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /*
-     * Lock the fd to hold-off additional I/O on this fd.
-     */
-    pthread_mutex_lock(&(fdEntry->lock));
-
-    {
-        /* On fast machines we see that we enter dup2 before the
-         * accepting thread had a chance to get and process the signal.
-         * So in case we woke a thread up, give it some time to cope.
-         * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */
-        int num_woken = 0;
-
-        /*
-         * Send a wakeup signal to all threads blocked on this
-         * file descriptor.
-         */
-        threadEntry_t *curr = fdEntry->threads;
-        while (curr != NULL) {
-            curr->intr = 1;
-            pthread_kill( curr->thr, sigWakeup );
-            num_woken ++;
-            curr = curr->next;
-        }
-
-        if (num_woken > 0) {
-          usleep(num_woken * 50);
-        }
-
-        /*
-         * And close/dup the file descriptor
-         * (restart if interrupted by signal)
-         */
-        do {
-            if (fd1 < 0) {
-                rv = close(fd2);
-            } else {
-                rv = dup2(fd1, fd2);
-            }
-        } while (rv == -1 && errno == EINTR);
-    }
-
-    /*
-     * Unlock without destroying errno
-     */
-    orig_errno = errno;
-    pthread_mutex_unlock(&(fdEntry->lock));
-    errno = orig_errno;
-
-    return rv;
-}
-
-/*
- * Wrapper for dup2 - same semantics as dup2 system call except
- * that any threads blocked in an I/O system call on fd2 will be
- * preempted and return -1/EBADF;
- */
-int NET_Dup2(int fd, int fd2) {
-    if (fd < 0) {
-        errno = EBADF;
-        return -1;
-    }
-    return closefd(fd, fd2);
-}
-
-/*
- * Wrapper for close - same semantics as close system call
- * except that any threads blocked in an I/O on fd will be
- * preempted and the I/O system call will return -1/EBADF.
- */
-int NET_SocketClose(int fd) {
-    return closefd(-1, fd);
-}
-
-/************** Basic I/O operations here ***************/
-
-/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
- */
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
-    int ret;                                    \
-    threadEntry_t self;                         \
-    fdEntry_t *fdEntry = getFdEntry(FD);        \
-    if (fdEntry == NULL) {                      \
-        errno = EBADF;                          \
-        return -1;                              \
-    }                                           \
-    do {                                        \
-        startOp(fdEntry, &self);                \
-        ret = FUNC;                             \
-        endOp(fdEntry, &self);                  \
-    } while (ret == -1 && errno == EINTR);      \
-    return ret;                                 \
-}
-
-int NET_Read(int s, void* buf, size_t len) {
-    BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
-    BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
-       struct sockaddr *from, int *fromlen) {
-    socklen_t socklen = *fromlen;
-    BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
-    *fromlen = socklen;
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
-    BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
-    BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
-}
-
-int NET_SendTo(int s, const void *msg, int len,  unsigned  int
-       flags, const struct sockaddr *to, int tolen) {
-    BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
-}
-
-int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
-    socklen_t socklen = *addrlen;
-    BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
-    *addrlen = socklen;
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
-    int crc = -1, prc = -1;
-    threadEntry_t self;
-    fdEntry_t* fdEntry = getFdEntry(s);
-
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /* On AIX, when the system call connect() is interrupted, the connection
-     * is not aborted and it will be established asynchronously by the kernel.
-     * Hence, no need to restart connect() when EINTR is received
-     */
-    startOp(fdEntry, &self);
-    crc = connect(s, addr, addrlen);
-    endOp(fdEntry, &self);
-
-    if (crc == -1 && errno == EINTR) {
-        struct pollfd s_pollfd;
-        int sockopt_arg = 0;
-        socklen_t len;
-
-        s_pollfd.fd = s;
-        s_pollfd.events = POLLOUT | POLLERR;
-
-        /* poll the file descriptor */
-        do {
-            startOp(fdEntry, &self);
-            prc = poll(&s_pollfd, 1, -1);
-            endOp(fdEntry, &self);
-        } while (prc == -1  && errno == EINTR);
-
-        if (prc < 0)
-            return prc;
-
-        len = sizeof(sockopt_arg);
-
-        /* Check whether the connection has been established */
-        if (getsockopt(s, SOL_SOCKET, SO_ERROR, &sockopt_arg, &len) == -1)
-            return -1;
-
-        if (sockopt_arg != 0 ) {
-            errno = sockopt_arg;
-            return -1;
-        }
-    } else {
-        return crc;
-    }
-
-    /* At this point, fd is connected. Set successful return code */
-    return 0;
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
-    BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
-}
-
-/*
- * Wrapper for poll(s, timeout).
- * Auto restarts with adjusted timeout if interrupted by
- * signal other than our wakeup signal.
- */
-int NET_Timeout(int s, long timeout) {
-    long prevtime = 0, newtime;
-    struct timeval t;
-    fdEntry_t *fdEntry = getFdEntry(s);
-
-    /*
-     * Check that fd hasn't been closed.
-     */
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /*
-     * Pick up current time as may need to adjust timeout
-     */
-    if (timeout > 0) {
-        gettimeofday(&t, NULL);
-        prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
-    }
-
-    for(;;) {
-        struct pollfd pfd;
-        int rv;
-        threadEntry_t self;
-
-        /*
-         * Poll the fd. If interrupted by our wakeup signal
-         * errno will be set to EBADF.
-         */
-        pfd.fd = s;
-        pfd.events = POLLIN | POLLERR;
-
-        startOp(fdEntry, &self);
-        rv = poll(&pfd, 1, timeout);
-        endOp(fdEntry, &self);
-
-        /*
-         * If interrupted then adjust timeout. If timeout
-         * has expired return 0 (indicating timeout expired).
-         */
-        if (rv < 0 && errno == EINTR) {
-            if (timeout > 0) {
-                gettimeofday(&t, NULL);
-                newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
-                timeout -= newtime - prevtime;
-                if (timeout <= 0) {
-                    return 0;
-                }
-                prevtime = newtime;
-            }
-        } else {
-            return rv;
-        }
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/linux/native/libnet/linux_close.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2001, 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+    pthread_t thr;                      /* this thread */
+    struct threadEntry *next;           /* next thread */
+    int intr;                           /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+    pthread_mutex_t lock;               /* fd lock */
+    threadEntry_t *threads;             /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = (__SIGRTMAX - 2);
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable;
+static int fdCount;
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ */
+static void __attribute((constructor)) init() {
+    struct rlimit nbr_files;
+    sigset_t sigset;
+    struct sigaction sa;
+
+    /*
+     * Allocate table based on the maximum number of
+     * file descriptors.
+     */
+    getrlimit(RLIMIT_NOFILE, &nbr_files);
+    fdCount = nbr_files.rlim_max;
+    fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+    if (fdTable == NULL) {
+        fprintf(stderr, "library initialization failed - "
+                "unable to allocate file descriptor table - out of memory");
+        abort();
+    }
+
+    /*
+     * Setup the signal handler
+     */
+    sa.sa_handler = sig_wakeup;
+    sa.sa_flags   = 0;
+    sigemptyset(&sa.sa_mask);
+    sigaction(sigWakeup, &sa, NULL);
+
+    sigemptyset(&sigset);
+    sigaddset(&sigset, sigWakeup);
+    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+    if (fd < 0 || fd >= fdCount) {
+        return NULL;
+    }
+    return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ *    Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+    self->thr = pthread_self();
+    self->intr = 0;
+
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        self->next = fdEntry->threads;
+        fdEntry->threads = self;
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ *     Remove thread from thread list for the fd
+ *     If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+    (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+    int orig_errno = errno;
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        threadEntry_t *curr, *prev=NULL;
+        curr = fdEntry->threads;
+        while (curr != NULL) {
+            if (curr == self) {
+                if (curr->intr) {
+                    orig_errno = EBADF;
+                }
+                if (prev == NULL) {
+                    fdEntry->threads = curr->next;
+                } else {
+                    prev->next = curr->next;
+                }
+                break;
+            }
+            prev = curr;
+            curr = curr->next;
+        }
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ *      fd1 < 0    => close(fd2)
+ *      fd1 >= 0   => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+    int rv, orig_errno;
+    fdEntry_t *fdEntry = getFdEntry(fd2);
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /*
+     * Lock the fd to hold-off additional I/O on this fd.
+     */
+    pthread_mutex_lock(&(fdEntry->lock));
+
+    {
+        /*
+         * And close/dup the file descriptor
+         * (restart if interrupted by signal)
+         */
+        do {
+            if (fd1 < 0) {
+                rv = close(fd2);
+            } else {
+                rv = dup2(fd1, fd2);
+            }
+        } while (rv == -1 && errno == EINTR);
+
+        /*
+         * Send a wakeup signal to all threads blocked on this
+         * file descriptor.
+         */
+        threadEntry_t *curr = fdEntry->threads;
+        while (curr != NULL) {
+            curr->intr = 1;
+            pthread_kill( curr->thr, sigWakeup );
+            curr = curr->next;
+        }
+    }
+
+    /*
+     * Unlock without destroying errno
+     */
+    orig_errno = errno;
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+
+    return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+    if (fd < 0) {
+        errno = EBADF;
+        return -1;
+    }
+    return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+    return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
+    int ret;                                    \
+    threadEntry_t self;                         \
+    fdEntry_t *fdEntry = getFdEntry(FD);        \
+    if (fdEntry == NULL) {                      \
+        errno = EBADF;                          \
+        return -1;                              \
+    }                                           \
+    do {                                        \
+        startOp(fdEntry, &self);                \
+        ret = FUNC;                             \
+        endOp(fdEntry, &self);                  \
+    } while (ret == -1 && errno == EINTR);      \
+    return ret;                                 \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+    BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+       struct sockaddr *from, socklen_t *fromlen) {
+    BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+    BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len,  unsigned  int
+       flags, const struct sockaddr *to, int tolen) {
+    BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+    BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+    BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+
+/*
+ * Wrapper for poll(s, timeout).
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+    long prevtime = 0, newtime;
+    struct timeval t;
+    fdEntry_t *fdEntry = getFdEntry(s);
+
+    /*
+     * Check that fd hasn't been closed.
+     */
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /*
+     * Pick up current time as may need to adjust timeout
+     */
+    if (timeout > 0) {
+        gettimeofday(&t, NULL);
+        prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
+    }
+
+    for(;;) {
+        struct pollfd pfd;
+        int rv;
+        threadEntry_t self;
+
+        /*
+         * Poll the fd. If interrupted by our wakeup signal
+         * errno will be set to EBADF.
+         */
+        pfd.fd = s;
+        pfd.events = POLLIN | POLLERR;
+
+        startOp(fdEntry, &self);
+        rv = poll(&pfd, 1, timeout);
+        endOp(fdEntry, &self);
+
+        /*
+         * If interrupted then adjust timeout. If timeout
+         * has expired return 0 (indicating timeout expired).
+         */
+        if (rv < 0 && errno == EINTR) {
+            if (timeout > 0) {
+                gettimeofday(&t, NULL);
+                newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
+                timeout -= newtime - prevtime;
+                if (timeout <= 0) {
+                    return 0;
+                }
+                prevtime = newtime;
+            }
+        } else {
+            return rv;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 1998, 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.
+ */
+
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <Security/AuthSession.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <Foundation/Foundation.h>
+
+#include "java_props_macosx.h"
+
+
+// need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded
+static void *getJRSFramework() {
+    static void *jrsFwk = NULL;
+    if (jrsFwk == NULL) {
+       jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
+    }
+    return jrsFwk;
+}
+
+char *getPosixLocale(int cat) {
+    char *lc = setlocale(cat, NULL);
+    if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
+        lc = getenv("LANG");
+    }
+    if (lc == NULL) return NULL;
+    return strdup(lc);
+}
+
+#define LOCALEIDLENGTH  128
+char *getMacOSXLocale(int cat) {
+    switch (cat) {
+    case LC_MESSAGES:
+        {
+            void *jrsFwk = getJRSFramework();
+            if (jrsFwk == NULL) return NULL;
+
+            char *(*JRSCopyPrimaryLanguage)() = dlsym(jrsFwk, "JRSCopyPrimaryLanguage");
+            char *primaryLanguage = JRSCopyPrimaryLanguage ? JRSCopyPrimaryLanguage() : NULL;
+            if (primaryLanguage == NULL) return NULL;
+
+            char *(*JRSCopyCanonicalLanguageForPrimaryLanguage)(char *) = dlsym(jrsFwk, "JRSCopyCanonicalLanguageForPrimaryLanguage");
+            char *canonicalLanguage = JRSCopyCanonicalLanguageForPrimaryLanguage ?  JRSCopyCanonicalLanguageForPrimaryLanguage(primaryLanguage) : NULL;
+            free (primaryLanguage);
+
+            return canonicalLanguage;
+        }
+        break;
+    default:
+        {
+            char localeString[LOCALEIDLENGTH];
+            if (CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
+                                   localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
+                return strdup(localeString);
+            }
+        }
+        break;
+    }
+
+    return NULL;
+}
+
+char *setupMacOSXLocale(int cat) {
+    char * ret = getMacOSXLocale(cat);
+
+    if (cat == LC_MESSAGES && ret != NULL) {
+        void *jrsFwk = getJRSFramework();
+        if (jrsFwk != NULL) {
+            void (*JRSSetDefaultLocalization)(char *) = dlsym(jrsFwk, "JRSSetDefaultLocalization");
+            if (JRSSetDefaultLocalization) JRSSetDefaultLocalization(ret);
+        }
+    }
+
+    if (ret == NULL) {
+        return getPosixLocale(cat);
+    } else {
+        return ret;
+    }
+}
+
+int isInAquaSession() {
+    // environment variable to bypass the aqua session check
+    char *ev = getenv("AWT_FORCE_HEADFUL");
+    if (ev && (strncasecmp(ev, "true", 4) == 0)) {
+        // if "true" then tell the caller we're in an Aqua session without actually checking
+        return 1;
+    }
+    // Is the WindowServer available?
+    SecuritySessionId session_id;
+    SessionAttributeBits session_info;
+    OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);
+    if (status == noErr) {
+        if (session_info & sessionHasGraphicAccess) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+void setOSNameAndVersion(java_props_t *sprops) {
+    /* Don't rely on JRSCopyOSName because there's no guarantee the value will
+     * remain the same, or even if the JRS functions will continue to be part of
+     * Mac OS X.  So hardcode os_name, and fill in os_version if we can.
+     */
+    sprops->os_name = strdup("Mac OS X");
+
+    void *jrsFwk = getJRSFramework();
+    if (jrsFwk != NULL) {
+        char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion");
+        if (copyOSVersion != NULL) {
+            sprops->os_version = copyOSVersion();
+            return;
+        }
+    }
+    sprops->os_version = strdup("Unknown");
+}
+
+
+static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey, CFStringRef inHostKey, CFStringRef inPortKey, CFStringRef *outProxyHost, int *ioProxyPort) {
+    /* See if the proxy is enabled. */
+    CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);
+    if (cf_enabled == NULL) {
+        return false;
+    }
+
+    int isEnabled = false;
+    if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {
+        return isEnabled;
+    }
+
+    if (!isEnabled) return false;
+    *outProxyHost = CFDictionaryGetValue(inDict, inHostKey);
+
+    // If cf_host is null, that means the checkbox is set,
+    //   but no host was entered. We'll treat that as NOT ENABLED.
+    // If cf_port is null or cf_port isn't a number, that means
+    //   no port number was entered. Treat this as ENABLED with the
+    //   protocol's default port.
+    if (*outProxyHost == NULL) {
+        return false;
+    }
+
+    if (CFStringGetLength(*outProxyHost) == 0) {
+        return false;
+    }
+
+    int newPort = 0;
+    CFNumberRef cf_port = NULL;
+    if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&
+        CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&
+        newPort > 0) {
+        *ioProxyPort = newPort;
+    } else {
+        // bad port or no port - leave *ioProxyPort unchanged
+    }
+
+    return true;
+}
+
+static char *createUTF8CString(const CFStringRef theString) {
+    if (theString == NULL) return NULL;
+
+    const CFIndex stringLength = CFStringGetLength(theString);
+    const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;
+    char *returnVal = (char *)malloc(bufSize);
+
+    if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {
+        return returnVal;
+    }
+
+    free(returnVal);
+    return NULL;
+}
+
+// Return TRUE if str is a syntactically valid IP address.
+// Using inet_pton() instead of inet_aton() for IPv6 support.
+// len is only a hint; cstr must still be nul-terminated
+static int looksLikeIPAddress(char *cstr, size_t len) {
+    if (len == 0  ||  (len == 1 && cstr[0] == '.')) return FALSE;
+
+    char dst[16]; // big enough for INET6
+    return (1 == inet_pton(AF_INET, cstr, dst)  ||
+            1 == inet_pton(AF_INET6, cstr, dst));
+}
+
+
+
+// Convert Mac OS X proxy exception entry to Java syntax.
+// See Radar #3441134 for details.
+// Returns NULL if this exception should be ignored by Java.
+// May generate a string with multiple exceptions separated by '|'.
+static char * createConvertedException(CFStringRef cf_original) {
+    // This is done with char* instead of CFString because inet_pton()
+    // needs a C string.
+    char *c_exception = createUTF8CString(cf_original);
+    if (!c_exception) return NULL;
+
+    int c_len = strlen(c_exception);
+
+    // 1. sanitize exception prefix
+    if (c_len >= 1  &&  0 == strncmp(c_exception, ".", 1)) {
+        memmove(c_exception, c_exception+1, c_len);
+        c_len -= 1;
+    } else if (c_len >= 2  &&  0 == strncmp(c_exception, "*.", 2)) {
+        memmove(c_exception, c_exception+2, c_len-1);
+        c_len -= 2;
+    }
+
+    // 2. pre-reject other exception wildcards
+    if (strchr(c_exception, '*')) {
+        free(c_exception);
+        return NULL;
+    }
+
+    // 3. no IP wildcarding
+    if (looksLikeIPAddress(c_exception, c_len)) {
+        return c_exception;
+    }
+
+    // 4. allow domain suffixes
+    // c_exception is now "str\0" - change to "str|*.str\0"
+    c_exception = reallocf(c_exception, c_len+3+c_len+1);
+    if (!c_exception) return NULL;
+
+    strncpy(c_exception+c_len, "|*.", 3);
+    strncpy(c_exception+c_len+3, c_exception, c_len);
+    c_exception[c_len+3+c_len] = '\0';
+    return c_exception;
+}
+
+/*
+ * Method for fetching the user.home path and storing it in the property list.
+ * For signed .apps running in the Mac App Sandbox, user.home is set to the
+ * app's sandbox container.
+ */
+void setUserHome(java_props_t *sprops) {
+    if (sprops == NULL) { return; }
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());
+    [pool drain];
+}
+
+/*
+ * Method for fetching proxy info and storing it in the property list.
+ */
+void setProxyProperties(java_props_t *sProps) {
+    if (sProps == NULL) return;
+
+    char buf[16];    /* Used for %d of an int - 16 is plenty */
+    CFStringRef
+    cf_httpHost = NULL,
+    cf_httpsHost = NULL,
+    cf_ftpHost = NULL,
+    cf_socksHost = NULL,
+    cf_gopherHost = NULL;
+    int
+    httpPort = 80, // Default proxy port values
+    httpsPort = 443,
+    ftpPort = 21,
+    socksPort = 1080,
+    gopherPort = 70;
+
+    CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
+    if (dict == NULL) return;
+
+    /* Read the proxy exceptions list */
+    CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);
+
+    CFMutableStringRef cf_exceptionList = NULL;
+    if (cf_list != NULL) {
+        CFIndex len = CFArrayGetCount(cf_list), idx;
+
+        cf_exceptionList = CFStringCreateMutable(NULL, 0);
+        for (idx = (CFIndex)0; idx < len; idx++) {
+            CFStringRef cf_ehost;
+            if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {
+                /* Convert this exception from Mac OS X syntax to Java syntax.
+                 See Radar #3441134 for details. This may generate a string
+                 with multiple Java exceptions separated by '|'. */
+                char *c_exception = createConvertedException(cf_ehost);
+                if (c_exception) {
+                    /* Append the host to the list of exclusions. */
+                    if (CFStringGetLength(cf_exceptionList) > 0) {
+                        CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);
+                    }
+                    CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);
+                    free(c_exception);
+                }
+            }
+        }
+    }
+
+    if (cf_exceptionList != NULL) {
+        if (CFStringGetLength(cf_exceptionList) > 0) {
+            sProps->exceptionList = createUTF8CString(cf_exceptionList);
+        }
+        CFRelease(cf_exceptionList);
+    }
+
+#define CHECK_PROXY(protocol, PROTOCOL)                                     \
+    sProps->protocol##ProxyEnabled =                                        \
+    getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable,      \
+    kSCPropNetProxies##PROTOCOL##Proxy,         \
+    kSCPropNetProxies##PROTOCOL##Port,          \
+    &cf_##protocol##Host, &protocol##Port);     \
+    if (sProps->protocol##ProxyEnabled) {                                   \
+        sProps->protocol##Host = createUTF8CString(cf_##protocol##Host);    \
+        snprintf(buf, sizeof(buf), "%d", protocol##Port);                   \
+        sProps->protocol##Port = malloc(strlen(buf) + 1);                   \
+        strcpy(sProps->protocol##Port, buf);                                \
+    }
+
+    CHECK_PROXY(http, HTTP);
+    CHECK_PROXY(https, HTTPS);
+    CHECK_PROXY(ftp, FTP);
+    CHECK_PROXY(socks, SOCKS);
+    CHECK_PROXY(gopher, Gopher);
+
+#undef CHECK_PROXY
+
+    CFRelease(dict);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.h	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1998, 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.
+ */
+
+#include "java_props.h"
+
+char *setupMacOSXLocale(int cat);
+void setOSNameAndVersion(java_props_t *sprops);
+void setUserHome(java_props_t *sprops);
+void setProxyProperties(java_props_t *sProps);
+int isInAquaSession();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libnet/bsd_close.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2001, 2012, 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+    pthread_t thr;                      /* this thread */
+    struct threadEntry *next;           /* next thread */
+    int intr;                           /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+    pthread_mutex_t lock;               /* fd lock */
+    threadEntry_t *threads;             /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = SIGIO;
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable;
+static int fdCount;
+
+/*
+ * This limit applies if getlimit() returns unlimited.
+ * Unfortunately, this means if someone wants a higher limit
+ * then they have to set an explicit limit, higher than this,
+ * which is probably counter-intuitive.
+ */
+#define MAX_FD_COUNT 4096
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ */
+static void __attribute((constructor)) init() {
+    struct rlimit nbr_files;
+    sigset_t sigset;
+    struct sigaction sa;
+    int i;
+
+    /*
+     * Allocate table based on the maximum number of
+     * file descriptors.
+     */
+    getrlimit(RLIMIT_NOFILE, &nbr_files);
+    if (nbr_files.rlim_max == RLIM_INFINITY) {
+        fdCount = MAX_FD_COUNT;
+    } else {
+        fdCount = nbr_files.rlim_max;
+    }
+    fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+    if (fdTable == NULL) {
+        fprintf(stderr, "library initialization failed - "
+                "unable to allocate file descriptor table - out of memory");
+        abort();
+    }
+    for (i=0; i<fdCount; i++) {
+        pthread_mutex_init(&fdTable[i].lock, NULL);
+    }
+
+    /*
+     * Setup the signal handler
+     */
+    sa.sa_handler = sig_wakeup;
+    sa.sa_flags   = 0;
+    sigemptyset(&sa.sa_mask);
+    sigaction(sigWakeup, &sa, NULL);
+
+    sigemptyset(&sigset);
+    sigaddset(&sigset, sigWakeup);
+    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+    if (fd < 0 || fd >= fdCount) {
+        return NULL;
+    }
+    return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ *    Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+    self->thr = pthread_self();
+    self->intr = 0;
+
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        self->next = fdEntry->threads;
+        fdEntry->threads = self;
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ *     Remove thread from thread list for the fd
+ *     If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+    (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+    int orig_errno = errno;
+    pthread_mutex_lock(&(fdEntry->lock));
+    {
+        threadEntry_t *curr, *prev=NULL;
+        curr = fdEntry->threads;
+        while (curr != NULL) {
+            if (curr == self) {
+                if (curr->intr) {
+                    orig_errno = EBADF;
+                }
+                if (prev == NULL) {
+                    fdEntry->threads = curr->next;
+                } else {
+                    prev->next = curr->next;
+                }
+                break;
+            }
+            prev = curr;
+            curr = curr->next;
+        }
+    }
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ *      fd1 < 0    => close(fd2)
+ *      fd1 >= 0   => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+    int rv, orig_errno;
+    fdEntry_t *fdEntry = getFdEntry(fd2);
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /*
+     * Lock the fd to hold-off additional I/O on this fd.
+     */
+    pthread_mutex_lock(&(fdEntry->lock));
+
+    {
+        /*
+         * Send a wakeup signal to all threads blocked on this
+         * file descriptor.
+         */
+        threadEntry_t *curr = fdEntry->threads;
+        while (curr != NULL) {
+            curr->intr = 1;
+            pthread_kill( curr->thr, sigWakeup );
+            curr = curr->next;
+        }
+
+        /*
+         * And close/dup the file descriptor
+         * (restart if interrupted by signal)
+         */
+        do {
+            if (fd1 < 0) {
+                rv = close(fd2);
+            } else {
+                rv = dup2(fd1, fd2);
+            }
+        } while (rv == -1 && errno == EINTR);
+
+    }
+
+    /*
+     * Unlock without destroying errno
+     */
+    orig_errno = errno;
+    pthread_mutex_unlock(&(fdEntry->lock));
+    errno = orig_errno;
+
+    return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+    if (fd < 0) {
+        errno = EBADF;
+        return -1;
+    }
+    return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+    return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
+    int ret;                                    \
+    threadEntry_t self;                         \
+    fdEntry_t *fdEntry = getFdEntry(FD);        \
+    if (fdEntry == NULL) {                      \
+        errno = EBADF;                          \
+        return -1;                              \
+    }                                           \
+    do {                                        \
+        startOp(fdEntry, &self);                \
+        ret = FUNC;                             \
+        endOp(fdEntry, &self);                  \
+    } while (ret == -1 && errno == EINTR);      \
+    return ret;                                 \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+    BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+       struct sockaddr *from, socklen_t *fromlen) {
+    BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+    BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+    BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len,  unsigned  int
+       flags, const struct sockaddr *to, int tolen) {
+    BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+    BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+    BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+
+/*
+ * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+    long prevtime = 0, newtime;
+    struct timeval t, *tp = &t;
+    fd_set fds;
+    fd_set* fdsp = NULL;
+    int allocated = 0;
+    threadEntry_t self;
+    fdEntry_t *fdEntry = getFdEntry(s);
+
+    /*
+     * Check that fd hasn't been closed.
+     */
+    if (fdEntry == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    /*
+     * Pick up current time as may need to adjust timeout
+     */
+    if (timeout > 0) {
+        /* Timed */
+        struct timeval now;
+        gettimeofday(&now, NULL);
+        prevtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
+        t.tv_sec = timeout / 1000;
+        t.tv_usec = (timeout % 1000) * 1000;
+    } else if (timeout < 0) {
+        /* Blocking */
+        tp = 0;
+    } else {
+        /* Poll */
+        t.tv_sec = 0;
+        t.tv_usec = 0;
+    }
+
+    if (s < FD_SETSIZE) {
+        fdsp = &fds;
+        FD_ZERO(fdsp);
+    } else {
+        int length = (howmany(s+1, NFDBITS)) * sizeof(int);
+        fdsp = (fd_set *) calloc(1, length);
+        if (fdsp == NULL) {
+            return -1;   // errno will be set to ENOMEM
+        }
+        allocated = 1;
+    }
+    FD_SET(s, fdsp);
+
+    for(;;) {
+        int rv;
+
+        /*
+         * call select on the fd. If interrupted by our wakeup signal
+         * errno will be set to EBADF.
+         */
+
+        startOp(fdEntry, &self);
+        rv = select(s+1, fdsp, 0, 0, tp);
+        endOp(fdEntry, &self);
+
+        /*
+         * If interrupted then adjust timeout. If timeout
+         * has expired return 0 (indicating timeout expired).
+         */
+        if (rv < 0 && errno == EINTR) {
+            if (timeout > 0) {
+                struct timeval now;
+                gettimeofday(&now, NULL);
+                newtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
+                timeout -= newtime - prevtime;
+                if (timeout <= 0) {
+                    if (allocated != 0)
+                        free(fdsp);
+                    return 0;
+                }
+                prevtime = newtime;
+                t.tv_sec = timeout / 1000;
+                t.tv_usec = (timeout % 1000) * 1000;
+            }
+        } else {
+            if (allocated != 0)
+                free(fdsp);
+            return rv;
+        }
+
+    }
+}
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -27,6 +27,9 @@
 
 import sun.misc.FloatingDecimal;
 import java.util.Arrays;
+import java.util.Spliterator;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
 
 /**
  * A mutable sequence of characters.
@@ -292,7 +295,7 @@
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
+        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
     }
 
     /**
@@ -1432,6 +1435,34 @@
     public abstract String toString();
 
     /**
+     * {@inheritDoc}
+     * @since 1.9
+     */
+    @Override
+    public IntStream chars() {
+        // Reuse String-based spliterator. This requires a supplier to
+        // capture the value and count when the terminal operation is executed
+        return StreamSupport.intStream(
+                () -> new String.IntCharArraySpliterator(value, 0, count, 0),
+                Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
+                false);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @since 1.9
+     */
+    @Override
+    public IntStream codePoints() {
+        // Reuse String-based spliterator. This requires a supplier to
+        // capture the value and count when the terminal operation is executed
+        return StreamSupport.intStream(
+                () -> new String.CodePointsSpliterator(value, 0, count, 0),
+                Spliterator.ORDERED,
+                false);
+    }
+
+    /**
      * Needed by {@code String} for the contentEquals method.
      */
     final char[] getValue() {
--- a/jdk/src/java.base/share/classes/java/lang/Object.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Object.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -42,6 +42,11 @@
     }
 
     /**
+     * Constructs a new object.
+     */
+    public Object() {}
+
+    /**
      * Returns the runtime class of this {@code Object}. The returned
      * {@code Class} object is the object that is locked by {@code
      * static synchronized} methods of the represented class.
@@ -86,12 +91,11 @@
      *     for unequal objects may improve the performance of hash tables.
      * </ul>
      * <p>
-     * As much as is reasonably practical, the hashCode method defined by
-     * class {@code Object} does return distinct integers for distinct
-     * objects. (This is typically implemented by converting the internal
-     * address of the object into an integer, but this implementation
-     * technique is not required by the
-     * Java&trade; programming language.)
+     * As much as is reasonably practical, the hashCode method defined
+     * by class {@code Object} does return distinct integers for
+     * distinct objects. (The hashCode may or may not be implemented
+     * as some function of an object's memory address at some point
+     * in time.)
      *
      * @return  a hash code value for this object.
      * @see     java.lang.Object#equals(java.lang.Object)
@@ -344,10 +348,12 @@
      *         ... // Perform action appropriate to condition
      *     }
      * </pre>
-     * (For more information on this topic, see Section 3.2.3 in Doug Lea's
-     * "Concurrent Programming in Java (Second Edition)" (Addison-Wesley,
-     * 2000), or Item 50 in Joshua Bloch's "Effective Java Programming
-     * Language Guide" (Addison-Wesley, 2001).
+     *
+     * (For more information on this topic, see section 14.2,
+     * Condition Queues, in Brian Goetz and others' "Java Concurrency
+     * in Practice" (Addison-Wesley, 2006) or Item 69 in Joshua
+     * Bloch's "Effective Java (Second Edition)" (Addison-Wesley,
+     * 2008).
      *
      * <p>If the current thread is {@linkplain java.lang.Thread#interrupt()
      * interrupted} by any thread before or while it is waiting, then an
--- a/jdk/src/java.base/share/classes/java/lang/String.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/String.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -34,10 +34,14 @@
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.Spliterator;
 import java.util.StringJoiner;
+import java.util.function.IntConsumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
 
 /**
  * The {@code String} class represents character strings. All
@@ -2894,6 +2898,180 @@
         return this;
     }
 
+    static class IntCharArraySpliterator implements Spliterator.OfInt {
+        private final char[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        IntCharArraySpliterator(char[] array, int acs) {
+            this(array, 0, array.length, acs);
+        }
+
+        IntCharArraySpliterator(char[] array, int origin, int fence, int acs) {
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
+                      | Spliterator.SUBSIZED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            return (lo >= mid)
+                   ? null
+                   : new IntCharArraySpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            char[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if ((a = array).length >= (hi = fence) &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do { action.accept(a[i]); } while (++i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                action.accept(array[index++]);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    /**
+     * Returns a stream of {@code int} zero-extending the {@code char} values
+     * from this sequence.  Any char which maps to a <a
+     * href="{@docRoot}/java/lang/Character.html#unicode">surrogate code
+     * point</a> is passed through uninterpreted.
+     *
+     * @return an IntStream of char values from this sequence
+     * @since 1.9
+     */
+    @Override
+    public IntStream chars() {
+        return StreamSupport.intStream(
+                new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false);
+    }
+
+    static class CodePointsSpliterator implements Spliterator.OfInt {
+        private final char[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CodePointsSpliterator(char[] array, int acs) {
+            this(array, 0, array.length, acs);
+        }
+
+        CodePointsSpliterator(char[] array, int origin, int fence, int acs) {
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            if (lo >= mid)
+                return null;
+
+            int midOneLess;
+            // If the mid-point intersects a surrogate pair
+            if (Character.isLowSurrogate(array[mid]) &&
+                Character.isHighSurrogate(array[midOneLess = (mid -1)])) {
+                // If there is only one pair it cannot be split
+                if (lo >= midOneLess)
+                    return null;
+                // Shift the mid-point to align with the surrogate pair
+                return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
+            }
+            return new CodePointsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            char[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if ((a = array).length >= (hi = fence) &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do {
+                    i = advance(a, i, hi, action);
+                } while (i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                index = advance(array, index, fence, action);
+                return true;
+            }
+            return false;
+        }
+
+        // Advance one code point from the index, i, and return the next
+        // index to advance from
+        private static int advance(char[] a, int i, int hi, IntConsumer action) {
+            char c1 = a[i++];
+            int cp = c1;
+            if (Character.isHighSurrogate(c1) && i < hi) {
+                char c2 = a[i];
+                if (Character.isLowSurrogate(c2)) {
+                    i++;
+                    cp = Character.toCodePoint(c1, c2);
+                }
+            }
+            action.accept(cp);
+            return i;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    /**
+     * Returns a stream of code point values from this sequence.  Any surrogate
+     * pairs encountered in the sequence are combined as if by {@linkplain
+     * Character#toCodePoint Character.toCodePoint} and the result is passed
+     * to the stream. Any other code units, including ordinary BMP characters,
+     * unpaired surrogates, and undefined code units, are zero-extended to
+     * {@code int} values which are then passed to the stream.
+     *
+     * @return an IntStream of Unicode code points from this sequence
+     * @since 1.9
+     */
+    @Override
+    public IntStream codePoints() {
+        return StreamSupport.intStream(
+                new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false);
+    }
+
     /**
      * Converts this string to a new character array.
      *
--- a/jdk/src/java.base/share/classes/java/lang/System.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/System.java	Wed Jul 05 20:17:15 2017 +0200
@@ -376,19 +376,16 @@
      * the difference between two such values, obtained within the same
      * instance of a Java virtual machine, is computed.
      *
-     * <p> For example, to measure how long some code takes to execute:
-     *  <pre> {@code
+     * <p>For example, to measure how long some code takes to execute:
+     * <pre> {@code
      * long startTime = System.nanoTime();
      * // ... the code being measured ...
-     * long estimatedTime = System.nanoTime() - startTime;}</pre>
+     * long elapsedNanos = System.nanoTime() - startTime;}</pre>
      *
-     * <p>To compare two nanoTime values
-     *  <pre> {@code
-     * long t0 = System.nanoTime();
-     * ...
-     * long t1 = System.nanoTime();}</pre>
-     *
-     * one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
+     * <p>To compare elapsed time against a timeout, use <pre> {@code
+     * if (System.nanoTime() - startTime >= timeoutNanos) ...}</pre>
+     * instead of <pre> {@code
+     * if (System.nanoTime() >= startTime + timeoutNanos) ...}</pre>
      * because of the possibility of numerical overflow.
      *
      * @return the current value of the running Java Virtual Machine's
--- a/jdk/src/java.base/share/classes/java/util/Spliterator.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Spliterator.java	Wed Jul 05 20:17:15 2017 +0200
@@ -553,6 +553,12 @@
      * sub-split size is known and additions or removals to the source are not
      * reflected when traversing.
      *
+     * <p>A top-level Spliterator should not report both {@code CONCURRENT} and
+     * {@code IMMUTABLE}, since they are mutually exclusive. Such a Spliterator
+     * is inconsistent and no guarantees can be made about any computation using
+     * that Spliterator. Sub-spliterators may report {@code IMMUTABLE} if
+     * additions or removals to the source are not reflected when traversing.
+     *
      * @apiNote Most concurrent collections maintain a consistency policy
      * guaranteeing accuracy with respect to elements present at the point of
      * Spliterator construction, but possibly not reflecting subsequent
--- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java	Wed Jul 05 20:17:15 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
@@ -845,22 +845,6 @@
     public native Object allocateInstance(Class<?> cls)
         throws InstantiationException;
 
-    /** Lock the object.  It must get unlocked via {@link #monitorExit}. */
-    public native void monitorEnter(Object o);
-
-    /**
-     * Unlock the object.  It must have been locked via {@link
-     * #monitorEnter}.
-     */
-    public native void monitorExit(Object o);
-
-    /**
-     * Tries to lock the object.  Returns true or false to indicate
-     * whether the lock succeeded.  If it did, the object must be
-     * unlocked via {@link #monitorExit}.
-     */
-    public native boolean tryMonitorEnter(Object o);
-
     /** Throw the exception without telling the verifier. */
     public native void throwException(Throwable ee);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/solaris/native/libnet/solaris_close.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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 <errno.h>
+#include <sys/socket.h>
+#include <stropts.h>
+#include <unistd.h>
+
+/* Support for restartable system calls on Solaris. */
+
+#define RESTARTABLE_RETURN_INT(_cmd) do {             \
+    int _result;                                      \
+    if (1) {                                          \
+        do {                                          \
+            _result = _cmd;                           \
+        } while((_result == -1) && (errno == EINTR)); \
+        return _result;                               \
+    }                                                 \
+} while(0)
+
+int NET_Read(int s, void* buf, size_t len) {
+    RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+                 struct sockaddr *from, socklen_t *fromlen) {
+    RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+    RESTARTABLE_RETURN_INT(readv(s, vector, count));
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+    RESTARTABLE_RETURN_INT(writev(s, vector, count));
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+    RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
+}
+
+int NET_SendTo(int s, const void *msg, int len,  unsigned  int flags,
+               const struct sockaddr *to, int tolen) {
+    RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+    RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
+}
+
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+    RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
+}
+
+int NET_SocketClose(int fd) {
+    return close(fd);
+}
+
+int NET_Dup2(int fd, int fd2) {
+    return dup2(fd, fd2);
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+    RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
+}
+
+int NET_Timeout(int s, long timeout) {
+    int result;
+    struct timeval t;
+    long prevtime, newtime;
+    struct pollfd pfd;
+    pfd.fd = s;
+    pfd.events = POLLIN;
+
+    if (timeout > 0) {
+        gettimeofday(&t, NULL);
+        prevtime = (t.tv_sec * 1000)  +  t.tv_usec / 1000;
+    }
+
+    for(;;) {
+        result = poll(&pfd, 1, timeout);
+        if (result < 0 && errno == EINTR) {
+            if (timeout > 0) {
+                gettimeofday(&t, NULL);
+                newtime = (t.tv_sec * 1000)  +  t.tv_usec /1000;
+                timeout -= newtime - prevtime;
+                if (timeout <= 0)
+                    return 0;
+                prevtime = newtime;
+            }
+        } else {
+            return result;
+        }
+    }
+}
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -25,24 +25,156 @@
 
 package java.lang;
 
-import java.io.IOException;
+import java.lang.ProcessBuilder.Redirect;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.lang.ProcessBuilder.Redirect;
-import java.lang.ProcessBuilder.Redirect;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.security.AccessController;
+import static java.security.AccessController.doPrivileged;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 
 /**
- * This class is for the exclusive use of ProcessBuilder.start() to
- * create new processes.
+ * This java.lang.Process subclass in the UNIX environment is for the exclusive use of
+ * ProcessBuilder.start() to create new processes.
  *
+ * @author Mario Wolczko and Ross Knippel.
+ * @author Konstantin Kladko (ported to Linux and Bsd)
  * @author Martin Buchholz
+ * @author Volker Simonis (ported to AIX)
  * @since   1.5
  */
-final class ProcessImpl {
+final class ProcessImpl extends Process {
     private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
         = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
 
-    private ProcessImpl() {}    // Not instantiable
+    private final int pid;
+    private int exitcode;
+    private boolean hasExited;
+
+    private /* final */ OutputStream stdin;
+    private /* final */ InputStream stdout;
+    private /* final */ InputStream  stderr;
+
+    // only used on Solaris
+    private /* final */ DeferredCloseInputStream stdout_inner_stream;
+
+    private static enum LaunchMechanism {
+        // order IS important!
+        FORK,
+        POSIX_SPAWN,
+        VFORK
+    }
+
+    private static enum Platform {
+
+        LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
+
+        BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
+
+        SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
+
+        AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
+
+        final LaunchMechanism defaultLaunchMechanism;
+        final Set<LaunchMechanism> validLaunchMechanisms;
+
+        Platform(LaunchMechanism ... launchMechanisms) {
+            this.defaultLaunchMechanism = launchMechanisms[0];
+            this.validLaunchMechanisms =
+                    EnumSet.copyOf(Arrays.asList(launchMechanisms));
+        }
+
+        @SuppressWarnings("fallthrough")
+        private String helperPath(String javahome, String osArch) {
+            switch (this) {
+                case SOLARIS:
+                    if (osArch.equals("x86")) { osArch = "i386"; }
+                    else if (osArch.equals("x86_64")) { osArch = "amd64"; }
+                    // fall through...
+                case LINUX:
+                case AIX:
+                    return javahome + "/lib/" + osArch + "/jspawnhelper";
+
+                case BSD:
+                    return javahome + "/lib/jspawnhelper";
+
+                default:
+                    throw new AssertionError("Unsupported platform: " + this);
+            }
+        }
+
+        String helperPath() {
+            return AccessController.doPrivileged(
+                    (PrivilegedAction<String>) () ->
+                            helperPath(System.getProperty("java.home"),
+                                    System.getProperty("os.arch"))
+            );
+        }
+
+        LaunchMechanism launchMechanism() {
+            return AccessController.doPrivileged(
+                    (PrivilegedAction<LaunchMechanism>) () -> {
+                        String s = System.getProperty(
+                                "jdk.lang.Process.launchMechanism");
+                        LaunchMechanism lm;
+                        if (s == null) {
+                            lm = defaultLaunchMechanism;
+                            s = lm.name().toLowerCase(Locale.ENGLISH);
+                        } else {
+                            try {
+                                lm = LaunchMechanism.valueOf(
+                                        s.toUpperCase(Locale.ENGLISH));
+                            } catch (IllegalArgumentException e) {
+                                lm = null;
+                            }
+                        }
+                        if (lm == null || !validLaunchMechanisms.contains(lm)) {
+                            throw new Error(
+                                    s + " is not a supported " +
+                                            "process launch mechanism on this platform."
+                            );
+                        }
+                        return lm;
+                    }
+            );
+        }
+
+        static Platform get() {
+            String osName = AccessController.doPrivileged(
+                    (PrivilegedAction<String>) () -> System.getProperty("os.name")
+            );
+
+            if (osName.equals("Linux")) { return LINUX; }
+            if (osName.contains("OS X")) { return BSD; }
+            if (osName.equals("SunOS")) { return SOLARIS; }
+            if (osName.equals("AIX")) { return AIX; }
+
+            throw new Error(osName + " is not a supported OS platform.");
+        }
+    }
+
+    private static final Platform platform = Platform.get();
+    private static final LaunchMechanism launchMechanism = platform.launchMechanism();
+    private static final byte[] helperpath = toCString(platform.helperPath());
+
+    /* this is for the reaping thread */
+    private native int waitForProcessExit(int pid);
 
     private static byte[] toCString(String s) {
         if (s == null)
@@ -50,8 +182,8 @@
         byte[] bytes = s.getBytes();
         byte[] result = new byte[bytes.length + 1];
         System.arraycopy(bytes, 0,
-                         result, 0,
-                         bytes.length);
+                result, 0,
+                bytes.length);
         result[result.length-1] = (byte)0;
         return result;
     }
@@ -62,7 +194,7 @@
                          String dir,
                          ProcessBuilder.Redirect[] redirects,
                          boolean redirectErrorStream)
-        throws IOException
+            throws IOException
     {
         assert cmdarray != null && cmdarray.length > 0;
 
@@ -112,7 +244,7 @@
                     std_fds[1] = 1;
                 else {
                     f1 = new FileOutputStream(redirects[1].file(),
-                                              redirects[1].append());
+                            redirects[1].append());
                     std_fds[1] = fdAccess.get(f1.getFD());
                 }
 
@@ -122,18 +254,18 @@
                     std_fds[2] = 2;
                 else {
                     f2 = new FileOutputStream(redirects[2].file(),
-                                              redirects[2].append());
+                            redirects[2].append());
                     std_fds[2] = fdAccess.get(f2.getFD());
                 }
             }
 
-        return new UNIXProcess
-            (toCString(cmdarray[0]),
-             argBlock, args.length,
-             envBlock, envc[0],
-             toCString(dir),
-                 std_fds,
-             redirectErrorStream);
+            return new ProcessImpl
+                    (toCString(cmdarray[0]),
+                            argBlock, args.length,
+                            envBlock, envc[0],
+                            toCString(dir),
+                            std_fds,
+                            redirectErrorStream);
         } finally {
             // In theory, close() can throw IOException
             // (although it is rather unlikely to happen here)
@@ -144,4 +276,654 @@
             }
         }
     }
+
+
+    /**
+     * Creates a process. Depending on the {@code mode} flag, this is done by
+     * one of the following mechanisms:
+     * <pre>
+     *   1 - fork(2) and exec(2)
+     *   2 - posix_spawn(3P)
+     *   3 - vfork(2) and exec(2)
+     *
+     *  (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
+     * </pre>
+     * @param fds an array of three file descriptors.
+     *        Indexes 0, 1, and 2 correspond to standard input,
+     *        standard output and standard error, respectively.  On
+     *        input, a value of -1 means to create a pipe to connect
+     *        child and parent processes.  On output, a value which
+     *        is not -1 is the parent pipe fd corresponding to the
+     *        pipe which has been created.  An element of this array
+     *        is -1 on input if and only if it is <em>not</em> -1 on
+     *        output.
+     * @return the pid of the subprocess
+     */
+    private native int forkAndExec(int mode, byte[] helperpath,
+                                   byte[] prog,
+                                   byte[] argBlock, int argc,
+                                   byte[] envBlock, int envc,
+                                   byte[] dir,
+                                   int[] fds,
+                                   boolean redirectErrorStream)
+            throws IOException;
+
+    /**
+     * The thread pool of "process reaper" daemon threads.
+     */
+    private static final Executor processReaperExecutor =
+            doPrivileged((PrivilegedAction<Executor>) () -> {
+
+                ThreadGroup tg = Thread.currentThread().getThreadGroup();
+                while (tg.getParent() != null) tg = tg.getParent();
+                ThreadGroup systemThreadGroup = tg;
+
+                ThreadFactory threadFactory = grimReaper -> {
+                    // Our thread stack requirement is quite modest.
+                    Thread t = new Thread(systemThreadGroup, grimReaper,
+                            "process reaper", 32768);
+                    t.setDaemon(true);
+                    // A small attempt (probably futile) to avoid priority inversion
+                    t.setPriority(Thread.MAX_PRIORITY);
+                    return t;
+                };
+
+                return Executors.newCachedThreadPool(threadFactory);
+            });
+
+    private ProcessImpl(final byte[] prog,
+                final byte[] argBlock, final int argc,
+                final byte[] envBlock, final int envc,
+                final byte[] dir,
+                final int[] fds,
+                final boolean redirectErrorStream)
+            throws IOException {
+
+        pid = forkAndExec(launchMechanism.ordinal() + 1,
+                helperpath,
+                prog,
+                argBlock, argc,
+                envBlock, envc,
+                dir,
+                fds,
+                redirectErrorStream);
+
+        try {
+            doPrivileged((PrivilegedExceptionAction<Void>) () -> {
+                initStreams(fds);
+                return null;
+            });
+        } catch (PrivilegedActionException ex) {
+            throw (IOException) ex.getException();
+        }
+    }
+
+    static FileDescriptor newFileDescriptor(int fd) {
+        FileDescriptor fileDescriptor = new FileDescriptor();
+        fdAccess.set(fileDescriptor, fd);
+        return fileDescriptor;
+    }
+
+    void initStreams(int[] fds) throws IOException {
+        switch (platform) {
+            case LINUX:
+            case BSD:
+                stdin = (fds[0] == -1) ?
+                        ProcessBuilder.NullOutputStream.INSTANCE :
+                        new ProcessPipeOutputStream(fds[0]);
+
+                stdout = (fds[1] == -1) ?
+                        ProcessBuilder.NullInputStream.INSTANCE :
+                        new ProcessPipeInputStream(fds[1]);
+
+                stderr = (fds[2] == -1) ?
+                        ProcessBuilder.NullInputStream.INSTANCE :
+                        new ProcessPipeInputStream(fds[2]);
+
+                processReaperExecutor.execute(() -> {
+                    int exitcode = waitForProcessExit(pid);
+
+                    synchronized (this) {
+                        this.exitcode = exitcode;
+                        this.hasExited = true;
+                        this.notifyAll();
+                    }
+
+                    if (stdout instanceof ProcessPipeInputStream)
+                        ((ProcessPipeInputStream) stdout).processExited();
+
+                    if (stderr instanceof ProcessPipeInputStream)
+                        ((ProcessPipeInputStream) stderr).processExited();
+
+                    if (stdin instanceof ProcessPipeOutputStream)
+                        ((ProcessPipeOutputStream) stdin).processExited();
+                });
+                break;
+
+            case SOLARIS:
+                stdin = (fds[0] == -1) ?
+                        ProcessBuilder.NullOutputStream.INSTANCE :
+                        new BufferedOutputStream(
+                                new FileOutputStream(newFileDescriptor(fds[0])));
+
+                stdout = (fds[1] == -1) ?
+                        ProcessBuilder.NullInputStream.INSTANCE :
+                        new BufferedInputStream(
+                                stdout_inner_stream =
+                                        new DeferredCloseInputStream(
+                                                newFileDescriptor(fds[1])));
+
+                stderr = (fds[2] == -1) ?
+                        ProcessBuilder.NullInputStream.INSTANCE :
+                        new DeferredCloseInputStream(newFileDescriptor(fds[2]));
+
+                /*
+                 * For each subprocess forked a corresponding reaper task
+                 * is submitted.  That task is the only thread which waits
+                 * for the subprocess to terminate and it doesn't hold any
+                 * locks while doing so.  This design allows waitFor() and
+                 * exitStatus() to be safely executed in parallel (and they
+                 * need no native code).
+                 */
+                processReaperExecutor.execute(() -> {
+                    int exitcode = waitForProcessExit(pid);
+
+                    synchronized (this) {
+                        this.exitcode = exitcode;
+                        this.hasExited = true;
+                        this.notifyAll();
+                    }
+                });
+                break;
+
+            case AIX:
+                stdin = (fds[0] == -1) ?
+                        ProcessBuilder.NullOutputStream.INSTANCE :
+                        new ProcessPipeOutputStream(fds[0]);
+
+                stdout = (fds[1] == -1) ?
+                        ProcessBuilder.NullInputStream.INSTANCE :
+                        new DeferredCloseProcessPipeInputStream(fds[1]);
+
+                stderr = (fds[2] == -1) ?
+                        ProcessBuilder.NullInputStream.INSTANCE :
+                        new DeferredCloseProcessPipeInputStream(fds[2]);
+
+                processReaperExecutor.execute(() -> {
+                    int exitcode = waitForProcessExit(pid);
+
+                    synchronized (this) {
+                        this.exitcode = exitcode;
+                        this.hasExited = true;
+                        this.notifyAll();
+                    }
+
+                    if (stdout instanceof DeferredCloseProcessPipeInputStream)
+                        ((DeferredCloseProcessPipeInputStream) stdout).processExited();
+
+                    if (stderr instanceof DeferredCloseProcessPipeInputStream)
+                        ((DeferredCloseProcessPipeInputStream) stderr).processExited();
+
+                    if (stdin instanceof ProcessPipeOutputStream)
+                        ((ProcessPipeOutputStream) stdin).processExited();
+                });
+                break;
+
+            default: throw new AssertionError("Unsupported platform: " + platform);
+        }
+    }
+
+    public OutputStream getOutputStream() {
+        return stdin;
+    }
+
+    public InputStream getInputStream() {
+        return stdout;
+    }
+
+    public InputStream getErrorStream() {
+        return stderr;
+    }
+
+    public synchronized int waitFor() throws InterruptedException {
+        while (!hasExited) {
+            wait();
+        }
+        return exitcode;
+    }
+
+    @Override
+    public synchronized boolean waitFor(long timeout, TimeUnit unit)
+            throws InterruptedException
+    {
+        if (hasExited) return true;
+        if (timeout <= 0) return false;
+
+        long remainingNanos = unit.toNanos(timeout);
+        long deadline = System.nanoTime() + remainingNanos;
+
+        do {
+            // Round up to next millisecond
+            wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
+            if (hasExited) {
+                return true;
+            }
+            remainingNanos = deadline - System.nanoTime();
+        } while (remainingNanos > 0);
+        return hasExited;
+    }
+
+    public synchronized int exitValue() {
+        if (!hasExited) {
+            throw new IllegalThreadStateException("process hasn't exited");
+        }
+        return exitcode;
+    }
+
+    private static native void destroyProcess(int pid, boolean force);
+
+    private void destroy(boolean force) {
+        switch (platform) {
+            case LINUX:
+            case BSD:
+            case AIX:
+                // There is a risk that pid will be recycled, causing us to
+                // kill the wrong process!  So we only terminate processes
+                // that appear to still be running.  Even with this check,
+                // there is an unavoidable race condition here, but the window
+                // is very small, and OSes try hard to not recycle pids too
+                // soon, so this is quite safe.
+                synchronized (this) {
+                    if (!hasExited)
+                        destroyProcess(pid, force);
+                }
+                try { stdin.close();  } catch (IOException ignored) {}
+                try { stdout.close(); } catch (IOException ignored) {}
+                try { stderr.close(); } catch (IOException ignored) {}
+                break;
+
+            case SOLARIS:
+                // There is a risk that pid will be recycled, causing us to
+                // kill the wrong process!  So we only terminate processes
+                // that appear to still be running.  Even with this check,
+                // there is an unavoidable race condition here, but the window
+                // is very small, and OSes try hard to not recycle pids too
+                // soon, so this is quite safe.
+                synchronized (this) {
+                    if (!hasExited)
+                        destroyProcess(pid, force);
+                    try {
+                        stdin.close();
+                        if (stdout_inner_stream != null)
+                            stdout_inner_stream.closeDeferred(stdout);
+                        if (stderr instanceof DeferredCloseInputStream)
+                            ((DeferredCloseInputStream) stderr)
+                                    .closeDeferred(stderr);
+                    } catch (IOException e) {
+                        // ignore
+                    }
+                }
+                break;
+
+            default: throw new AssertionError("Unsupported platform: " + platform);
+        }
+    }
+
+    public void destroy() {
+        destroy(false);
+    }
+
+    @Override
+    public Process destroyForcibly() {
+        destroy(true);
+        return this;
+    }
+
+    @Override
+    public long getPid() {
+        return pid;
+    }
+
+    @Override
+    public synchronized boolean isAlive() {
+        return !hasExited;
+    }
+
+    private static native void init();
+
+    static {
+        init();
+    }
+
+    /**
+     * A buffered input stream for a subprocess pipe file descriptor
+     * that allows the underlying file descriptor to be reclaimed when
+     * the process exits, via the processExited hook.
+     *
+     * This is tricky because we do not want the user-level InputStream to be
+     * closed until the user invokes close(), and we need to continue to be
+     * able to read any buffered data lingering in the OS pipe buffer.
+     */
+    private static class ProcessPipeInputStream extends BufferedInputStream {
+        private final Object closeLock = new Object();
+
+        ProcessPipeInputStream(int fd) {
+            super(new FileInputStream(newFileDescriptor(fd)));
+        }
+        private static byte[] drainInputStream(InputStream in)
+                throws IOException {
+            int n = 0;
+            int j;
+            byte[] a = null;
+            while ((j = in.available()) > 0) {
+                a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+                n += in.read(a, n, j);
+            }
+            return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
+        }
+
+        /** Called by the process reaper thread when the process exits. */
+        synchronized void processExited() {
+            synchronized (closeLock) {
+                try {
+                    InputStream in = this.in;
+                    // this stream is closed if and only if: in == null
+                    if (in != null) {
+                        byte[] stragglers = drainInputStream(in);
+                        in.close();
+                        this.in = (stragglers == null) ?
+                                ProcessBuilder.NullInputStream.INSTANCE :
+                                new ByteArrayInputStream(stragglers);
+                    }
+                } catch (IOException ignored) {}
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            // BufferedInputStream#close() is not synchronized unlike most other
+            // methods. Synchronizing helps avoid race with processExited().
+            synchronized (closeLock) {
+                super.close();
+            }
+        }
+    }
+
+    /**
+     * A buffered output stream for a subprocess pipe file descriptor
+     * that allows the underlying file descriptor to be reclaimed when
+     * the process exits, via the processExited hook.
+     */
+    private static class ProcessPipeOutputStream extends BufferedOutputStream {
+        ProcessPipeOutputStream(int fd) {
+            super(new FileOutputStream(newFileDescriptor(fd)));
+        }
+
+        /** Called by the process reaper thread when the process exits. */
+        synchronized void processExited() {
+            OutputStream out = this.out;
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException ignored) {
+                    // We know of no reason to get an IOException, but if
+                    // we do, there's nothing else to do but carry on.
+                }
+                this.out = ProcessBuilder.NullOutputStream.INSTANCE;
+            }
+        }
+    }
+
+    // A FileInputStream that supports the deferment of the actual close
+    // operation until the last pending I/O operation on the stream has
+    // finished.  This is required on Solaris because we must close the stdin
+    // and stdout streams in the destroy method in order to reclaim the
+    // underlying file descriptors.  Doing so, however, causes any thread
+    // currently blocked in a read on one of those streams to receive an
+    // IOException("Bad file number"), which is incompatible with historical
+    // behavior.  By deferring the close we allow any pending reads to see -1
+    // (EOF) as they did before.
+    //
+    private static class DeferredCloseInputStream extends FileInputStream
+    {
+        DeferredCloseInputStream(FileDescriptor fd) {
+            super(fd);
+        }
+
+        private Object lock = new Object();     // For the following fields
+        private boolean closePending = false;
+        private int useCount = 0;
+        private InputStream streamToClose;
+
+        private void raise() {
+            synchronized (lock) {
+                useCount++;
+            }
+        }
+
+        private void lower() throws IOException {
+            synchronized (lock) {
+                useCount--;
+                if (useCount == 0 && closePending) {
+                    streamToClose.close();
+                }
+            }
+        }
+
+        // stc is the actual stream to be closed; it might be this object, or
+        // it might be an upstream object for which this object is downstream.
+        //
+        private void closeDeferred(InputStream stc) throws IOException {
+            synchronized (lock) {
+                if (useCount == 0) {
+                    stc.close();
+                } else {
+                    closePending = true;
+                    streamToClose = stc;
+                }
+            }
+        }
+
+        public void close() throws IOException {
+            synchronized (lock) {
+                useCount = 0;
+                closePending = false;
+            }
+            super.close();
+        }
+
+        public int read() throws IOException {
+            raise();
+            try {
+                return super.read();
+            } finally {
+                lower();
+            }
+        }
+
+        public int read(byte[] b) throws IOException {
+            raise();
+            try {
+                return super.read(b);
+            } finally {
+                lower();
+            }
+        }
+
+        public int read(byte[] b, int off, int len) throws IOException {
+            raise();
+            try {
+                return super.read(b, off, len);
+            } finally {
+                lower();
+            }
+        }
+
+        public long skip(long n) throws IOException {
+            raise();
+            try {
+                return super.skip(n);
+            } finally {
+                lower();
+            }
+        }
+
+        public int available() throws IOException {
+            raise();
+            try {
+                return super.available();
+            } finally {
+                lower();
+            }
+        }
+    }
+
+    /**
+     * A buffered input stream for a subprocess pipe file descriptor
+     * that allows the underlying file descriptor to be reclaimed when
+     * the process exits, via the processExited hook.
+     *
+     * This is tricky because we do not want the user-level InputStream to be
+     * closed until the user invokes close(), and we need to continue to be
+     * able to read any buffered data lingering in the OS pipe buffer.
+     *
+     * On AIX this is especially tricky, because the 'close()' system call
+     * will block if another thread is at the same time blocked in a file
+     * operation (e.g. 'read()') on the same file descriptor. We therefore
+     * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
+     * with the DeferredCloseInputStream approach used on Solaris. This means
+     * that every potentially blocking operation on the file descriptor
+     * increments a counter before it is executed and decrements it once it
+     * finishes. The 'close()' operation will only be executed if there are
+     * no pending operations. Otherwise it is deferred after the last pending
+     * operation has finished.
+     *
+     */
+    private static class DeferredCloseProcessPipeInputStream
+            extends BufferedInputStream {
+
+        private final Object closeLock = new Object();
+        private int useCount = 0;
+        private boolean closePending = false;
+
+        DeferredCloseProcessPipeInputStream(int fd) {
+            super(new FileInputStream(newFileDescriptor(fd)));
+        }
+
+        private InputStream drainInputStream(InputStream in)
+                throws IOException {
+            int n = 0;
+            int j;
+            byte[] a = null;
+            synchronized (closeLock) {
+                if (buf == null) // asynchronous close()?
+                    return null; // discard
+                j = in.available();
+            }
+            while (j > 0) {
+                a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+                synchronized (closeLock) {
+                    if (buf == null) // asynchronous close()?
+                        return null; // discard
+                    n += in.read(a, n, j);
+                    j = in.available();
+                }
+            }
+            return (a == null) ?
+                    ProcessBuilder.NullInputStream.INSTANCE :
+                    new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
+        }
+
+        /** Called by the process reaper thread when the process exits. */
+        synchronized void processExited() {
+            try {
+                InputStream in = this.in;
+                if (in != null) {
+                    InputStream stragglers = drainInputStream(in);
+                    in.close();
+                    this.in = stragglers;
+                }
+            } catch (IOException ignored) { }
+        }
+
+        private void raise() {
+            synchronized (closeLock) {
+                useCount++;
+            }
+        }
+
+        private void lower() throws IOException {
+            synchronized (closeLock) {
+                useCount--;
+                if (useCount == 0 && closePending) {
+                    closePending = false;
+                    super.close();
+                }
+            }
+        }
+
+        @Override
+        public int read() throws IOException {
+            raise();
+            try {
+                return super.read();
+            } finally {
+                lower();
+            }
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            raise();
+            try {
+                return super.read(b);
+            } finally {
+                lower();
+            }
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            raise();
+            try {
+                return super.read(b, off, len);
+            } finally {
+                lower();
+            }
+        }
+
+        @Override
+        public long skip(long n) throws IOException {
+            raise();
+            try {
+                return super.skip(n);
+            } finally {
+                lower();
+            }
+        }
+
+        @Override
+        public int available() throws IOException {
+            raise();
+            try {
+                return super.available();
+            } finally {
+                lower();
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            // BufferedInputStream#close() is not synchronized unlike most other
+            // methods. Synchronizing helps avoid racing with drainInputStream().
+            synchronized (closeLock) {
+                if (useCount == 0) {
+                    super.close();
+                }
+                else {
+                    closePending = true;
+                }
+            }
+        }
+    }
 }
--- a/jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,836 +0,0 @@
-/*
- * Copyright (c) 1995, 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.
- */
-
-package java.lang;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.security.AccessController;
-import static java.security.AccessController.doPrivileged;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-/**
- * java.lang.Process subclass in the UNIX environment.
- *
- * @author Mario Wolczko and Ross Knippel.
- * @author Konstantin Kladko (ported to Linux and Bsd)
- * @author Martin Buchholz
- * @author Volker Simonis (ported to AIX)
- */
-final class UNIXProcess extends Process {
-    private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
-        = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
-
-    private final int pid;
-    private int exitcode;
-    private boolean hasExited;
-
-    private /* final */ OutputStream stdin;
-    private /* final */ InputStream  stdout;
-    private /* final */ InputStream  stderr;
-
-    // only used on Solaris
-    private /* final */ DeferredCloseInputStream stdout_inner_stream;
-
-    private static enum LaunchMechanism {
-        // order IS important!
-        FORK,
-        POSIX_SPAWN,
-        VFORK
-    }
-
-    private static enum Platform {
-
-        LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
-
-        BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
-
-        SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
-
-        AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
-
-        final LaunchMechanism defaultLaunchMechanism;
-        final Set<LaunchMechanism> validLaunchMechanisms;
-
-        Platform(LaunchMechanism ... launchMechanisms) {
-            this.defaultLaunchMechanism = launchMechanisms[0];
-            this.validLaunchMechanisms =
-                EnumSet.copyOf(Arrays.asList(launchMechanisms));
-        }
-
-        @SuppressWarnings("fallthrough")
-        private String helperPath(String javahome, String osArch) {
-            switch (this) {
-                case SOLARIS:
-                    if (osArch.equals("x86")) { osArch = "i386"; }
-                    else if (osArch.equals("x86_64")) { osArch = "amd64"; }
-                    // fall through...
-                case LINUX:
-                case AIX:
-                    return javahome + "/lib/" + osArch + "/jspawnhelper";
-
-                case BSD:
-                    return javahome + "/lib/jspawnhelper";
-
-                default:
-                    throw new AssertionError("Unsupported platform: " + this);
-            }
-        }
-
-        String helperPath() {
-            return AccessController.doPrivileged(
-                (PrivilegedAction<String>) () ->
-                    helperPath(System.getProperty("java.home"),
-                               System.getProperty("os.arch"))
-            );
-        }
-
-        LaunchMechanism launchMechanism() {
-            return AccessController.doPrivileged(
-                (PrivilegedAction<LaunchMechanism>) () -> {
-                    String s = System.getProperty(
-                        "jdk.lang.Process.launchMechanism");
-                    LaunchMechanism lm;
-                    if (s == null) {
-                        lm = defaultLaunchMechanism;
-                        s = lm.name().toLowerCase(Locale.ENGLISH);
-                    } else {
-                        try {
-                            lm = LaunchMechanism.valueOf(
-                                s.toUpperCase(Locale.ENGLISH));
-                        } catch (IllegalArgumentException e) {
-                            lm = null;
-                        }
-                    }
-                    if (lm == null || !validLaunchMechanisms.contains(lm)) {
-                        throw new Error(
-                            s + " is not a supported " +
-                            "process launch mechanism on this platform."
-                        );
-                    }
-                    return lm;
-                }
-            );
-        }
-
-        static Platform get() {
-            String osName = AccessController.doPrivileged(
-                (PrivilegedAction<String>) () -> System.getProperty("os.name")
-            );
-
-            if (osName.equals("Linux")) { return LINUX; }
-            if (osName.contains("OS X")) { return BSD; }
-            if (osName.equals("SunOS")) { return SOLARIS; }
-            if (osName.equals("AIX")) { return AIX; }
-
-            throw new Error(osName + " is not a supported OS platform.");
-        }
-    }
-
-    private static final Platform platform = Platform.get();
-    private static final LaunchMechanism launchMechanism = platform.launchMechanism();
-    private static final byte[] helperpath = toCString(platform.helperPath());
-
-    private static byte[] toCString(String s) {
-        if (s == null)
-            return null;
-        byte[] bytes = s.getBytes();
-        byte[] result = new byte[bytes.length + 1];
-        System.arraycopy(bytes, 0,
-                         result, 0,
-                         bytes.length);
-        result[result.length-1] = (byte)0;
-        return result;
-    }
-
-    /* this is for the reaping thread */
-    private native int waitForProcessExit(int pid);
-
-    /**
-     * Creates a process. Depending on the {@code mode} flag, this is done by
-     * one of the following mechanisms:
-     * <pre>
-     *   1 - fork(2) and exec(2)
-     *   2 - posix_spawn(3P)
-     *   3 - vfork(2) and exec(2)
-     *
-     *  (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
-     * </pre>
-     * @param fds an array of three file descriptors.
-     *        Indexes 0, 1, and 2 correspond to standard input,
-     *        standard output and standard error, respectively.  On
-     *        input, a value of -1 means to create a pipe to connect
-     *        child and parent processes.  On output, a value which
-     *        is not -1 is the parent pipe fd corresponding to the
-     *        pipe which has been created.  An element of this array
-     *        is -1 on input if and only if it is <em>not</em> -1 on
-     *        output.
-     * @return the pid of the subprocess
-     */
-    private native int forkAndExec(int mode, byte[] helperpath,
-                                   byte[] prog,
-                                   byte[] argBlock, int argc,
-                                   byte[] envBlock, int envc,
-                                   byte[] dir,
-                                   int[] fds,
-                                   boolean redirectErrorStream)
-        throws IOException;
-
-    /**
-     * The thread pool of "process reaper" daemon threads.
-     */
-    private static final Executor processReaperExecutor =
-        doPrivileged((PrivilegedAction<Executor>) () -> {
-
-            ThreadGroup tg = Thread.currentThread().getThreadGroup();
-            while (tg.getParent() != null) tg = tg.getParent();
-            ThreadGroup systemThreadGroup = tg;
-
-            ThreadFactory threadFactory = grimReaper -> {
-                // Our thread stack requirement is quite modest.
-                Thread t = new Thread(systemThreadGroup, grimReaper,
-                                      "process reaper", 32768);
-                t.setDaemon(true);
-                // A small attempt (probably futile) to avoid priority inversion
-                t.setPriority(Thread.MAX_PRIORITY);
-                return t;
-            };
-
-            return Executors.newCachedThreadPool(threadFactory);
-        });
-
-    UNIXProcess(final byte[] prog,
-                final byte[] argBlock, final int argc,
-                final byte[] envBlock, final int envc,
-                final byte[] dir,
-                final int[] fds,
-                final boolean redirectErrorStream)
-            throws IOException {
-
-        pid = forkAndExec(launchMechanism.ordinal() + 1,
-                          helperpath,
-                          prog,
-                          argBlock, argc,
-                          envBlock, envc,
-                          dir,
-                          fds,
-                          redirectErrorStream);
-
-        try {
-            doPrivileged((PrivilegedExceptionAction<Void>) () -> {
-                initStreams(fds);
-                return null;
-            });
-        } catch (PrivilegedActionException ex) {
-            throw (IOException) ex.getException();
-        }
-    }
-
-    static FileDescriptor newFileDescriptor(int fd) {
-        FileDescriptor fileDescriptor = new FileDescriptor();
-        fdAccess.set(fileDescriptor, fd);
-        return fileDescriptor;
-    }
-
-    void initStreams(int[] fds) throws IOException {
-        switch (platform) {
-            case LINUX:
-            case BSD:
-                stdin = (fds[0] == -1) ?
-                        ProcessBuilder.NullOutputStream.INSTANCE :
-                        new ProcessPipeOutputStream(fds[0]);
-
-                stdout = (fds[1] == -1) ?
-                         ProcessBuilder.NullInputStream.INSTANCE :
-                         new ProcessPipeInputStream(fds[1]);
-
-                stderr = (fds[2] == -1) ?
-                         ProcessBuilder.NullInputStream.INSTANCE :
-                         new ProcessPipeInputStream(fds[2]);
-
-                processReaperExecutor.execute(() -> {
-                    int exitcode = waitForProcessExit(pid);
-
-                    synchronized (this) {
-                        this.exitcode = exitcode;
-                        this.hasExited = true;
-                        this.notifyAll();
-                    }
-
-                    if (stdout instanceof ProcessPipeInputStream)
-                        ((ProcessPipeInputStream) stdout).processExited();
-
-                    if (stderr instanceof ProcessPipeInputStream)
-                        ((ProcessPipeInputStream) stderr).processExited();
-
-                    if (stdin instanceof ProcessPipeOutputStream)
-                        ((ProcessPipeOutputStream) stdin).processExited();
-                });
-                break;
-
-            case SOLARIS:
-                stdin = (fds[0] == -1) ?
-                        ProcessBuilder.NullOutputStream.INSTANCE :
-                        new BufferedOutputStream(
-                            new FileOutputStream(newFileDescriptor(fds[0])));
-
-                stdout = (fds[1] == -1) ?
-                         ProcessBuilder.NullInputStream.INSTANCE :
-                         new BufferedInputStream(
-                             stdout_inner_stream =
-                                 new DeferredCloseInputStream(
-                                     newFileDescriptor(fds[1])));
-
-                stderr = (fds[2] == -1) ?
-                         ProcessBuilder.NullInputStream.INSTANCE :
-                         new DeferredCloseInputStream(newFileDescriptor(fds[2]));
-
-                /*
-                 * For each subprocess forked a corresponding reaper task
-                 * is submitted.  That task is the only thread which waits
-                 * for the subprocess to terminate and it doesn't hold any
-                 * locks while doing so.  This design allows waitFor() and
-                 * exitStatus() to be safely executed in parallel (and they
-                 * need no native code).
-                 */
-                processReaperExecutor.execute(() -> {
-                    int exitcode = waitForProcessExit(pid);
-
-                    synchronized (this) {
-                        this.exitcode = exitcode;
-                        this.hasExited = true;
-                        this.notifyAll();
-                    }
-                });
-                break;
-
-            case AIX:
-                stdin = (fds[0] == -1) ?
-                        ProcessBuilder.NullOutputStream.INSTANCE :
-                        new ProcessPipeOutputStream(fds[0]);
-
-                stdout = (fds[1] == -1) ?
-                         ProcessBuilder.NullInputStream.INSTANCE :
-                         new DeferredCloseProcessPipeInputStream(fds[1]);
-
-                stderr = (fds[2] == -1) ?
-                         ProcessBuilder.NullInputStream.INSTANCE :
-                         new DeferredCloseProcessPipeInputStream(fds[2]);
-
-                processReaperExecutor.execute(() -> {
-                    int exitcode = waitForProcessExit(pid);
-
-                    synchronized (this) {
-                        this.exitcode = exitcode;
-                        this.hasExited = true;
-                        this.notifyAll();
-                    }
-
-                    if (stdout instanceof DeferredCloseProcessPipeInputStream)
-                        ((DeferredCloseProcessPipeInputStream) stdout).processExited();
-
-                    if (stderr instanceof DeferredCloseProcessPipeInputStream)
-                        ((DeferredCloseProcessPipeInputStream) stderr).processExited();
-
-                    if (stdin instanceof ProcessPipeOutputStream)
-                        ((ProcessPipeOutputStream) stdin).processExited();
-                });
-                break;
-
-            default: throw new AssertionError("Unsupported platform: " + platform);
-        }
-    }
-
-    public OutputStream getOutputStream() {
-        return stdin;
-    }
-
-    public InputStream getInputStream() {
-        return stdout;
-    }
-
-    public InputStream getErrorStream() {
-        return stderr;
-    }
-
-    public synchronized int waitFor() throws InterruptedException {
-        while (!hasExited) {
-            wait();
-        }
-        return exitcode;
-    }
-
-    @Override
-    public synchronized boolean waitFor(long timeout, TimeUnit unit)
-        throws InterruptedException
-    {
-        if (hasExited) return true;
-        if (timeout <= 0) return false;
-
-        long remainingNanos = unit.toNanos(timeout);
-        long deadline = System.nanoTime() + remainingNanos;
-
-        do {
-            // Round up to next millisecond
-            wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
-            if (hasExited) {
-                return true;
-            }
-            remainingNanos = deadline - System.nanoTime();
-        } while (remainingNanos > 0);
-        return hasExited;
-    }
-
-    public synchronized int exitValue() {
-        if (!hasExited) {
-            throw new IllegalThreadStateException("process hasn't exited");
-        }
-        return exitcode;
-    }
-
-    private static native void destroyProcess(int pid, boolean force);
-
-    private void destroy(boolean force) {
-        switch (platform) {
-            case LINUX:
-            case BSD:
-            case AIX:
-                // There is a risk that pid will be recycled, causing us to
-                // kill the wrong process!  So we only terminate processes
-                // that appear to still be running.  Even with this check,
-                // there is an unavoidable race condition here, but the window
-                // is very small, and OSes try hard to not recycle pids too
-                // soon, so this is quite safe.
-                synchronized (this) {
-                    if (!hasExited)
-                        destroyProcess(pid, force);
-                }
-                try { stdin.close();  } catch (IOException ignored) {}
-                try { stdout.close(); } catch (IOException ignored) {}
-                try { stderr.close(); } catch (IOException ignored) {}
-                break;
-
-            case SOLARIS:
-                // There is a risk that pid will be recycled, causing us to
-                // kill the wrong process!  So we only terminate processes
-                // that appear to still be running.  Even with this check,
-                // there is an unavoidable race condition here, but the window
-                // is very small, and OSes try hard to not recycle pids too
-                // soon, so this is quite safe.
-                synchronized (this) {
-                    if (!hasExited)
-                        destroyProcess(pid, force);
-                    try {
-                        stdin.close();
-                        if (stdout_inner_stream != null)
-                            stdout_inner_stream.closeDeferred(stdout);
-                        if (stderr instanceof DeferredCloseInputStream)
-                            ((DeferredCloseInputStream) stderr)
-                                .closeDeferred(stderr);
-                    } catch (IOException e) {
-                        // ignore
-                    }
-                }
-                break;
-
-            default: throw new AssertionError("Unsupported platform: " + platform);
-        }
-    }
-
-    public void destroy() {
-        destroy(false);
-    }
-
-    @Override
-    public Process destroyForcibly() {
-        destroy(true);
-        return this;
-    }
-
-    @Override
-    public long getPid() {
-        return pid;
-    }
-
-    @Override
-    public synchronized boolean isAlive() {
-        return !hasExited;
-    }
-
-    private static native void init();
-
-    static {
-        init();
-    }
-
-    /**
-     * A buffered input stream for a subprocess pipe file descriptor
-     * that allows the underlying file descriptor to be reclaimed when
-     * the process exits, via the processExited hook.
-     *
-     * This is tricky because we do not want the user-level InputStream to be
-     * closed until the user invokes close(), and we need to continue to be
-     * able to read any buffered data lingering in the OS pipe buffer.
-     */
-    private static class ProcessPipeInputStream extends BufferedInputStream {
-        private final Object closeLock = new Object();
-
-        ProcessPipeInputStream(int fd) {
-            super(new FileInputStream(newFileDescriptor(fd)));
-        }
-        private static byte[] drainInputStream(InputStream in)
-                throws IOException {
-            int n = 0;
-            int j;
-            byte[] a = null;
-            while ((j = in.available()) > 0) {
-                a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
-                n += in.read(a, n, j);
-            }
-            return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
-        }
-
-        /** Called by the process reaper thread when the process exits. */
-        synchronized void processExited() {
-            synchronized (closeLock) {
-                try {
-                    InputStream in = this.in;
-                    // this stream is closed if and only if: in == null
-                    if (in != null) {
-                        byte[] stragglers = drainInputStream(in);
-                        in.close();
-                        this.in = (stragglers == null) ?
-                            ProcessBuilder.NullInputStream.INSTANCE :
-                            new ByteArrayInputStream(stragglers);
-                    }
-                } catch (IOException ignored) {}
-            }
-        }
-
-        @Override
-        public void close() throws IOException {
-            // BufferedInputStream#close() is not synchronized unlike most other
-            // methods. Synchronizing helps avoid race with processExited().
-            synchronized (closeLock) {
-                super.close();
-            }
-        }
-    }
-
-    /**
-     * A buffered output stream for a subprocess pipe file descriptor
-     * that allows the underlying file descriptor to be reclaimed when
-     * the process exits, via the processExited hook.
-     */
-    private static class ProcessPipeOutputStream extends BufferedOutputStream {
-        ProcessPipeOutputStream(int fd) {
-            super(new FileOutputStream(newFileDescriptor(fd)));
-        }
-
-        /** Called by the process reaper thread when the process exits. */
-        synchronized void processExited() {
-            OutputStream out = this.out;
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException ignored) {
-                    // We know of no reason to get an IOException, but if
-                    // we do, there's nothing else to do but carry on.
-                }
-                this.out = ProcessBuilder.NullOutputStream.INSTANCE;
-            }
-        }
-    }
-
-    // A FileInputStream that supports the deferment of the actual close
-    // operation until the last pending I/O operation on the stream has
-    // finished.  This is required on Solaris because we must close the stdin
-    // and stdout streams in the destroy method in order to reclaim the
-    // underlying file descriptors.  Doing so, however, causes any thread
-    // currently blocked in a read on one of those streams to receive an
-    // IOException("Bad file number"), which is incompatible with historical
-    // behavior.  By deferring the close we allow any pending reads to see -1
-    // (EOF) as they did before.
-    //
-    private static class DeferredCloseInputStream extends FileInputStream
-    {
-        DeferredCloseInputStream(FileDescriptor fd) {
-            super(fd);
-        }
-
-        private Object lock = new Object();     // For the following fields
-        private boolean closePending = false;
-        private int useCount = 0;
-        private InputStream streamToClose;
-
-        private void raise() {
-            synchronized (lock) {
-                useCount++;
-            }
-        }
-
-        private void lower() throws IOException {
-            synchronized (lock) {
-                useCount--;
-                if (useCount == 0 && closePending) {
-                    streamToClose.close();
-                }
-            }
-        }
-
-        // stc is the actual stream to be closed; it might be this object, or
-        // it might be an upstream object for which this object is downstream.
-        //
-        private void closeDeferred(InputStream stc) throws IOException {
-            synchronized (lock) {
-                if (useCount == 0) {
-                    stc.close();
-                } else {
-                    closePending = true;
-                    streamToClose = stc;
-                }
-            }
-        }
-
-        public void close() throws IOException {
-            synchronized (lock) {
-                useCount = 0;
-                closePending = false;
-            }
-            super.close();
-        }
-
-        public int read() throws IOException {
-            raise();
-            try {
-                return super.read();
-            } finally {
-                lower();
-            }
-        }
-
-        public int read(byte[] b) throws IOException {
-            raise();
-            try {
-                return super.read(b);
-            } finally {
-                lower();
-            }
-        }
-
-        public int read(byte[] b, int off, int len) throws IOException {
-            raise();
-            try {
-                return super.read(b, off, len);
-            } finally {
-                lower();
-            }
-        }
-
-        public long skip(long n) throws IOException {
-            raise();
-            try {
-                return super.skip(n);
-            } finally {
-                lower();
-            }
-        }
-
-        public int available() throws IOException {
-            raise();
-            try {
-                return super.available();
-            } finally {
-                lower();
-            }
-        }
-    }
-
-    /**
-     * A buffered input stream for a subprocess pipe file descriptor
-     * that allows the underlying file descriptor to be reclaimed when
-     * the process exits, via the processExited hook.
-     *
-     * This is tricky because we do not want the user-level InputStream to be
-     * closed until the user invokes close(), and we need to continue to be
-     * able to read any buffered data lingering in the OS pipe buffer.
-     *
-     * On AIX this is especially tricky, because the 'close()' system call
-     * will block if another thread is at the same time blocked in a file
-     * operation (e.g. 'read()') on the same file descriptor. We therefore
-     * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
-     * with the DeferredCloseInputStream approach used on Solaris. This means
-     * that every potentially blocking operation on the file descriptor
-     * increments a counter before it is executed and decrements it once it
-     * finishes. The 'close()' operation will only be executed if there are
-     * no pending operations. Otherwise it is deferred after the last pending
-     * operation has finished.
-     *
-     */
-    private static class DeferredCloseProcessPipeInputStream
-        extends BufferedInputStream {
-
-        private final Object closeLock = new Object();
-        private int useCount = 0;
-        private boolean closePending = false;
-
-        DeferredCloseProcessPipeInputStream(int fd) {
-            super(new FileInputStream(newFileDescriptor(fd)));
-        }
-
-        private InputStream drainInputStream(InputStream in)
-                throws IOException {
-            int n = 0;
-            int j;
-            byte[] a = null;
-            synchronized (closeLock) {
-                if (buf == null) // asynchronous close()?
-                    return null; // discard
-                j = in.available();
-            }
-            while (j > 0) {
-                a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
-                synchronized (closeLock) {
-                    if (buf == null) // asynchronous close()?
-                        return null; // discard
-                    n += in.read(a, n, j);
-                    j = in.available();
-                }
-            }
-            return (a == null) ?
-                    ProcessBuilder.NullInputStream.INSTANCE :
-                    new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
-        }
-
-        /** Called by the process reaper thread when the process exits. */
-        synchronized void processExited() {
-            try {
-                InputStream in = this.in;
-                if (in != null) {
-                    InputStream stragglers = drainInputStream(in);
-                    in.close();
-                    this.in = stragglers;
-                }
-            } catch (IOException ignored) { }
-        }
-
-        private void raise() {
-            synchronized (closeLock) {
-                useCount++;
-            }
-        }
-
-        private void lower() throws IOException {
-            synchronized (closeLock) {
-                useCount--;
-                if (useCount == 0 && closePending) {
-                    closePending = false;
-                    super.close();
-                }
-            }
-        }
-
-        @Override
-        public int read() throws IOException {
-            raise();
-            try {
-                return super.read();
-            } finally {
-                lower();
-            }
-        }
-
-        @Override
-        public int read(byte[] b) throws IOException {
-            raise();
-            try {
-                return super.read(b);
-            } finally {
-                lower();
-            }
-        }
-
-        @Override
-        public int read(byte[] b, int off, int len) throws IOException {
-            raise();
-            try {
-                return super.read(b, off, len);
-            } finally {
-                lower();
-            }
-        }
-
-        @Override
-        public long skip(long n) throws IOException {
-            raise();
-            try {
-                return super.skip(n);
-            } finally {
-                lower();
-            }
-        }
-
-        @Override
-        public int available() throws IOException {
-            raise();
-            try {
-                return super.available();
-            } finally {
-                lower();
-            }
-        }
-
-        @Override
-        public void close() throws IOException {
-            // BufferedInputStream#close() is not synchronized unlike most other
-            // methods. Synchronizing helps avoid racing with drainInputStream().
-            synchronized (closeLock) {
-                if (useCount == 0) {
-                    super.close();
-                }
-                else {
-                    closePending = true;
-                }
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 1995, 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.
+ */
+
+#undef  _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE 1
+
+#include "jni.h"
+#include "jvm.h"
+#include "jvm_md.h"
+#include "jni_util.h"
+#include "io_util.h"
+
+/*
+ * Platform-specific support for java.lang.Process
+ */
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <string.h>
+
+#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
+#include <spawn.h>
+#endif
+
+#include "childproc.h"
+
+/*
+ * There are 4 possible strategies we might use to "fork":
+ *
+ * - fork(2).  Very portable and reliable but subject to
+ *   failure due to overcommit (see the documentation on
+ *   /proc/sys/vm/overcommit_memory in Linux proc(5)).
+ *   This is the ancient problem of spurious failure whenever a large
+ *   process starts a small subprocess.
+ *
+ * - vfork().  Using this is scary because all relevant man pages
+ *   contain dire warnings, e.g. Linux vfork(2).  But at least it's
+ *   documented in the glibc docs and is standardized by XPG4.
+ *   http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
+ *   On Linux, one might think that vfork() would be implemented using
+ *   the clone system call with flag CLONE_VFORK, but in fact vfork is
+ *   a separate system call (which is a good sign, suggesting that
+ *   vfork will continue to be supported at least on Linux).
+ *   Another good sign is that glibc implements posix_spawn using
+ *   vfork whenever possible.  Note that we cannot use posix_spawn
+ *   ourselves because there's no reliable way to close all inherited
+ *   file descriptors.
+ *
+ * - clone() with flags CLONE_VM but not CLONE_THREAD.  clone() is
+ *   Linux-specific, but this ought to work - at least the glibc
+ *   sources contain code to handle different combinations of CLONE_VM
+ *   and CLONE_THREAD.  However, when this was implemented, it
+ *   appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
+ *   the simple program
+ *     Runtime.getRuntime().exec("/bin/true").waitFor();
+ *   with:
+ *     #  Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
+ *     #  Error: pthread_getattr_np failed with errno = 3 (ESRCH)
+ *   We believe this is a glibc bug, reported here:
+ *     http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
+ *   but the glibc maintainers closed it as WONTFIX.
+ *
+ * - posix_spawn(). While posix_spawn() is a fairly elaborate and
+ *   complicated system call, it can't quite do everything that the old
+ *   fork()/exec() combination can do, so the only feasible way to do
+ *   this, is to use posix_spawn to launch a new helper executable
+ *   "jprochelper", which in turn execs the target (after cleaning
+ *   up file-descriptors etc.) The end result is the same as before,
+ *   a child process linked to the parent in the same way, but it
+ *   avoids the problem of duplicating the parent (VM) process
+ *   address space temporarily, before launching the target command.
+ *
+ * Based on the above analysis, we are currently using vfork() on
+ * Linux and spawn() on other Unix systems, but the code to use clone()
+ * and fork() remains.
+ */
+
+
+static void
+setSIGCHLDHandler(JNIEnv *env)
+{
+    /* There is a subtle difference between having the signal handler
+     * for SIGCHLD be SIG_DFL and SIG_IGN.  We cannot obtain process
+     * termination information for child processes if the signal
+     * handler is SIG_IGN.  It must be SIG_DFL.
+     *
+     * We used to set the SIGCHLD handler only on Linux, but it's
+     * safest to set it unconditionally.
+     *
+     * Consider what happens if java's parent process sets the SIGCHLD
+     * handler to SIG_IGN.  Normally signal handlers are inherited by
+     * children, but SIGCHLD is a controversial case.  Solaris appears
+     * to always reset it to SIG_DFL, but this behavior may be
+     * non-standard-compliant, and we shouldn't rely on it.
+     *
+     * References:
+     * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
+     * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
+     */
+    struct sigaction sa;
+    sa.sa_handler = SIG_DFL;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+    if (sigaction(SIGCHLD, &sa, NULL) < 0)
+        JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
+}
+
+static void*
+xmalloc(JNIEnv *env, size_t size)
+{
+    void *p = malloc(size);
+    if (p == NULL)
+        JNU_ThrowOutOfMemoryError(env, NULL);
+    return p;
+}
+
+#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
+
+/**
+ * If PATH is not defined, the OS provides some default value.
+ * Unfortunately, there's no portable way to get this value.
+ * Fortunately, it's only needed if the child has PATH while we do not.
+ */
+static const char*
+defaultPath(void)
+{
+#ifdef __solaris__
+    /* These really are the Solaris defaults! */
+    return (geteuid() == 0 || getuid() == 0) ?
+        "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
+        "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
+#else
+    return ":/bin:/usr/bin";    /* glibc */
+#endif
+}
+
+static const char*
+effectivePath(void)
+{
+    const char *s = getenv("PATH");
+    return (s != NULL) ? s : defaultPath();
+}
+
+static int
+countOccurrences(const char *s, char c)
+{
+    int count;
+    for (count = 0; *s != '\0'; s++)
+        count += (*s == c);
+    return count;
+}
+
+static const char * const *
+effectivePathv(JNIEnv *env)
+{
+    char *p;
+    int i;
+    const char *path = effectivePath();
+    int count = countOccurrences(path, ':') + 1;
+    size_t pathvsize = sizeof(const char *) * (count+1);
+    size_t pathsize = strlen(path) + 1;
+    const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
+
+    if (pathv == NULL)
+        return NULL;
+    p = (char *) pathv + pathvsize;
+    memcpy(p, path, pathsize);
+    /* split PATH by replacing ':' with NULs; empty components => "." */
+    for (i = 0; i < count; i++) {
+        char *q = p + strcspn(p, ":");
+        pathv[i] = (p == q) ? "." : p;
+        *q = '\0';
+        p = q + 1;
+    }
+    pathv[count] = NULL;
+    return pathv;
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
+{
+    parentPathv = effectivePathv(env);
+    CHECK_NULL(parentPathv);
+    setSIGCHLDHandler(env);
+}
+
+
+#ifndef WIFEXITED
+#define WIFEXITED(status) (((status)&0xFF) == 0)
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status) (((status)>>8)&0xFF)
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
+#endif
+
+#ifndef WTERMSIG
+#define WTERMSIG(status) ((status)&0x7F)
+#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;
+        }
+    }
+
+    if (WIFEXITED(status)) {
+        /*
+         * The child exited normally; get its exit code.
+         */
+        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
+    } else {
+        /*
+         * Unknown exit code; pass it through.
+         */
+        return status;
+    }
+}
+
+static const char *
+getBytes(JNIEnv *env, jbyteArray arr)
+{
+    return arr == NULL ? NULL :
+        (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
+}
+
+static void
+releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
+{
+    if (parr != NULL)
+        (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
+}
+
+static void
+throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
+{
+    static const char * const format = "error=%d, %s";
+    const char *detail = defaultDetail;
+    char *errmsg;
+    jstring s;
+
+    if (errnum != 0) {
+        const char *s = strerror(errnum);
+        if (strcmp(s, "Unknown error") != 0)
+            detail = s;
+    }
+    /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
+    errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
+    if (errmsg == NULL)
+        return;
+
+    sprintf(errmsg, format, errnum, detail);
+    s = JNU_NewStringPlatform(env, errmsg);
+    if (s != NULL) {
+        jobject x = JNU_NewObjectByName(env, "java/io/IOException",
+                                        "(Ljava/lang/String;)V", s);
+        if (x != NULL)
+            (*env)->Throw(env, x);
+    }
+    free(errmsg);
+}
+
+#ifdef DEBUG_PROCESS
+/* Debugging process code is difficult; where to write debug output? */
+static void
+debugPrint(char *format, ...)
+{
+    FILE *tty = fopen("/dev/tty", "w");
+    va_list ap;
+    va_start(ap, format);
+    vfprintf(tty, format, ap);
+    va_end(ap);
+    fclose(tty);
+}
+#endif /* DEBUG_PROCESS */
+
+static void
+copyPipe(int from[2], int to[2])
+{
+    to[0] = from[0];
+    to[1] = from[1];
+}
+
+/* arg is an array of pointers to 0 terminated strings. array is terminated
+ * by a null element.
+ *
+ * *nelems and *nbytes receive the number of elements of array (incl 0)
+ * and total number of bytes (incl. 0)
+ * Note. An empty array will have one null element
+ * But if arg is null, then *nelems set to 0, and *nbytes to 0
+ */
+static void arraysize(const char * const *arg, int *nelems, int *nbytes)
+{
+    int i, bytes, count;
+    const char * const *a = arg;
+    char *p;
+    int *q;
+    if (arg == 0) {
+        *nelems = 0;
+        *nbytes = 0;
+        return;
+    }
+    /* count the array elements and number of bytes */
+    for (count=0, bytes=0; *a != 0; count++, a++) {
+        bytes += strlen(*a)+1;
+    }
+    *nbytes = bytes;
+    *nelems = count+1;
+}
+
+/* copy the strings from arg[] into buf, starting at given offset
+ * return new offset to next free byte
+ */
+static int copystrings(char *buf, int offset, const char * const *arg) {
+    char *p;
+    const char * const *a;
+    int count=0;
+
+    if (arg == 0) {
+        return offset;
+    }
+    for (p=buf+offset, a=arg; *a != 0; a++) {
+        int len = strlen(*a) +1;
+        memcpy(p, *a, len);
+        p += len;
+        count += len;
+    }
+    return offset+count;
+}
+
+/**
+ * We are unusually paranoid; use of clone/vfork is
+ * especially likely to tickle gcc/glibc bugs.
+ */
+#ifdef __attribute_noinline__  /* See: sys/cdefs.h */
+__attribute_noinline__
+#endif
+
+#define START_CHILD_USE_CLONE 0  /* clone() currently disabled; see above. */
+
+#ifdef START_CHILD_USE_CLONE
+static pid_t
+cloneChild(ChildStuff *c) {
+#ifdef __linux__
+#define START_CHILD_CLONE_STACK_SIZE (64 * 1024)
+    /*
+     * See clone(2).
+     * Instead of worrying about which direction the stack grows, just
+     * allocate twice as much and start the stack in the middle.
+     */
+    if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL)
+        /* errno will be set to ENOMEM */
+        return -1;
+    return clone(childProcess,
+                 c->clone_stack + START_CHILD_CLONE_STACK_SIZE,
+                 CLONE_VFORK | CLONE_VM | SIGCHLD, c);
+#else
+/* not available on Solaris / Mac */
+    assert(0);
+    return -1;
+#endif
+}
+#endif
+
+static pid_t
+vforkChild(ChildStuff *c) {
+    volatile pid_t resultPid;
+
+    /*
+     * We separate the call to vfork into a separate function to make
+     * very sure to keep stack of child from corrupting stack of parent,
+     * as suggested by the scary gcc warning:
+     *  warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
+     */
+    resultPid = vfork();
+
+    if (resultPid == 0) {
+        childProcess(c);
+    }
+    assert(resultPid != 0);  /* childProcess never returns */
+    return resultPid;
+}
+
+static pid_t
+forkChild(ChildStuff *c) {
+    pid_t resultPid;
+
+    /*
+     * From Solaris fork(2): In Solaris 10, a call to fork() is
+     * identical to a call to fork1(); only the calling thread is
+     * replicated in the child process. This is the POSIX-specified
+     * behavior for fork().
+     */
+    resultPid = fork();
+
+    if (resultPid == 0) {
+        childProcess(c);
+    }
+    assert(resultPid != 0);  /* childProcess never returns */
+    return resultPid;
+}
+
+#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
+static pid_t
+spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
+    pid_t resultPid;
+    jboolean isCopy;
+    int i, offset, rval, bufsize, magic;
+    char *buf, buf1[16];
+    char *hlpargs[2];
+    SpawnInfo sp;
+
+    /* need to tell helper which fd is for receiving the childstuff
+     * and which fd to send response back on
+     */
+    snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]);
+    /* put the fd string as argument to the helper cmd */
+    hlpargs[0] = buf1;
+    hlpargs[1] = 0;
+
+    /* Following items are sent down the pipe to the helper
+     * after it is spawned.
+     * All strings are null terminated. All arrays of strings
+     * have an empty string for termination.
+     * - the ChildStuff struct
+     * - the SpawnInfo struct
+     * - the argv strings array
+     * - the envv strings array
+     * - the home directory string
+     * - the parentPath string
+     * - the parentPathv array
+     */
+    /* First calculate the sizes */
+    arraysize(c->argv, &sp.nargv, &sp.argvBytes);
+    bufsize = sp.argvBytes;
+    arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
+    bufsize += sp.envvBytes;
+    sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
+    bufsize += sp.dirlen;
+    arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
+    bufsize += sp.parentPathvBytes;
+    /* We need to clear FD_CLOEXEC if set in the fds[].
+     * Files are created FD_CLOEXEC in Java.
+     * Otherwise, they will be closed when the target gets exec'd */
+    for (i=0; i<3; i++) {
+        if (c->fds[i] != -1) {
+            int flags = fcntl(c->fds[i], F_GETFD);
+            if (flags & FD_CLOEXEC) {
+                fcntl(c->fds[i], F_SETFD, flags & (~1));
+            }
+        }
+    }
+
+    rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
+
+    if (rval != 0) {
+        return -1;
+    }
+
+    /* now the lengths are known, copy the data */
+    buf = NEW(char, bufsize);
+    if (buf == 0) {
+        return -1;
+    }
+    offset = copystrings(buf, 0, &c->argv[0]);
+    offset = copystrings(buf, offset, &c->envv[0]);
+    memcpy(buf+offset, c->pdir, sp.dirlen);
+    offset += sp.dirlen;
+    offset = copystrings(buf, offset, parentPathv);
+    assert(offset == bufsize);
+
+    magic = magicNumber();
+
+    /* write the two structs and the data buffer */
+    write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
+    write(c->childenv[1], (char *)c, sizeof(*c));
+    write(c->childenv[1], (char *)&sp, sizeof(sp));
+    write(c->childenv[1], buf, bufsize);
+    free(buf);
+
+    /* In this mode an external main() in invoked which calls back into
+     * childProcess() in this file, rather than directly
+     * via the statement below */
+    return resultPid;
+}
+#endif
+
+/*
+ * Start a child process running function childProcess.
+ * This function only returns in the parent.
+ */
+static pid_t
+startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
+    switch (c->mode) {
+      case MODE_VFORK:
+        return vforkChild(c);
+      case MODE_FORK:
+        return forkChild(c);
+#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
+      case MODE_POSIX_SPAWN:
+        return spawnChild(env, process, c, helperpath);
+#endif
+      default:
+        return -1;
+    }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
+                                       jobject process,
+                                       jint mode,
+                                       jbyteArray helperpath,
+                                       jbyteArray prog,
+                                       jbyteArray argBlock, jint argc,
+                                       jbyteArray envBlock, jint envc,
+                                       jbyteArray dir,
+                                       jintArray std_fds,
+                                       jboolean redirectErrorStream)
+{
+    int errnum;
+    int resultPid = -1;
+    int in[2], out[2], err[2], fail[2], childenv[2];
+    jint *fds = NULL;
+    const char *phelperpath = NULL;
+    const char *pprog = NULL;
+    const char *pargBlock = NULL;
+    const char *penvBlock = NULL;
+    ChildStuff *c;
+
+    in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
+    childenv[0] = childenv[1] = -1;
+
+    if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
+    c->argv = NULL;
+    c->envv = NULL;
+    c->pdir = NULL;
+    c->clone_stack = NULL;
+
+    /* Convert prog + argBlock into a char ** argv.
+     * Add one word room for expansion of argv for use by
+     * execve_as_traditional_shell_script.
+     * This word is also used when using spawn mode
+     */
+    assert(prog != NULL && argBlock != NULL);
+    if ((phelperpath = getBytes(env, helperpath))   == NULL) goto Catch;
+    if ((pprog       = getBytes(env, prog))         == NULL) goto Catch;
+    if ((pargBlock   = getBytes(env, argBlock))     == NULL) goto Catch;
+    if ((c->argv     = NEW(const char *, argc + 3)) == NULL) goto Catch;
+    c->argv[0] = pprog;
+    c->argc = argc + 2;
+    initVectorFromBlock(c->argv+1, pargBlock, argc);
+
+    if (envBlock != NULL) {
+        /* Convert envBlock into a char ** envv */
+        if ((penvBlock = getBytes(env, envBlock))   == NULL) goto Catch;
+        if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
+        initVectorFromBlock(c->envv, penvBlock, envc);
+    }
+
+    if (dir != NULL) {
+        if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
+    }
+
+    assert(std_fds != NULL);
+    fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
+    if (fds == NULL) goto Catch;
+
+    if ((fds[0] == -1 && pipe(in)  < 0) ||
+        (fds[1] == -1 && pipe(out) < 0) ||
+        (fds[2] == -1 && pipe(err) < 0) ||
+        (pipe(childenv) < 0) ||
+        (pipe(fail) < 0)) {
+        throwIOException(env, errno, "Bad file descriptor");
+        goto Catch;
+    }
+    c->fds[0] = fds[0];
+    c->fds[1] = fds[1];
+    c->fds[2] = fds[2];
+
+    copyPipe(in,   c->in);
+    copyPipe(out,  c->out);
+    copyPipe(err,  c->err);
+    copyPipe(fail, c->fail);
+    copyPipe(childenv, c->childenv);
+
+    c->redirectErrorStream = redirectErrorStream;
+    c->mode = mode;
+
+    resultPid = startChild(env, process, c, phelperpath);
+    assert(resultPid != 0);
+
+    if (resultPid < 0) {
+        switch (c->mode) {
+          case MODE_VFORK:
+            throwIOException(env, errno, "vfork failed");
+            break;
+          case MODE_FORK:
+            throwIOException(env, errno, "fork failed");
+            break;
+          case MODE_POSIX_SPAWN:
+            throwIOException(env, errno, "spawn failed");
+            break;
+        }
+        goto Catch;
+    }
+    close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec  (childproc.c)  */
+
+    switch (readFully(fail[0], &errnum, sizeof(errnum))) {
+    case 0: break; /* Exec succeeded */
+    case sizeof(errnum):
+        waitpid(resultPid, NULL, 0);
+        throwIOException(env, errnum, "Exec failed");
+        goto Catch;
+    default:
+        throwIOException(env, errno, "Read failed");
+        goto Catch;
+    }
+
+    fds[0] = (in [1] != -1) ? in [1] : -1;
+    fds[1] = (out[0] != -1) ? out[0] : -1;
+    fds[2] = (err[0] != -1) ? err[0] : -1;
+
+ Finally:
+    free(c->clone_stack);
+
+    /* Always clean up the child's side of the pipes */
+    closeSafely(in [0]);
+    closeSafely(out[1]);
+    closeSafely(err[1]);
+
+    /* Always clean up fail and childEnv descriptors */
+    closeSafely(fail[0]);
+    closeSafely(fail[1]);
+    closeSafely(childenv[0]);
+    closeSafely(childenv[1]);
+
+    releaseBytes(env, helperpath, phelperpath);
+    releaseBytes(env, prog,       pprog);
+    releaseBytes(env, argBlock,   pargBlock);
+    releaseBytes(env, envBlock,   penvBlock);
+    releaseBytes(env, dir,        c->pdir);
+
+    free(c->argv);
+    free(c->envv);
+    free(c);
+
+    if (fds != NULL)
+        (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
+
+    return resultPid;
+
+ Catch:
+    /* Clean up the parent's side of the pipes in case of failure only */
+    closeSafely(in [1]); in[1] = -1;
+    closeSafely(out[0]); out[0] = -1;
+    closeSafely(err[0]); err[0] = -1;
+    goto Finally;
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessImpl_destroyProcess(JNIEnv *env,
+                                          jobject junk,
+                                          jint pid,
+                                          jboolean force)
+{
+    int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM;
+    kill(pid, sig);
+}
--- a/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-/*
- * Copyright (c) 1995, 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.
- */
-
-#undef  _LARGEFILE64_SOURCE
-#define _LARGEFILE64_SOURCE 1
-
-#include "jni.h"
-#include "jvm.h"
-#include "jvm_md.h"
-#include "jni_util.h"
-#include "io_util.h"
-
-/*
- * Platform-specific support for java.lang.Process
- */
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <string.h>
-
-#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
-#include <spawn.h>
-#endif
-
-#include "childproc.h"
-
-/*
- * There are 4 possible strategies we might use to "fork":
- *
- * - fork(2).  Very portable and reliable but subject to
- *   failure due to overcommit (see the documentation on
- *   /proc/sys/vm/overcommit_memory in Linux proc(5)).
- *   This is the ancient problem of spurious failure whenever a large
- *   process starts a small subprocess.
- *
- * - vfork().  Using this is scary because all relevant man pages
- *   contain dire warnings, e.g. Linux vfork(2).  But at least it's
- *   documented in the glibc docs and is standardized by XPG4.
- *   http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
- *   On Linux, one might think that vfork() would be implemented using
- *   the clone system call with flag CLONE_VFORK, but in fact vfork is
- *   a separate system call (which is a good sign, suggesting that
- *   vfork will continue to be supported at least on Linux).
- *   Another good sign is that glibc implements posix_spawn using
- *   vfork whenever possible.  Note that we cannot use posix_spawn
- *   ourselves because there's no reliable way to close all inherited
- *   file descriptors.
- *
- * - clone() with flags CLONE_VM but not CLONE_THREAD.  clone() is
- *   Linux-specific, but this ought to work - at least the glibc
- *   sources contain code to handle different combinations of CLONE_VM
- *   and CLONE_THREAD.  However, when this was implemented, it
- *   appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
- *   the simple program
- *     Runtime.getRuntime().exec("/bin/true").waitFor();
- *   with:
- *     #  Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
- *     #  Error: pthread_getattr_np failed with errno = 3 (ESRCH)
- *   We believe this is a glibc bug, reported here:
- *     http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
- *   but the glibc maintainers closed it as WONTFIX.
- *
- * - posix_spawn(). While posix_spawn() is a fairly elaborate and
- *   complicated system call, it can't quite do everything that the old
- *   fork()/exec() combination can do, so the only feasible way to do
- *   this, is to use posix_spawn to launch a new helper executable
- *   "jprochelper", which in turn execs the target (after cleaning
- *   up file-descriptors etc.) The end result is the same as before,
- *   a child process linked to the parent in the same way, but it
- *   avoids the problem of duplicating the parent (VM) process
- *   address space temporarily, before launching the target command.
- *
- * Based on the above analysis, we are currently using vfork() on
- * Linux and spawn() on other Unix systems, but the code to use clone()
- * and fork() remains.
- */
-
-
-static void
-setSIGCHLDHandler(JNIEnv *env)
-{
-    /* There is a subtle difference between having the signal handler
-     * for SIGCHLD be SIG_DFL and SIG_IGN.  We cannot obtain process
-     * termination information for child processes if the signal
-     * handler is SIG_IGN.  It must be SIG_DFL.
-     *
-     * We used to set the SIGCHLD handler only on Linux, but it's
-     * safest to set it unconditionally.
-     *
-     * Consider what happens if java's parent process sets the SIGCHLD
-     * handler to SIG_IGN.  Normally signal handlers are inherited by
-     * children, but SIGCHLD is a controversial case.  Solaris appears
-     * to always reset it to SIG_DFL, but this behavior may be
-     * non-standard-compliant, and we shouldn't rely on it.
-     *
-     * References:
-     * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
-     * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
-     */
-    struct sigaction sa;
-    sa.sa_handler = SIG_DFL;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
-    if (sigaction(SIGCHLD, &sa, NULL) < 0)
-        JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
-}
-
-static void*
-xmalloc(JNIEnv *env, size_t size)
-{
-    void *p = malloc(size);
-    if (p == NULL)
-        JNU_ThrowOutOfMemoryError(env, NULL);
-    return p;
-}
-
-#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
-
-/**
- * If PATH is not defined, the OS provides some default value.
- * Unfortunately, there's no portable way to get this value.
- * Fortunately, it's only needed if the child has PATH while we do not.
- */
-static const char*
-defaultPath(void)
-{
-#ifdef __solaris__
-    /* These really are the Solaris defaults! */
-    return (geteuid() == 0 || getuid() == 0) ?
-        "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
-        "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
-#else
-    return ":/bin:/usr/bin";    /* glibc */
-#endif
-}
-
-static const char*
-effectivePath(void)
-{
-    const char *s = getenv("PATH");
-    return (s != NULL) ? s : defaultPath();
-}
-
-static int
-countOccurrences(const char *s, char c)
-{
-    int count;
-    for (count = 0; *s != '\0'; s++)
-        count += (*s == c);
-    return count;
-}
-
-static const char * const *
-effectivePathv(JNIEnv *env)
-{
-    char *p;
-    int i;
-    const char *path = effectivePath();
-    int count = countOccurrences(path, ':') + 1;
-    size_t pathvsize = sizeof(const char *) * (count+1);
-    size_t pathsize = strlen(path) + 1;
-    const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
-
-    if (pathv == NULL)
-        return NULL;
-    p = (char *) pathv + pathvsize;
-    memcpy(p, path, pathsize);
-    /* split PATH by replacing ':' with NULs; empty components => "." */
-    for (i = 0; i < count; i++) {
-        char *q = p + strcspn(p, ":");
-        pathv[i] = (p == q) ? "." : p;
-        *q = '\0';
-        p = q + 1;
-    }
-    pathv[count] = NULL;
-    return pathv;
-}
-
-JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
-{
-    parentPathv = effectivePathv(env);
-    CHECK_NULL(parentPathv);
-    setSIGCHLDHandler(env);
-}
-
-
-#ifndef WIFEXITED
-#define WIFEXITED(status) (((status)&0xFF) == 0)
-#endif
-
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status) (((status)>>8)&0xFF)
-#endif
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
-#endif
-
-#ifndef WTERMSIG
-#define WTERMSIG(status) ((status)&0x7F)
-#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_UNIXProcess_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;
-        }
-    }
-
-    if (WIFEXITED(status)) {
-        /*
-         * The child exited normally; get its exit code.
-         */
-        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
-    } else {
-        /*
-         * Unknown exit code; pass it through.
-         */
-        return status;
-    }
-}
-
-static const char *
-getBytes(JNIEnv *env, jbyteArray arr)
-{
-    return arr == NULL ? NULL :
-        (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
-}
-
-static void
-releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
-{
-    if (parr != NULL)
-        (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
-}
-
-static void
-throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
-{
-    static const char * const format = "error=%d, %s";
-    const char *detail = defaultDetail;
-    char *errmsg;
-    jstring s;
-
-    if (errnum != 0) {
-        const char *s = strerror(errnum);
-        if (strcmp(s, "Unknown error") != 0)
-            detail = s;
-    }
-    /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
-    errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
-    if (errmsg == NULL)
-        return;
-
-    sprintf(errmsg, format, errnum, detail);
-    s = JNU_NewStringPlatform(env, errmsg);
-    if (s != NULL) {
-        jobject x = JNU_NewObjectByName(env, "java/io/IOException",
-                                        "(Ljava/lang/String;)V", s);
-        if (x != NULL)
-            (*env)->Throw(env, x);
-    }
-    free(errmsg);
-}
-
-#ifdef DEBUG_PROCESS
-/* Debugging process code is difficult; where to write debug output? */
-static void
-debugPrint(char *format, ...)
-{
-    FILE *tty = fopen("/dev/tty", "w");
-    va_list ap;
-    va_start(ap, format);
-    vfprintf(tty, format, ap);
-    va_end(ap);
-    fclose(tty);
-}
-#endif /* DEBUG_PROCESS */
-
-static void
-copyPipe(int from[2], int to[2])
-{
-    to[0] = from[0];
-    to[1] = from[1];
-}
-
-/* arg is an array of pointers to 0 terminated strings. array is terminated
- * by a null element.
- *
- * *nelems and *nbytes receive the number of elements of array (incl 0)
- * and total number of bytes (incl. 0)
- * Note. An empty array will have one null element
- * But if arg is null, then *nelems set to 0, and *nbytes to 0
- */
-static void arraysize(const char * const *arg, int *nelems, int *nbytes)
-{
-    int i, bytes, count;
-    const char * const *a = arg;
-    char *p;
-    int *q;
-    if (arg == 0) {
-        *nelems = 0;
-        *nbytes = 0;
-        return;
-    }
-    /* count the array elements and number of bytes */
-    for (count=0, bytes=0; *a != 0; count++, a++) {
-        bytes += strlen(*a)+1;
-    }
-    *nbytes = bytes;
-    *nelems = count+1;
-}
-
-/* copy the strings from arg[] into buf, starting at given offset
- * return new offset to next free byte
- */
-static int copystrings(char *buf, int offset, const char * const *arg) {
-    char *p;
-    const char * const *a;
-    int count=0;
-
-    if (arg == 0) {
-        return offset;
-    }
-    for (p=buf+offset, a=arg; *a != 0; a++) {
-        int len = strlen(*a) +1;
-        memcpy(p, *a, len);
-        p += len;
-        count += len;
-    }
-    return offset+count;
-}
-
-/**
- * We are unusually paranoid; use of clone/vfork is
- * especially likely to tickle gcc/glibc bugs.
- */
-#ifdef __attribute_noinline__  /* See: sys/cdefs.h */
-__attribute_noinline__
-#endif
-
-#define START_CHILD_USE_CLONE 0  /* clone() currently disabled; see above. */
-
-#ifdef START_CHILD_USE_CLONE
-static pid_t
-cloneChild(ChildStuff *c) {
-#ifdef __linux__
-#define START_CHILD_CLONE_STACK_SIZE (64 * 1024)
-    /*
-     * See clone(2).
-     * Instead of worrying about which direction the stack grows, just
-     * allocate twice as much and start the stack in the middle.
-     */
-    if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL)
-        /* errno will be set to ENOMEM */
-        return -1;
-    return clone(childProcess,
-                 c->clone_stack + START_CHILD_CLONE_STACK_SIZE,
-                 CLONE_VFORK | CLONE_VM | SIGCHLD, c);
-#else
-/* not available on Solaris / Mac */
-    assert(0);
-    return -1;
-#endif
-}
-#endif
-
-static pid_t
-vforkChild(ChildStuff *c) {
-    volatile pid_t resultPid;
-
-    /*
-     * We separate the call to vfork into a separate function to make
-     * very sure to keep stack of child from corrupting stack of parent,
-     * as suggested by the scary gcc warning:
-     *  warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
-     */
-    resultPid = vfork();
-
-    if (resultPid == 0) {
-        childProcess(c);
-    }
-    assert(resultPid != 0);  /* childProcess never returns */
-    return resultPid;
-}
-
-static pid_t
-forkChild(ChildStuff *c) {
-    pid_t resultPid;
-
-    /*
-     * From Solaris fork(2): In Solaris 10, a call to fork() is
-     * identical to a call to fork1(); only the calling thread is
-     * replicated in the child process. This is the POSIX-specified
-     * behavior for fork().
-     */
-    resultPid = fork();
-
-    if (resultPid == 0) {
-        childProcess(c);
-    }
-    assert(resultPid != 0);  /* childProcess never returns */
-    return resultPid;
-}
-
-#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
-static pid_t
-spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
-    pid_t resultPid;
-    jboolean isCopy;
-    int i, offset, rval, bufsize, magic;
-    char *buf, buf1[16];
-    char *hlpargs[2];
-    SpawnInfo sp;
-
-    /* need to tell helper which fd is for receiving the childstuff
-     * and which fd to send response back on
-     */
-    snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]);
-    /* put the fd string as argument to the helper cmd */
-    hlpargs[0] = buf1;
-    hlpargs[1] = 0;
-
-    /* Following items are sent down the pipe to the helper
-     * after it is spawned.
-     * All strings are null terminated. All arrays of strings
-     * have an empty string for termination.
-     * - the ChildStuff struct
-     * - the SpawnInfo struct
-     * - the argv strings array
-     * - the envv strings array
-     * - the home directory string
-     * - the parentPath string
-     * - the parentPathv array
-     */
-    /* First calculate the sizes */
-    arraysize(c->argv, &sp.nargv, &sp.argvBytes);
-    bufsize = sp.argvBytes;
-    arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
-    bufsize += sp.envvBytes;
-    sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
-    bufsize += sp.dirlen;
-    arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
-    bufsize += sp.parentPathvBytes;
-    /* We need to clear FD_CLOEXEC if set in the fds[].
-     * Files are created FD_CLOEXEC in Java.
-     * Otherwise, they will be closed when the target gets exec'd */
-    for (i=0; i<3; i++) {
-        if (c->fds[i] != -1) {
-            int flags = fcntl(c->fds[i], F_GETFD);
-            if (flags & FD_CLOEXEC) {
-                fcntl(c->fds[i], F_SETFD, flags & (~1));
-            }
-        }
-    }
-
-    rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
-
-    if (rval != 0) {
-        return -1;
-    }
-
-    /* now the lengths are known, copy the data */
-    buf = NEW(char, bufsize);
-    if (buf == 0) {
-        return -1;
-    }
-    offset = copystrings(buf, 0, &c->argv[0]);
-    offset = copystrings(buf, offset, &c->envv[0]);
-    memcpy(buf+offset, c->pdir, sp.dirlen);
-    offset += sp.dirlen;
-    offset = copystrings(buf, offset, parentPathv);
-    assert(offset == bufsize);
-
-    magic = magicNumber();
-
-    /* write the two structs and the data buffer */
-    write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
-    write(c->childenv[1], (char *)c, sizeof(*c));
-    write(c->childenv[1], (char *)&sp, sizeof(sp));
-    write(c->childenv[1], buf, bufsize);
-    free(buf);
-
-    /* In this mode an external main() in invoked which calls back into
-     * childProcess() in this file, rather than directly
-     * via the statement below */
-    return resultPid;
-}
-#endif
-
-/*
- * Start a child process running function childProcess.
- * This function only returns in the parent.
- */
-static pid_t
-startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
-    switch (c->mode) {
-      case MODE_VFORK:
-        return vforkChild(c);
-      case MODE_FORK:
-        return forkChild(c);
-#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
-      case MODE_POSIX_SPAWN:
-        return spawnChild(env, process, c, helperpath);
-#endif
-      default:
-        return -1;
-    }
-}
-
-JNIEXPORT jint JNICALL
-Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
-                                       jobject process,
-                                       jint mode,
-                                       jbyteArray helperpath,
-                                       jbyteArray prog,
-                                       jbyteArray argBlock, jint argc,
-                                       jbyteArray envBlock, jint envc,
-                                       jbyteArray dir,
-                                       jintArray std_fds,
-                                       jboolean redirectErrorStream)
-{
-    int errnum;
-    int resultPid = -1;
-    int in[2], out[2], err[2], fail[2], childenv[2];
-    jint *fds = NULL;
-    const char *phelperpath = NULL;
-    const char *pprog = NULL;
-    const char *pargBlock = NULL;
-    const char *penvBlock = NULL;
-    ChildStuff *c;
-
-    in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
-    childenv[0] = childenv[1] = -1;
-
-    if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
-    c->argv = NULL;
-    c->envv = NULL;
-    c->pdir = NULL;
-    c->clone_stack = NULL;
-
-    /* Convert prog + argBlock into a char ** argv.
-     * Add one word room for expansion of argv for use by
-     * execve_as_traditional_shell_script.
-     * This word is also used when using spawn mode
-     */
-    assert(prog != NULL && argBlock != NULL);
-    if ((phelperpath = getBytes(env, helperpath))   == NULL) goto Catch;
-    if ((pprog       = getBytes(env, prog))         == NULL) goto Catch;
-    if ((pargBlock   = getBytes(env, argBlock))     == NULL) goto Catch;
-    if ((c->argv     = NEW(const char *, argc + 3)) == NULL) goto Catch;
-    c->argv[0] = pprog;
-    c->argc = argc + 2;
-    initVectorFromBlock(c->argv+1, pargBlock, argc);
-
-    if (envBlock != NULL) {
-        /* Convert envBlock into a char ** envv */
-        if ((penvBlock = getBytes(env, envBlock))   == NULL) goto Catch;
-        if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
-        initVectorFromBlock(c->envv, penvBlock, envc);
-    }
-
-    if (dir != NULL) {
-        if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
-    }
-
-    assert(std_fds != NULL);
-    fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
-    if (fds == NULL) goto Catch;
-
-    if ((fds[0] == -1 && pipe(in)  < 0) ||
-        (fds[1] == -1 && pipe(out) < 0) ||
-        (fds[2] == -1 && pipe(err) < 0) ||
-        (pipe(childenv) < 0) ||
-        (pipe(fail) < 0)) {
-        throwIOException(env, errno, "Bad file descriptor");
-        goto Catch;
-    }
-    c->fds[0] = fds[0];
-    c->fds[1] = fds[1];
-    c->fds[2] = fds[2];
-
-    copyPipe(in,   c->in);
-    copyPipe(out,  c->out);
-    copyPipe(err,  c->err);
-    copyPipe(fail, c->fail);
-    copyPipe(childenv, c->childenv);
-
-    c->redirectErrorStream = redirectErrorStream;
-    c->mode = mode;
-
-    resultPid = startChild(env, process, c, phelperpath);
-    assert(resultPid != 0);
-
-    if (resultPid < 0) {
-        switch (c->mode) {
-          case MODE_VFORK:
-            throwIOException(env, errno, "vfork failed");
-            break;
-          case MODE_FORK:
-            throwIOException(env, errno, "fork failed");
-            break;
-          case MODE_POSIX_SPAWN:
-            throwIOException(env, errno, "spawn failed");
-            break;
-        }
-        goto Catch;
-    }
-    close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec  (childproc.c)  */
-
-    switch (readFully(fail[0], &errnum, sizeof(errnum))) {
-    case 0: break; /* Exec succeeded */
-    case sizeof(errnum):
-        waitpid(resultPid, NULL, 0);
-        throwIOException(env, errnum, "Exec failed");
-        goto Catch;
-    default:
-        throwIOException(env, errno, "Read failed");
-        goto Catch;
-    }
-
-    fds[0] = (in [1] != -1) ? in [1] : -1;
-    fds[1] = (out[0] != -1) ? out[0] : -1;
-    fds[2] = (err[0] != -1) ? err[0] : -1;
-
- Finally:
-    free(c->clone_stack);
-
-    /* Always clean up the child's side of the pipes */
-    closeSafely(in [0]);
-    closeSafely(out[1]);
-    closeSafely(err[1]);
-
-    /* Always clean up fail and childEnv descriptors */
-    closeSafely(fail[0]);
-    closeSafely(fail[1]);
-    closeSafely(childenv[0]);
-    closeSafely(childenv[1]);
-
-    releaseBytes(env, helperpath, phelperpath);
-    releaseBytes(env, prog,       pprog);
-    releaseBytes(env, argBlock,   pargBlock);
-    releaseBytes(env, envBlock,   penvBlock);
-    releaseBytes(env, dir,        c->pdir);
-
-    free(c->argv);
-    free(c->envv);
-    free(c);
-
-    if (fds != NULL)
-        (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
-
-    return resultPid;
-
- Catch:
-    /* Clean up the parent's side of the pipes in case of failure only */
-    closeSafely(in [1]); in[1] = -1;
-    closeSafely(out[0]); out[0] = -1;
-    closeSafely(err[0]); err[0] = -1;
-    goto Finally;
-}
-
-JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env,
-                                          jobject junk,
-                                          jint pid,
-                                          jboolean force)
-{
-    int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM;
-    kill(pid, sig);
-}
--- a/jdk/src/java.base/unix/native/libjava/childproc.h	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/unix/native/libjava/childproc.h	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -79,7 +79,7 @@
   } while((_result == -1) && (errno == EINTR)); \
 } while(0)
 
-/* These numbers must be the same as the Enum in UNIXProcess.java
+/* These numbers must be the same as the Enum in ProcessImpl.java
  * Must be a better way of doing this.
  */
 #define MODE_FORK 1
--- a/jdk/src/java.base/unix/native/libjava/java_props_macosx.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-/*
- * Copyright (c) 1998, 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.
- */
-
-#include <dlfcn.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <Security/AuthSession.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <Foundation/Foundation.h>
-
-#include "java_props_macosx.h"
-
-
-// need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded
-static void *getJRSFramework() {
-    static void *jrsFwk = NULL;
-    if (jrsFwk == NULL) {
-       jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
-    }
-    return jrsFwk;
-}
-
-char *getPosixLocale(int cat) {
-    char *lc = setlocale(cat, NULL);
-    if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
-        lc = getenv("LANG");
-    }
-    if (lc == NULL) return NULL;
-    return strdup(lc);
-}
-
-#define LOCALEIDLENGTH  128
-char *getMacOSXLocale(int cat) {
-    switch (cat) {
-    case LC_MESSAGES:
-        {
-            void *jrsFwk = getJRSFramework();
-            if (jrsFwk == NULL) return NULL;
-
-            char *(*JRSCopyPrimaryLanguage)() = dlsym(jrsFwk, "JRSCopyPrimaryLanguage");
-            char *primaryLanguage = JRSCopyPrimaryLanguage ? JRSCopyPrimaryLanguage() : NULL;
-            if (primaryLanguage == NULL) return NULL;
-
-            char *(*JRSCopyCanonicalLanguageForPrimaryLanguage)(char *) = dlsym(jrsFwk, "JRSCopyCanonicalLanguageForPrimaryLanguage");
-            char *canonicalLanguage = JRSCopyCanonicalLanguageForPrimaryLanguage ?  JRSCopyCanonicalLanguageForPrimaryLanguage(primaryLanguage) : NULL;
-            free (primaryLanguage);
-
-            return canonicalLanguage;
-        }
-        break;
-    default:
-        {
-            char localeString[LOCALEIDLENGTH];
-            if (CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
-                                   localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
-                return strdup(localeString);
-            }
-        }
-        break;
-    }
-
-    return NULL;
-}
-
-char *setupMacOSXLocale(int cat) {
-    char * ret = getMacOSXLocale(cat);
-
-    if (cat == LC_MESSAGES && ret != NULL) {
-        void *jrsFwk = getJRSFramework();
-        if (jrsFwk != NULL) {
-            void (*JRSSetDefaultLocalization)(char *) = dlsym(jrsFwk, "JRSSetDefaultLocalization");
-            if (JRSSetDefaultLocalization) JRSSetDefaultLocalization(ret);
-        }
-    }
-
-    if (ret == NULL) {
-        return getPosixLocale(cat);
-    } else {
-        return ret;
-    }
-}
-
-int isInAquaSession() {
-    // environment variable to bypass the aqua session check
-    char *ev = getenv("AWT_FORCE_HEADFUL");
-    if (ev && (strncasecmp(ev, "true", 4) == 0)) {
-        // if "true" then tell the caller we're in an Aqua session without actually checking
-        return 1;
-    }
-    // Is the WindowServer available?
-    SecuritySessionId session_id;
-    SessionAttributeBits session_info;
-    OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);
-    if (status == noErr) {
-        if (session_info & sessionHasGraphicAccess) {
-            return 1;
-        }
-    }
-    return 0;
-}
-
-void setOSNameAndVersion(java_props_t *sprops) {
-    /* Don't rely on JRSCopyOSName because there's no guarantee the value will
-     * remain the same, or even if the JRS functions will continue to be part of
-     * Mac OS X.  So hardcode os_name, and fill in os_version if we can.
-     */
-    sprops->os_name = strdup("Mac OS X");
-
-    void *jrsFwk = getJRSFramework();
-    if (jrsFwk != NULL) {
-        char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion");
-        if (copyOSVersion != NULL) {
-            sprops->os_version = copyOSVersion();
-            return;
-        }
-    }
-    sprops->os_version = strdup("Unknown");
-}
-
-
-static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey, CFStringRef inHostKey, CFStringRef inPortKey, CFStringRef *outProxyHost, int *ioProxyPort) {
-    /* See if the proxy is enabled. */
-    CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);
-    if (cf_enabled == NULL) {
-        return false;
-    }
-
-    int isEnabled = false;
-    if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {
-        return isEnabled;
-    }
-
-    if (!isEnabled) return false;
-    *outProxyHost = CFDictionaryGetValue(inDict, inHostKey);
-
-    // If cf_host is null, that means the checkbox is set,
-    //   but no host was entered. We'll treat that as NOT ENABLED.
-    // If cf_port is null or cf_port isn't a number, that means
-    //   no port number was entered. Treat this as ENABLED with the
-    //   protocol's default port.
-    if (*outProxyHost == NULL) {
-        return false;
-    }
-
-    if (CFStringGetLength(*outProxyHost) == 0) {
-        return false;
-    }
-
-    int newPort = 0;
-    CFNumberRef cf_port = NULL;
-    if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&
-        CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&
-        newPort > 0) {
-        *ioProxyPort = newPort;
-    } else {
-        // bad port or no port - leave *ioProxyPort unchanged
-    }
-
-    return true;
-}
-
-static char *createUTF8CString(const CFStringRef theString) {
-    if (theString == NULL) return NULL;
-
-    const CFIndex stringLength = CFStringGetLength(theString);
-    const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;
-    char *returnVal = (char *)malloc(bufSize);
-
-    if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {
-        return returnVal;
-    }
-
-    free(returnVal);
-    return NULL;
-}
-
-// Return TRUE if str is a syntactically valid IP address.
-// Using inet_pton() instead of inet_aton() for IPv6 support.
-// len is only a hint; cstr must still be nul-terminated
-static int looksLikeIPAddress(char *cstr, size_t len) {
-    if (len == 0  ||  (len == 1 && cstr[0] == '.')) return FALSE;
-
-    char dst[16]; // big enough for INET6
-    return (1 == inet_pton(AF_INET, cstr, dst)  ||
-            1 == inet_pton(AF_INET6, cstr, dst));
-}
-
-
-
-// Convert Mac OS X proxy exception entry to Java syntax.
-// See Radar #3441134 for details.
-// Returns NULL if this exception should be ignored by Java.
-// May generate a string with multiple exceptions separated by '|'.
-static char * createConvertedException(CFStringRef cf_original) {
-    // This is done with char* instead of CFString because inet_pton()
-    // needs a C string.
-    char *c_exception = createUTF8CString(cf_original);
-    if (!c_exception) return NULL;
-
-    int c_len = strlen(c_exception);
-
-    // 1. sanitize exception prefix
-    if (c_len >= 1  &&  0 == strncmp(c_exception, ".", 1)) {
-        memmove(c_exception, c_exception+1, c_len);
-        c_len -= 1;
-    } else if (c_len >= 2  &&  0 == strncmp(c_exception, "*.", 2)) {
-        memmove(c_exception, c_exception+2, c_len-1);
-        c_len -= 2;
-    }
-
-    // 2. pre-reject other exception wildcards
-    if (strchr(c_exception, '*')) {
-        free(c_exception);
-        return NULL;
-    }
-
-    // 3. no IP wildcarding
-    if (looksLikeIPAddress(c_exception, c_len)) {
-        return c_exception;
-    }
-
-    // 4. allow domain suffixes
-    // c_exception is now "str\0" - change to "str|*.str\0"
-    c_exception = reallocf(c_exception, c_len+3+c_len+1);
-    if (!c_exception) return NULL;
-
-    strncpy(c_exception+c_len, "|*.", 3);
-    strncpy(c_exception+c_len+3, c_exception, c_len);
-    c_exception[c_len+3+c_len] = '\0';
-    return c_exception;
-}
-
-/*
- * Method for fetching the user.home path and storing it in the property list.
- * For signed .apps running in the Mac App Sandbox, user.home is set to the
- * app's sandbox container.
- */
-void setUserHome(java_props_t *sprops) {
-    if (sprops == NULL) { return; }
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());
-    [pool drain];
-}
-
-/*
- * Method for fetching proxy info and storing it in the property list.
- */
-void setProxyProperties(java_props_t *sProps) {
-    if (sProps == NULL) return;
-
-    char buf[16];    /* Used for %d of an int - 16 is plenty */
-    CFStringRef
-    cf_httpHost = NULL,
-    cf_httpsHost = NULL,
-    cf_ftpHost = NULL,
-    cf_socksHost = NULL,
-    cf_gopherHost = NULL;
-    int
-    httpPort = 80, // Default proxy port values
-    httpsPort = 443,
-    ftpPort = 21,
-    socksPort = 1080,
-    gopherPort = 70;
-
-    CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
-    if (dict == NULL) return;
-
-    /* Read the proxy exceptions list */
-    CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);
-
-    CFMutableStringRef cf_exceptionList = NULL;
-    if (cf_list != NULL) {
-        CFIndex len = CFArrayGetCount(cf_list), idx;
-
-        cf_exceptionList = CFStringCreateMutable(NULL, 0);
-        for (idx = (CFIndex)0; idx < len; idx++) {
-            CFStringRef cf_ehost;
-            if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {
-                /* Convert this exception from Mac OS X syntax to Java syntax.
-                 See Radar #3441134 for details. This may generate a string
-                 with multiple Java exceptions separated by '|'. */
-                char *c_exception = createConvertedException(cf_ehost);
-                if (c_exception) {
-                    /* Append the host to the list of exclusions. */
-                    if (CFStringGetLength(cf_exceptionList) > 0) {
-                        CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);
-                    }
-                    CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);
-                    free(c_exception);
-                }
-            }
-        }
-    }
-
-    if (cf_exceptionList != NULL) {
-        if (CFStringGetLength(cf_exceptionList) > 0) {
-            sProps->exceptionList = createUTF8CString(cf_exceptionList);
-        }
-        CFRelease(cf_exceptionList);
-    }
-
-#define CHECK_PROXY(protocol, PROTOCOL)                                     \
-    sProps->protocol##ProxyEnabled =                                        \
-    getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable,      \
-    kSCPropNetProxies##PROTOCOL##Proxy,         \
-    kSCPropNetProxies##PROTOCOL##Port,          \
-    &cf_##protocol##Host, &protocol##Port);     \
-    if (sProps->protocol##ProxyEnabled) {                                   \
-        sProps->protocol##Host = createUTF8CString(cf_##protocol##Host);    \
-        snprintf(buf, sizeof(buf), "%d", protocol##Port);                   \
-        sProps->protocol##Port = malloc(strlen(buf) + 1);                   \
-        strcpy(sProps->protocol##Port, buf);                                \
-    }
-
-    CHECK_PROXY(http, HTTP);
-    CHECK_PROXY(https, HTTPS);
-    CHECK_PROXY(ftp, FTP);
-    CHECK_PROXY(socks, SOCKS);
-    CHECK_PROXY(gopher, Gopher);
-
-#undef CHECK_PROXY
-
-    CFRelease(dict);
-}
--- a/jdk/src/java.base/unix/native/libjava/java_props_macosx.h	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 1998, 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.
- */
-
-#include "java_props.h"
-
-char *setupMacOSXLocale(int cat);
-void setOSNameAndVersion(java_props_t *sprops);
-void setUserHome(java_props_t *sprops);
-void setProxyProperties(java_props_t *sProps);
-int isInAquaSession();
--- a/jdk/src/java.base/unix/native/libnet/bsd_close.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/*
- * Copyright (c) 2001, 2012, 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 <stdio.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-/*
- * Stack allocated by thread when doing blocking operation
- */
-typedef struct threadEntry {
-    pthread_t thr;                      /* this thread */
-    struct threadEntry *next;           /* next thread */
-    int intr;                           /* interrupted */
-} threadEntry_t;
-
-/*
- * Heap allocated during initialized - one entry per fd
- */
-typedef struct {
-    pthread_mutex_t lock;               /* fd lock */
-    threadEntry_t *threads;             /* threads blocked on fd */
-} fdEntry_t;
-
-/*
- * Signal to unblock thread
- */
-static int sigWakeup = SIGIO;
-
-/*
- * The fd table and the number of file descriptors
- */
-static fdEntry_t *fdTable;
-static int fdCount;
-
-/*
- * This limit applies if getlimit() returns unlimited.
- * Unfortunately, this means if someone wants a higher limit
- * then they have to set an explicit limit, higher than this,
- * which is probably counter-intuitive.
- */
-#define MAX_FD_COUNT 4096
-
-/*
- * Null signal handler
- */
-static void sig_wakeup(int sig) {
-}
-
-/*
- * Initialization routine (executed when library is loaded)
- * Allocate fd tables and sets up signal handler.
- */
-static void __attribute((constructor)) init() {
-    struct rlimit nbr_files;
-    sigset_t sigset;
-    struct sigaction sa;
-    int i;
-
-    /*
-     * Allocate table based on the maximum number of
-     * file descriptors.
-     */
-    getrlimit(RLIMIT_NOFILE, &nbr_files);
-    if (nbr_files.rlim_max == RLIM_INFINITY) {
-        fdCount = MAX_FD_COUNT;
-    } else {
-        fdCount = nbr_files.rlim_max;
-    }
-    fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
-    if (fdTable == NULL) {
-        fprintf(stderr, "library initialization failed - "
-                "unable to allocate file descriptor table - out of memory");
-        abort();
-    }
-    for (i=0; i<fdCount; i++) {
-        pthread_mutex_init(&fdTable[i].lock, NULL);
-    }
-
-    /*
-     * Setup the signal handler
-     */
-    sa.sa_handler = sig_wakeup;
-    sa.sa_flags   = 0;
-    sigemptyset(&sa.sa_mask);
-    sigaction(sigWakeup, &sa, NULL);
-
-    sigemptyset(&sigset);
-    sigaddset(&sigset, sigWakeup);
-    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-}
-
-/*
- * Return the fd table for this fd or NULL is fd out
- * of range.
- */
-static inline fdEntry_t *getFdEntry(int fd)
-{
-    if (fd < 0 || fd >= fdCount) {
-        return NULL;
-    }
-    return &fdTable[fd];
-}
-
-/*
- * Start a blocking operation :-
- *    Insert thread onto thread list for the fd.
- */
-static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
-{
-    self->thr = pthread_self();
-    self->intr = 0;
-
-    pthread_mutex_lock(&(fdEntry->lock));
-    {
-        self->next = fdEntry->threads;
-        fdEntry->threads = self;
-    }
-    pthread_mutex_unlock(&(fdEntry->lock));
-}
-
-/*
- * End a blocking operation :-
- *     Remove thread from thread list for the fd
- *     If fd has been interrupted then set errno to EBADF
- */
-static inline void endOp
-    (fdEntry_t *fdEntry, threadEntry_t *self)
-{
-    int orig_errno = errno;
-    pthread_mutex_lock(&(fdEntry->lock));
-    {
-        threadEntry_t *curr, *prev=NULL;
-        curr = fdEntry->threads;
-        while (curr != NULL) {
-            if (curr == self) {
-                if (curr->intr) {
-                    orig_errno = EBADF;
-                }
-                if (prev == NULL) {
-                    fdEntry->threads = curr->next;
-                } else {
-                    prev->next = curr->next;
-                }
-                break;
-            }
-            prev = curr;
-            curr = curr->next;
-        }
-    }
-    pthread_mutex_unlock(&(fdEntry->lock));
-    errno = orig_errno;
-}
-
-/*
- * Close or dup2 a file descriptor ensuring that all threads blocked on
- * the file descriptor are notified via a wakeup signal.
- *
- *      fd1 < 0    => close(fd2)
- *      fd1 >= 0   => dup2(fd1, fd2)
- *
- * Returns -1 with errno set if operation fails.
- */
-static int closefd(int fd1, int fd2) {
-    int rv, orig_errno;
-    fdEntry_t *fdEntry = getFdEntry(fd2);
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /*
-     * Lock the fd to hold-off additional I/O on this fd.
-     */
-    pthread_mutex_lock(&(fdEntry->lock));
-
-    {
-        /*
-         * Send a wakeup signal to all threads blocked on this
-         * file descriptor.
-         */
-        threadEntry_t *curr = fdEntry->threads;
-        while (curr != NULL) {
-            curr->intr = 1;
-            pthread_kill( curr->thr, sigWakeup );
-            curr = curr->next;
-        }
-
-        /*
-         * And close/dup the file descriptor
-         * (restart if interrupted by signal)
-         */
-        do {
-            if (fd1 < 0) {
-                rv = close(fd2);
-            } else {
-                rv = dup2(fd1, fd2);
-            }
-        } while (rv == -1 && errno == EINTR);
-
-    }
-
-    /*
-     * Unlock without destroying errno
-     */
-    orig_errno = errno;
-    pthread_mutex_unlock(&(fdEntry->lock));
-    errno = orig_errno;
-
-    return rv;
-}
-
-/*
- * Wrapper for dup2 - same semantics as dup2 system call except
- * that any threads blocked in an I/O system call on fd2 will be
- * preempted and return -1/EBADF;
- */
-int NET_Dup2(int fd, int fd2) {
-    if (fd < 0) {
-        errno = EBADF;
-        return -1;
-    }
-    return closefd(fd, fd2);
-}
-
-/*
- * Wrapper for close - same semantics as close system call
- * except that any threads blocked in an I/O on fd will be
- * preempted and the I/O system call will return -1/EBADF.
- */
-int NET_SocketClose(int fd) {
-    return closefd(-1, fd);
-}
-
-/************** Basic I/O operations here ***************/
-
-/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
- */
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
-    int ret;                                    \
-    threadEntry_t self;                         \
-    fdEntry_t *fdEntry = getFdEntry(FD);        \
-    if (fdEntry == NULL) {                      \
-        errno = EBADF;                          \
-        return -1;                              \
-    }                                           \
-    do {                                        \
-        startOp(fdEntry, &self);                \
-        ret = FUNC;                             \
-        endOp(fdEntry, &self);                  \
-    } while (ret == -1 && errno == EINTR);      \
-    return ret;                                 \
-}
-
-int NET_Read(int s, void* buf, size_t len) {
-    BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
-    BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
-       struct sockaddr *from, socklen_t *fromlen) {
-    BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
-    BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
-    BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
-}
-
-int NET_SendTo(int s, const void *msg, int len,  unsigned  int
-       flags, const struct sockaddr *to, int tolen) {
-    BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
-}
-
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
-    BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
-    BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
-    BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
-}
-
-/*
- * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
- * Auto restarts with adjusted timeout if interrupted by
- * signal other than our wakeup signal.
- */
-int NET_Timeout(int s, long timeout) {
-    long prevtime = 0, newtime;
-    struct timeval t, *tp = &t;
-    fd_set fds;
-    fd_set* fdsp = NULL;
-    int allocated = 0;
-    threadEntry_t self;
-    fdEntry_t *fdEntry = getFdEntry(s);
-
-    /*
-     * Check that fd hasn't been closed.
-     */
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /*
-     * Pick up current time as may need to adjust timeout
-     */
-    if (timeout > 0) {
-        /* Timed */
-        struct timeval now;
-        gettimeofday(&now, NULL);
-        prevtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
-        t.tv_sec = timeout / 1000;
-        t.tv_usec = (timeout % 1000) * 1000;
-    } else if (timeout < 0) {
-        /* Blocking */
-        tp = 0;
-    } else {
-        /* Poll */
-        t.tv_sec = 0;
-        t.tv_usec = 0;
-    }
-
-    if (s < FD_SETSIZE) {
-        fdsp = &fds;
-        FD_ZERO(fdsp);
-    } else {
-        int length = (howmany(s+1, NFDBITS)) * sizeof(int);
-        fdsp = (fd_set *) calloc(1, length);
-        if (fdsp == NULL) {
-            return -1;   // errno will be set to ENOMEM
-        }
-        allocated = 1;
-    }
-    FD_SET(s, fdsp);
-
-    for(;;) {
-        int rv;
-
-        /*
-         * call select on the fd. If interrupted by our wakeup signal
-         * errno will be set to EBADF.
-         */
-
-        startOp(fdEntry, &self);
-        rv = select(s+1, fdsp, 0, 0, tp);
-        endOp(fdEntry, &self);
-
-        /*
-         * If interrupted then adjust timeout. If timeout
-         * has expired return 0 (indicating timeout expired).
-         */
-        if (rv < 0 && errno == EINTR) {
-            if (timeout > 0) {
-                struct timeval now;
-                gettimeofday(&now, NULL);
-                newtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
-                timeout -= newtime - prevtime;
-                if (timeout <= 0) {
-                    if (allocated != 0)
-                        free(fdsp);
-                    return 0;
-                }
-                prevtime = newtime;
-                t.tv_sec = timeout / 1000;
-                t.tv_usec = (timeout % 1000) * 1000;
-            }
-        } else {
-            if (allocated != 0)
-                free(fdsp);
-            return rv;
-        }
-
-    }
-}
--- a/jdk/src/java.base/unix/native/libnet/linux_close.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-/*
- * Stack allocated by thread when doing blocking operation
- */
-typedef struct threadEntry {
-    pthread_t thr;                      /* this thread */
-    struct threadEntry *next;           /* next thread */
-    int intr;                           /* interrupted */
-} threadEntry_t;
-
-/*
- * Heap allocated during initialized - one entry per fd
- */
-typedef struct {
-    pthread_mutex_t lock;               /* fd lock */
-    threadEntry_t *threads;             /* threads blocked on fd */
-} fdEntry_t;
-
-/*
- * Signal to unblock thread
- */
-static int sigWakeup = (__SIGRTMAX - 2);
-
-/*
- * The fd table and the number of file descriptors
- */
-static fdEntry_t *fdTable;
-static int fdCount;
-
-/*
- * Null signal handler
- */
-static void sig_wakeup(int sig) {
-}
-
-/*
- * Initialization routine (executed when library is loaded)
- * Allocate fd tables and sets up signal handler.
- */
-static void __attribute((constructor)) init() {
-    struct rlimit nbr_files;
-    sigset_t sigset;
-    struct sigaction sa;
-
-    /*
-     * Allocate table based on the maximum number of
-     * file descriptors.
-     */
-    getrlimit(RLIMIT_NOFILE, &nbr_files);
-    fdCount = nbr_files.rlim_max;
-    fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
-    if (fdTable == NULL) {
-        fprintf(stderr, "library initialization failed - "
-                "unable to allocate file descriptor table - out of memory");
-        abort();
-    }
-
-    /*
-     * Setup the signal handler
-     */
-    sa.sa_handler = sig_wakeup;
-    sa.sa_flags   = 0;
-    sigemptyset(&sa.sa_mask);
-    sigaction(sigWakeup, &sa, NULL);
-
-    sigemptyset(&sigset);
-    sigaddset(&sigset, sigWakeup);
-    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-}
-
-/*
- * Return the fd table for this fd or NULL is fd out
- * of range.
- */
-static inline fdEntry_t *getFdEntry(int fd)
-{
-    if (fd < 0 || fd >= fdCount) {
-        return NULL;
-    }
-    return &fdTable[fd];
-}
-
-/*
- * Start a blocking operation :-
- *    Insert thread onto thread list for the fd.
- */
-static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
-{
-    self->thr = pthread_self();
-    self->intr = 0;
-
-    pthread_mutex_lock(&(fdEntry->lock));
-    {
-        self->next = fdEntry->threads;
-        fdEntry->threads = self;
-    }
-    pthread_mutex_unlock(&(fdEntry->lock));
-}
-
-/*
- * End a blocking operation :-
- *     Remove thread from thread list for the fd
- *     If fd has been interrupted then set errno to EBADF
- */
-static inline void endOp
-    (fdEntry_t *fdEntry, threadEntry_t *self)
-{
-    int orig_errno = errno;
-    pthread_mutex_lock(&(fdEntry->lock));
-    {
-        threadEntry_t *curr, *prev=NULL;
-        curr = fdEntry->threads;
-        while (curr != NULL) {
-            if (curr == self) {
-                if (curr->intr) {
-                    orig_errno = EBADF;
-                }
-                if (prev == NULL) {
-                    fdEntry->threads = curr->next;
-                } else {
-                    prev->next = curr->next;
-                }
-                break;
-            }
-            prev = curr;
-            curr = curr->next;
-        }
-    }
-    pthread_mutex_unlock(&(fdEntry->lock));
-    errno = orig_errno;
-}
-
-/*
- * Close or dup2 a file descriptor ensuring that all threads blocked on
- * the file descriptor are notified via a wakeup signal.
- *
- *      fd1 < 0    => close(fd2)
- *      fd1 >= 0   => dup2(fd1, fd2)
- *
- * Returns -1 with errno set if operation fails.
- */
-static int closefd(int fd1, int fd2) {
-    int rv, orig_errno;
-    fdEntry_t *fdEntry = getFdEntry(fd2);
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /*
-     * Lock the fd to hold-off additional I/O on this fd.
-     */
-    pthread_mutex_lock(&(fdEntry->lock));
-
-    {
-        /*
-         * And close/dup the file descriptor
-         * (restart if interrupted by signal)
-         */
-        do {
-            if (fd1 < 0) {
-                rv = close(fd2);
-            } else {
-                rv = dup2(fd1, fd2);
-            }
-        } while (rv == -1 && errno == EINTR);
-
-        /*
-         * Send a wakeup signal to all threads blocked on this
-         * file descriptor.
-         */
-        threadEntry_t *curr = fdEntry->threads;
-        while (curr != NULL) {
-            curr->intr = 1;
-            pthread_kill( curr->thr, sigWakeup );
-            curr = curr->next;
-        }
-    }
-
-    /*
-     * Unlock without destroying errno
-     */
-    orig_errno = errno;
-    pthread_mutex_unlock(&(fdEntry->lock));
-    errno = orig_errno;
-
-    return rv;
-}
-
-/*
- * Wrapper for dup2 - same semantics as dup2 system call except
- * that any threads blocked in an I/O system call on fd2 will be
- * preempted and return -1/EBADF;
- */
-int NET_Dup2(int fd, int fd2) {
-    if (fd < 0) {
-        errno = EBADF;
-        return -1;
-    }
-    return closefd(fd, fd2);
-}
-
-/*
- * Wrapper for close - same semantics as close system call
- * except that any threads blocked in an I/O on fd will be
- * preempted and the I/O system call will return -1/EBADF.
- */
-int NET_SocketClose(int fd) {
-    return closefd(-1, fd);
-}
-
-/************** Basic I/O operations here ***************/
-
-/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
- */
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) {      \
-    int ret;                                    \
-    threadEntry_t self;                         \
-    fdEntry_t *fdEntry = getFdEntry(FD);        \
-    if (fdEntry == NULL) {                      \
-        errno = EBADF;                          \
-        return -1;                              \
-    }                                           \
-    do {                                        \
-        startOp(fdEntry, &self);                \
-        ret = FUNC;                             \
-        endOp(fdEntry, &self);                  \
-    } while (ret == -1 && errno == EINTR);      \
-    return ret;                                 \
-}
-
-int NET_Read(int s, void* buf, size_t len) {
-    BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
-    BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
-       struct sockaddr *from, socklen_t *fromlen) {
-    BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
-    BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
-    BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
-}
-
-int NET_SendTo(int s, const void *msg, int len,  unsigned  int
-       flags, const struct sockaddr *to, int tolen) {
-    BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
-}
-
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
-    BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
-    BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
-    BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
-}
-
-/*
- * Wrapper for poll(s, timeout).
- * Auto restarts with adjusted timeout if interrupted by
- * signal other than our wakeup signal.
- */
-int NET_Timeout(int s, long timeout) {
-    long prevtime = 0, newtime;
-    struct timeval t;
-    fdEntry_t *fdEntry = getFdEntry(s);
-
-    /*
-     * Check that fd hasn't been closed.
-     */
-    if (fdEntry == NULL) {
-        errno = EBADF;
-        return -1;
-    }
-
-    /*
-     * Pick up current time as may need to adjust timeout
-     */
-    if (timeout > 0) {
-        gettimeofday(&t, NULL);
-        prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
-    }
-
-    for(;;) {
-        struct pollfd pfd;
-        int rv;
-        threadEntry_t self;
-
-        /*
-         * Poll the fd. If interrupted by our wakeup signal
-         * errno will be set to EBADF.
-         */
-        pfd.fd = s;
-        pfd.events = POLLIN | POLLERR;
-
-        startOp(fdEntry, &self);
-        rv = poll(&pfd, 1, timeout);
-        endOp(fdEntry, &self);
-
-        /*
-         * If interrupted then adjust timeout. If timeout
-         * has expired return 0 (indicating timeout expired).
-         */
-        if (rv < 0 && errno == EINTR) {
-            if (timeout > 0) {
-                gettimeofday(&t, NULL);
-                newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
-                timeout -= newtime - prevtime;
-                if (timeout <= 0) {
-                    return 0;
-                }
-                prevtime = newtime;
-            }
-        } else {
-            return rv;
-        }
-
-    }
-}
--- a/jdk/src/java.base/unix/native/libnet/solaris_close.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +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 <errno.h>
-#include <sys/socket.h>
-#include <stropts.h>
-#include <unistd.h>
-
-/* Support for restartable system calls on Solaris. */
-
-#define RESTARTABLE_RETURN_INT(_cmd) do {             \
-    int _result;                                      \
-    if (1) {                                          \
-        do {                                          \
-            _result = _cmd;                           \
-        } while((_result == -1) && (errno == EINTR)); \
-        return _result;                               \
-    }                                                 \
-} while(0)
-
-int NET_Read(int s, void* buf, size_t len) {
-    RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
-                 struct sockaddr *from, socklen_t *fromlen) {
-    RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
-    RESTARTABLE_RETURN_INT(readv(s, vector, count));
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
-    RESTARTABLE_RETURN_INT(writev(s, vector, count));
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
-    RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
-}
-
-int NET_SendTo(int s, const void *msg, int len,  unsigned  int flags,
-               const struct sockaddr *to, int tolen) {
-    RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
-    RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
-}
-
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
-    RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
-}
-
-int NET_SocketClose(int fd) {
-    return close(fd);
-}
-
-int NET_Dup2(int fd, int fd2) {
-    return dup2(fd, fd2);
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
-    RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
-}
-
-int NET_Timeout(int s, long timeout) {
-    int result;
-    struct timeval t;
-    long prevtime, newtime;
-    struct pollfd pfd;
-    pfd.fd = s;
-    pfd.events = POLLIN;
-
-    if (timeout > 0) {
-        gettimeofday(&t, NULL);
-        prevtime = (t.tv_sec * 1000)  +  t.tv_usec / 1000;
-    }
-
-    for(;;) {
-        result = poll(&pfd, 1, timeout);
-        if (result < 0 && errno == EINTR) {
-            if (timeout > 0) {
-                gettimeofday(&t, NULL);
-                newtime = (t.tv_sec * 1000)  +  t.tv_usec /1000;
-                timeout -= newtime - prevtime;
-                if (timeout <= 0)
-                    return 0;
-                prevtime = newtime;
-            }
-        } else {
-            return result;
-        }
-    }
-}
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Wed Jul 05 20:17:15 2017 +0200
@@ -48,6 +48,8 @@
     isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
                                      "(Ljava/net/InetAddress;I)V");
 
+    initInetAddressIDs(env);
+
     // implement read timeout with select.
     isRcvTimeoutSupported = 0;
 }
@@ -294,6 +296,8 @@
         return -1;
     }
 
+    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
+
     ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
     isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
     (*env)->SetObjectArrayElement(env, isaa, 0, isa);
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Wed Jul 05 20:17:15 2017 +0200
@@ -699,6 +699,7 @@
         }
         return;
     }
+    SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
     (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
 
     if (him.him.sa_family == AF_INET) {
--- a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c	Wed Jul 05 20:17:15 2017 +0200
@@ -105,6 +105,7 @@
         return IOS_THROWN;
     }
 
+    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
     (*env)->SetIntField(env, newfdo, fd_fdID, newfd);
     remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port);
     CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java	Wed Jul 05 20:17:15 2017 +0200
@@ -913,9 +913,9 @@
 
     private static String unquote(String s) {
         s = s.trim();
-        if (s.isEmpty()) return s;
-        if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
-                s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
+        if (s.length() >= 2 &&
+                ((s.charAt(0) == '"' && s.charAt(s.length()-1) == '"') ||
+                 (s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\''))) {
             s = s.substring(1, s.length()-1).trim();
         }
         return s;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java	Wed Jul 05 20:17:15 2017 +0200
@@ -62,7 +62,8 @@
             throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
         }
 
-        for (int i = 1; i < 6; i++) {
+        // We allow KDC to return a non-forwardable ticket if request has -f
+        for (int i = 2; i < 6; i++) {
             if (req.reqBody.kdcOptions.get(i) !=
                    rep.encKDCRepPart.flags.get(i)) {
                 if (Krb5.DEBUG) {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java	Wed Jul 05 20:17:15 2017 +0200
@@ -149,19 +149,11 @@
         ctime = KerberosTime.now();
 
         // check if they are valid arguments. The optional fields
-        // should be  consistent with settings in KDCOptions.
-
-        // TODO: Is this necessary? If the TGT is not FORWARDABLE,
-        // you can still request for a FORWARDABLE ticket, just the
-        // KDC will give you a non-FORWARDABLE one. Even if you
-        // cannot use the ticket expected, it still contains info.
-        // This means there will be problem later. We already have
-        // flags check in KrbTgsRep. Of course, sometimes the KDC
-        // will not issue the ticket at all.
+        // should be consistent with settings in KDCOptions.
 
         if (options.get(KDCOptions.FORWARDABLE) &&
                 (!(asCreds.flags.get(Krb5.TKT_OPTS_FORWARDABLE)))) {
-            throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
+            options.set(KDCOptions.FORWARDABLE, false);
         }
         if (options.get(KDCOptions.FORWARDED)) {
             if (!(asCreds.flags.get(KDCOptions.FORWARDABLE)))
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java	Wed Jul 05 20:17:15 2017 +0200
@@ -58,6 +58,9 @@
             // TODO: we do not support kerberos referral now
             throw new KrbException("Cross realm impersonation not supported");
         }
+        if (!ccreds.isForwardable()) {
+            throw new KrbException("S4U2self needs a FORWARDABLE ticket");
+        }
         KrbTgsReq req = new KrbTgsReq(
                 ccreds,
                 ccreds.getClient(),
@@ -68,6 +71,9 @@
         if (!creds.getClient().equals(client)) {
             throw new KrbException("S4U2self request not honored by KDC");
         }
+        if (!creds.isForwardable()) {
+            throw new KrbException("S4U2self ticket must be FORWARDABLE");
+        }
         return creds;
     }
 
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c	Wed Jul 05 20:17:15 2017 +0200
@@ -316,11 +316,12 @@
     if (isaCls == 0) {
         jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
         CHECK_NULL(c);
+        isaCtrID = (*env)->GetMethodID(env, c, "<init>",
+                                     "(Ljava/net/InetAddress;I)V");
+        CHECK_NULL(isaCtrID);
         isaCls = (*env)->NewGlobalRef(env, c);
         CHECK_NULL(isaCls);
         (*env)->DeleteLocalRef(env, c);
-        isaCtrID = (*env)->GetMethodID(env, isaCls, "<init>",
-                                     "(Ljava/net/InetAddress;I)V");
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.auth/solaris/native/libjaas/Solaris.c	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2000, 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.
+ */
+
+#include <jni.h>
+#include "com_sun_security_auth_module_SolarisSystem.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+
+static void throwIllegalArgumentException(JNIEnv *env, const char *msg) {
+    jclass clazz = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
+    if (clazz != NULL)
+        (*env)->ThrowNew(env, clazz, msg);
+}
+
+JNIEXPORT void JNICALL
+Java_com_sun_security_auth_module_SolarisSystem_getSolarisInfo
+                                                (JNIEnv *env, jobject obj) {
+
+    int i;
+    char pwd_buf[1024];
+    struct passwd pwd;
+    jsize numSuppGroups = getgroups(0, NULL);
+    jfieldID fid;
+    jstring jstr;
+    jlongArray jgroups;
+    jlong *jgroupsAsArray;
+    gid_t *groups;
+    jclass cls;
+
+    groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
+
+    if (groups == NULL) {
+        jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
+        if (cls != NULL)
+            (*env)->ThrowNew(env, cls, NULL);
+        return;
+    }
+
+    cls = (*env)->GetObjectClass(env, obj);
+
+    memset(pwd_buf, 0, sizeof(pwd_buf));
+    if (getpwuid_r(getuid(), &pwd, pwd_buf, sizeof(pwd_buf)) != NULL &&
+        getgroups(numSuppGroups, groups) != -1) {
+
+        /*
+         * set username
+         */
+        fid = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
+        if (fid == 0) {
+            (*env)->ExceptionClear(env);
+            throwIllegalArgumentException(env, "invalid field: username");
+            goto cleanupAndReturn;
+        }
+        jstr = (*env)->NewStringUTF(env, pwd.pw_name);
+        if (jstr == NULL) {
+            goto cleanupAndReturn;
+        }
+        (*env)->SetObjectField(env, obj, fid, jstr);
+
+        /*
+         * set uid
+         */
+        fid = (*env)->GetFieldID(env, cls, "uid", "J");
+        if (fid == 0) {
+            (*env)->ExceptionClear(env);
+            throwIllegalArgumentException(env, "invalid field: uid");
+            goto cleanupAndReturn;
+        }
+        (*env)->SetLongField(env, obj, fid, pwd.pw_uid);
+
+        /*
+         * set gid
+         */
+        fid = (*env)->GetFieldID(env, cls, "gid", "J");
+        if (fid == 0) {
+            (*env)->ExceptionClear(env);
+            throwIllegalArgumentException(env, "invalid field: gid");
+            goto cleanupAndReturn;
+        }
+        (*env)->SetLongField(env, obj, fid, pwd.pw_gid);
+
+        /*
+         * set supplementary groups
+         */
+        fid = (*env)->GetFieldID(env, cls, "groups", "[J");
+        if (fid == 0) {
+            (*env)->ExceptionClear(env);
+            throwIllegalArgumentException(env, "invalid field: groups");
+            goto cleanupAndReturn;
+        }
+
+        jgroups = (*env)->NewLongArray(env, numSuppGroups);
+        if (jgroups == NULL) {
+            goto cleanupAndReturn;
+        }
+        jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
+        if (jgroupsAsArray == NULL) {
+            goto cleanupAndReturn;
+        }
+        for (i = 0; i < numSuppGroups; i++)
+            jgroupsAsArray[i] = groups[i];
+        (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
+        (*env)->SetObjectField(env, obj, fid, jgroups);
+    }
+cleanupAndReturn:
+    free(groups);
+
+    return;
+}
--- a/jdk/src/jdk.security.auth/unix/native/libjaas/Solaris.c	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2000, 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.
- */
-
-#include <jni.h>
-#include "com_sun_security_auth_module_SolarisSystem.h"
-#include <stdio.h>
-#include <pwd.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pwd.h>
-
-static void throwIllegalArgumentException(JNIEnv *env, const char *msg) {
-    jclass clazz = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
-    if (clazz != NULL)
-        (*env)->ThrowNew(env, clazz, msg);
-}
-
-JNIEXPORT void JNICALL
-Java_com_sun_security_auth_module_SolarisSystem_getSolarisInfo
-                                                (JNIEnv *env, jobject obj) {
-
-    int i;
-    char pwd_buf[1024];
-    struct passwd pwd;
-    jsize numSuppGroups = getgroups(0, NULL);
-    jfieldID fid;
-    jstring jstr;
-    jlongArray jgroups;
-    jlong *jgroupsAsArray;
-    gid_t *groups;
-    jclass cls;
-
-    groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
-
-    if (groups == NULL) {
-        jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
-        if (cls != NULL)
-            (*env)->ThrowNew(env, cls, NULL);
-        return;
-    }
-
-    cls = (*env)->GetObjectClass(env, obj);
-
-    memset(pwd_buf, 0, sizeof(pwd_buf));
-    if (getpwuid_r(getuid(), &pwd, pwd_buf, sizeof(pwd_buf)) != NULL &&
-        getgroups(numSuppGroups, groups) != -1) {
-
-        /*
-         * set username
-         */
-        fid = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
-        if (fid == 0) {
-            (*env)->ExceptionClear(env);
-            throwIllegalArgumentException(env, "invalid field: username");
-            goto cleanupAndReturn;
-        }
-        jstr = (*env)->NewStringUTF(env, pwd.pw_name);
-        if (jstr == NULL) {
-            goto cleanupAndReturn;
-        }
-        (*env)->SetObjectField(env, obj, fid, jstr);
-
-        /*
-         * set uid
-         */
-        fid = (*env)->GetFieldID(env, cls, "uid", "J");
-        if (fid == 0) {
-            (*env)->ExceptionClear(env);
-            throwIllegalArgumentException(env, "invalid field: uid");
-            goto cleanupAndReturn;
-        }
-        (*env)->SetLongField(env, obj, fid, pwd.pw_uid);
-
-        /*
-         * set gid
-         */
-        fid = (*env)->GetFieldID(env, cls, "gid", "J");
-        if (fid == 0) {
-            (*env)->ExceptionClear(env);
-            throwIllegalArgumentException(env, "invalid field: gid");
-            goto cleanupAndReturn;
-        }
-        (*env)->SetLongField(env, obj, fid, pwd.pw_gid);
-
-        /*
-         * set supplementary groups
-         */
-        fid = (*env)->GetFieldID(env, cls, "groups", "[J");
-        if (fid == 0) {
-            (*env)->ExceptionClear(env);
-            throwIllegalArgumentException(env, "invalid field: groups");
-            goto cleanupAndReturn;
-        }
-
-        jgroups = (*env)->NewLongArray(env, numSuppGroups);
-        if (jgroups == NULL) {
-            goto cleanupAndReturn;
-        }
-        jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
-        if (jgroupsAsArray == NULL) {
-            goto cleanupAndReturn;
-        }
-        for (i = 0; i < numSuppGroups; i++)
-            jgroupsAsArray[i] = groups[i];
-        (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
-        (*env)->SetObjectField(env, obj, fid, jgroups);
-    }
-cleanupAndReturn:
-    free(groups);
-
-    return;
-}
--- a/jdk/test/ProblemList.txt	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 20:17:15 2017 +0200
@@ -128,9 +128,6 @@
 
 # jdk_instrument
 
-# 8058536
-java/lang/instrument/NativeMethodPrefixAgent.java               generic-all
-
 # 8061177
 java/lang/instrument/RedefineBigClass.sh                        generic-all
 java/lang/instrument/RetransformBigClass.sh                     generic-all
@@ -246,6 +243,9 @@
 # 8062758
 java/security/Security/ClassLoaderDeadlock/Deadlock2.sh         generic-all
 
+# 8026393
+sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java      generic-all
+
 ############################################################################
 
 # jdk_sound
--- a/jdk/test/TEST.groups	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/TEST.groups	Wed Jul 05 20:17:15 2017 +0200
@@ -628,7 +628,6 @@
   sun/net/www/protocol/http \
   java/io/BufferedReader/Lines.java  \
   java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java \
-  java/lang/CharSequence/DefaultTest.java  \
   java/lang/IntegralPrimitiveToString.java  \
   java/lang/PrimitiveSumMinMaxTest.java  \
   java/lang/String/StringJoinTest.java  \
--- a/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java	Wed Jul 05 20:17:15 2017 +0200
@@ -50,8 +50,9 @@
                 }
 
                 ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
-                ClassLoader loader = new URLClassLoader(((URLClassLoader) systemLoader).getURLs(),
-                                                                                        systemLoader.getParent());
+                URL testClassesURL = new File(System.getProperty("test.classes")).toURI().toURL();
+                ClassLoader loader = new URLClassLoader(new URL[] { testClassesURL } ,
+                                                        systemLoader.getParent());
                 Class<? extends ObjectOutputStream> cl =
                         Class.forName(SubclassOfOOS.class.getName(), false,
                                                   loader).asSubclass(ObjectOutputStream.class);
--- a/jdk/test/java/io/Serializable/subclassGC/security.policy	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/io/Serializable/subclassGC/security.policy	Wed Jul 05 20:17:15 2017 +0200
@@ -2,5 +2,7 @@
 grant {
 	permission java.lang.RuntimePermission "createClassLoader";
 	permission java.lang.RuntimePermission "getClassLoader";
+	permission java.util.PropertyPermission "test.classes", "read";
+	permission java.io.FilePermission "<<ALL FILES>>", "read";
 };
 
--- a/jdk/test/java/lang/CharSequence/DefaultTest.java	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.PrimitiveIterator;
-import java.util.Spliterator;
-import java.util.stream.Collectors;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.*;
-
-/*
- * @test
- * @summary Unit test for CharSequence default methods
- * @bug 8012665 8025002
- * @run testng DefaultTest
- */
-
-@Test(groups = "lib")
-public class DefaultTest {
-
-    @Test(expectedExceptions = NoSuchElementException.class)
-    public void testEmptyChars() {
-        PrimitiveIterator.OfInt s = "".chars().iterator();
-        assertFalse(s.hasNext());
-        int ch = s.nextInt();
-    }
-
-    public void testSimpleChars() {
-        List<Integer> list = "abc".chars().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList((int) 'a', (int) 'b', (int) 'c'));
-    }
-
-    public void testCodePointsCharacteristics() {
-        Spliterator.OfInt s = "".codePoints().spliterator();
-        assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
-        assertTrue(s.hasCharacteristics(Spliterator.ORDERED));
-    }
-
-    @Test(expectedExceptions = NoSuchElementException.class)
-    public void testEmptyCodePoints() {
-        PrimitiveIterator.OfInt s = "".codePoints().iterator();
-        assertFalse(s.hasNext());
-        int cp = s.nextInt();
-    }
-
-    public void testSimpleCodePoints() {
-        List<Integer> list = "abc".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList((int)'a', (int)'b', (int)'c'));
-    }
-
-    public void testUndefCodePoints() {
-        List<Integer> list = "X\ufffeY".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList((int)'X', 0xFFFE, (int)'Y'));
-    }
-
-    public void testSurrogatePairing() {
-        // U+1D11E = MUSICAL SYMBOL G CLEF
-        // equivalent to surrogate pair U+D834 U+DD1E
-        List<Integer> list;
-        final int GCLEF = 0x1d11e;
-
-        list = "\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList(GCLEF));
-        list = "A\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList((int)'A', GCLEF));
-        list = "\ud834\udd1eB".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList(GCLEF, (int)'B'));
-        list = "X\ud834\udd1eY".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList((int)'X', GCLEF, (int)'Y'));
-    }
-
-    public void testUndefUnpaired() {
-        List<Integer> list = "W\udd1eX\ud834Y\ufffeZ".codePoints().boxed().collect(Collectors.toList());
-        assertEquals(list, Arrays.asList(
-            (int)'W', 0xdd1e, (int)'X', 0xd834, (int)'Y', 0xfffe, (int)'Z'));
-    }
-}
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -26,7 +26,7 @@
  * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
  *      5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
  *      6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
- *      4947220 7018606 7034570 4244896 5049299 8003488
+ *      4947220 7018606 7034570 4244896 5049299 8003488 8054494
  * @summary Basic tests for Process and Environment Variable code
  * @run main/othervm/timeout=300 Basic
  * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic
@@ -2042,7 +2042,7 @@
                     final Object deferred;
                     Class<?> c = s.getClass();
                     if (c.getName().equals(
-                        "java.lang.UNIXProcess$DeferredCloseInputStream"))
+                        "java.lang.ProcessImpl$DeferredCloseInputStream"))
                     {
                         deferred = s;
                     } else {
@@ -2059,13 +2059,11 @@
                         Thread.yield();
                     }
                 } else if (s instanceof BufferedInputStream) {
-                    Field f = Unsafe.class.getDeclaredField("theUnsafe");
-                    f.setAccessible(true);
-                    Unsafe unsafe = (Unsafe)f.get(null);
-
-                    while (unsafe.tryMonitorEnter(s)) {
-                        unsafe.monitorExit(s);
-                        Thread.sleep(1);
+                    // Wait until after the s.read occurs in "thread" by
+                    // checking when the input stream monitor is acquired
+                    // (BufferedInputStream.read is synchronized)
+                    while (!isLocked(s, 10)) {
+                        Thread.sleep(100);
                     }
                 }
                 p.destroy();
@@ -2565,4 +2563,21 @@
             catch (Throwable t) {
                 if (k.isAssignableFrom(t.getClass())) pass();
                 else unexpected(t);}}
+
+    static boolean isLocked(final Object monitor, final long millis) throws InterruptedException {
+        return new Thread() {
+            volatile boolean unlocked;
+
+            @Override
+            public void run() {
+                synchronized (monitor) { unlocked = true; }
+            }
+
+            boolean isLocked() throws InterruptedException {
+                start();
+                join(millis);
+                return !unlocked;
+            }
+        }.isLocked();
+    }
 }
--- a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,7 +25,7 @@
  * @test
  * @bug 7038914 8016341
  * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
- * @run main/othervm -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler
+ * @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler
  * @author peter.levart@gmail.com
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/ServerSocket/AcceptInheritHandle.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * 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 8067105
+ * @summary Socket returned by ServerSocket.accept() is inherited by child process on Windows
+ * @author Chris Hegarty
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.channels.ServerSocketChannel;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+public class AcceptInheritHandle {
+
+    enum ServerSocketProducer {
+        JAVA_NET(() -> {
+            try {
+                return new ServerSocket(); }
+            catch(IOException x) {
+                throw new UncheckedIOException(x);
+            }
+        }),
+        NIO_CHANNELS(() -> {
+            try {
+                return ServerSocketChannel.open().socket();
+            } catch (IOException x) {
+                throw new UncheckedIOException(x);
+            }
+        });
+
+        final Supplier<ServerSocket> supplier;
+        ServerSocketProducer(Supplier<ServerSocket> supplier) {
+            this.supplier = supplier;
+        }
+        Supplier<ServerSocket> supplier () { return supplier; }
+    }
+
+    static final String JAVA = System.getProperty("java.home")
+        + File.separator + "bin" + File.separator + "java";
+
+    static final String CLASSPATH = System.getProperty("java.class.path");
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 1)
+            server(ServerSocketProducer.valueOf(args[0]));
+        else
+            mainEntry();
+    }
+
+    static void mainEntry() throws Exception {
+        testJavaNetServerSocket();
+        testNioServerSocketChannel();
+    }
+
+    static void testJavaNetServerSocket() throws Exception {
+        test(ServerSocketProducer.JAVA_NET);
+        test(ServerSocketProducer.JAVA_NET, "-Djava.net.preferIPv4Stack=true");
+    }
+    static void testNioServerSocketChannel() throws Exception {
+        test(ServerSocketProducer.NIO_CHANNELS);
+    }
+
+    static void test(ServerSocketProducer ssp, String... sysProps) throws Exception {
+        System.out.println("\nStarting test for " + ssp.name());
+
+        List<String> commands = new ArrayList<>();
+        commands.add(JAVA);
+        for (String prop : sysProps)
+            commands.add(prop);
+        commands.add("-cp");
+        commands.add(CLASSPATH);
+        commands.add("AcceptInheritHandle");
+        commands.add(ssp.name());
+
+        System.out.println("Executing: "+ commands);
+        ProcessBuilder pb = new ProcessBuilder(commands);
+        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+        Process serverProcess = pb.start();
+        DataInputStream dis = new DataInputStream(serverProcess.getInputStream());
+
+        int port = dis.readInt();
+        System.out.println("Server process listening on " + port + ", connecting...");
+
+        Socket socket = new Socket("localhost", port);
+        String s = dis.readUTF();
+        System.out.println("Server process said " + s);
+
+        serverProcess.destroy();
+        serverProcess.waitFor(30, TimeUnit.SECONDS);
+        System.out.println("serverProcess exitCode:" + serverProcess.exitValue());
+
+        try {
+            socket.setSoTimeout(10 * 1000);
+            socket.getInputStream().read();
+        } catch (SocketTimeoutException x) {
+            // failed
+            throw new RuntimeException("Failed: should get reset, not " + x);
+        } catch (SocketException x) {
+            System.out.println("Expected:" + x);
+        }
+    }
+
+    static void server(ServerSocketProducer producer) throws Exception {
+        try (ServerSocket ss = producer.supplier().get()) {
+            ss.bind(new InetSocketAddress(0));
+            int port = ss.getLocalPort();
+            DataOutputStream dos = new DataOutputStream(System.out);
+            dos.writeInt(port);
+            dos.flush();
+
+            ss.accept();  // do not close
+
+            Runtime.getRuntime().exec("sleep 20");
+            Thread.sleep(3 * 1000);
+
+            dos.writeUTF("kill me!");
+            dos.flush();
+            Thread.sleep(30 * 1000);
+        }
+    }
+}
--- a/jdk/test/java/net/Socket/GetLocalAddress.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/net/Socket/GetLocalAddress.java	Wed Jul 05 20:17:15 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4106601 8026245
+ * @bug 4106601 8026245 8071424
  * @run main/othervm GetLocalAddress
  * @run main/othervm -Djava.net.preferIPv4Stack=true GetLocalAddress
  * @run main/othervm -Djava.net.preferIPv6Addresses=true GetLocalAddress
@@ -39,6 +39,8 @@
     static int port;
 
     public static void main(String args[]) throws Exception {
+        testBindNull();
+
         boolean      error = true;
         int          linger = 65546;
         int          value = 0;
@@ -66,4 +68,18 @@
         }
     }
 
+    static void testBindNull() throws Exception {
+        try (Socket soc = new Socket()) {
+            soc.bind(null);
+            if (!soc.isBound())
+                throw new RuntimeException(
+                    "should be bound after bind(null)");
+            if (soc.getLocalPort() <= 0)
+                throw new RuntimeException(
+                   "bind(null) failed, local port: " + soc.getLocalPort());
+            if (soc.getLocalAddress() == null)
+                 throw new RuntimeException(
+                   "bind(null) failed, local address is null");
+        }
+    }
 }
--- a/jdk/test/java/util/ResourceBundle/Bug6287579.java	Thu Jan 29 15:36:12 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2007, 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 6287579
- * @summary Make sure that getContents() of ListResourceBundle subclasses is 'protected'
- *          and returns a different Object[]][] instance in each invocation.
- */
-
-import java.lang.reflect.*;
-import java.util.*;
-
-public class Bug6287579 {
-    static final Locale ROOT = new Locale("");
-
-    static final String[] baseNames = {
-        "sun.text.resources.BreakIteratorInfo",
-        "sun.text.resources.FormatData",
-        "sun.text.resources.CollationData",
-        "sun.util.resources.LocaleNames",
-        "sun.util.resources.TimeZoneNames",
-
-        // Make sure the properties-to-class conversion tool generates
-        // the proper getContents().
-        "sun.awt.resources.awt",
-    };
-
-    public static void main(String[] args) throws Exception {
-        int errors = 0;
-
-        List<Locale> locales = new ArrayList<Locale>();
-        locales.addAll(Arrays.asList(Locale.getAvailableLocales()));
-        locales.add(ROOT);
-
-        for (Locale locale : locales) {
-            for (String base : baseNames) {
-                String className = getResourceName(base, locale);
-                errors += checkGetContents(className);
-            }
-        }
-        if (errors > 0) {
-            throw new RuntimeException(errors + " errors found");
-        }
-    }
-
-    static int checkGetContents(String className) throws Exception {
-        int err = 0;
-        try {
-            Class clazz = Class.forName(className);
-            Method getContentsMethod = clazz.getDeclaredMethod("getContents",
-                                                               (Class[]) null);
-            if (!Modifier.isProtected(getContentsMethod.getModifiers())) {
-                System.err.println(className + ": not protected");
-                err++;
-            }
-            getContentsMethod.setAccessible(true);
-            Object bundle = clazz.newInstance();
-            Object o1 = getContentsMethod.invoke(bundle, (Object[]) null);
-            Object o2 = getContentsMethod.invoke(bundle, (Object[]) null);
-            if (o1 == o2) {
-                System.err.println(className + ": same instance returned");
-                err++;
-            }
-        } catch (ClassNotFoundException ce) {
-            // Skip nonexistent classes
-        } catch (NoSuchMethodException me) {
-            System.out.println(className + ": no declared getContents()");
-        }
-        return err;
-    }
-
-    static String getResourceName(String base, Locale locale) {
-        if (locale.equals(ROOT)) {
-            return base;
-        }
-        StringBuilder sb = new StringBuilder(base);
-        sb.append('_').append(locale.getLanguage());
-        if (locale.getCountry().length() > 0
-            || locale.getVariant().length() > 0) {
-            sb.append('_').append(locale.getCountry());
-        }
-        if (locale.getVariant().length() > 0) {
-            sb.append('_').append(locale.getVariant());
-        }
-        return sb.toString();
-    }
-}
--- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8020156 8020009 8022326 8012913 8024405 8024408
+ * @bug 8020156 8020009 8022326 8012913 8024405 8024408 8071477
  * @run testng SpliteratorCharacteristics
  */
 
@@ -59,6 +59,57 @@
 @Test
 public class SpliteratorCharacteristics {
 
+    public void testSpliteratorFromCharSequence() {
+        class CharSequenceImpl implements CharSequence {
+            final String s;
+
+            public CharSequenceImpl(String s) {
+                this.s = s;
+            }
+
+            @Override
+            public int length() {
+                return s.length();
+            }
+
+            @Override
+            public char charAt(int index) {
+                return s.charAt(index);
+            }
+
+            @Override
+            public CharSequence subSequence(int start, int end) {
+                return s.subSequence(start, end);
+            }
+
+            @Override
+            public String toString() {
+                return s;
+            }
+        }
+
+        CharSequence cs = "A";
+        Spliterator.OfInt s = cs.chars().spliterator();
+        assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED |
+                                 Spliterator.SIZED | Spliterator.SUBSIZED);
+        assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+        s = cs.codePoints().spliterator();
+        assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED);
+        assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+
+        for (CharSequence c : Arrays.asList(new CharSequenceImpl("A"),
+                                             new StringBuilder("A"),
+                                             new StringBuffer("A"))) {
+            s = cs.chars().spliterator();
+            assertCharacteristics(s, Spliterator.ORDERED |
+                                     Spliterator.SIZED | Spliterator.SUBSIZED);
+            assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+            s = cs.codePoints().spliterator();
+            assertCharacteristics(s, Spliterator.ORDERED);
+            assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+        }
+    }
+
     public void testSpliteratorFromCollection() {
         List<Integer> l = Arrays.asList(1, 2, 3, 4);
 
--- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,7 +25,7 @@
  * @test
  * @summary Spliterator traversing and splitting tests
  * @run testng SpliteratorTraversingAndSplittingTest
- * @bug 8020016
+ * @bug 8020016 8071477
  */
 
 import org.testng.annotations.DataProvider;
@@ -85,7 +85,38 @@
 @Test
 public class SpliteratorTraversingAndSplittingTest {
 
-    private static List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
+    private static final List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
+
+    private static final String LOW = new String(new char[] {Character.MIN_LOW_SURROGATE});
+    private static final String HIGH = new String(new char[] {Character.MIN_HIGH_SURROGATE});
+    private static final String HIGH_LOW = HIGH + LOW;
+    private static final String CHAR_HIGH_LOW = "A" + HIGH_LOW;
+    private static final String HIGH_LOW_CHAR = HIGH_LOW + "A";
+    private static final String CHAR_HIGH_LOW_CHAR = "A" + HIGH_LOW + "A";
+
+    private static final List<String> STRINGS = generateTestStrings();
+
+    private static List<String> generateTestStrings() {
+        List<String> strings = new ArrayList<>();
+        for (int n : Arrays.asList(1, 2, 3, 16, 17)) {
+            strings.add(generate("A", n));
+            strings.add(generate(LOW, n));
+            strings.add(generate(HIGH, n));
+            strings.add(generate(HIGH_LOW, n));
+            strings.add(generate(CHAR_HIGH_LOW, n));
+            strings.add(generate(HIGH_LOW_CHAR, n));
+            strings.add(generate(CHAR_HIGH_LOW_CHAR, n));
+        }
+        return strings;
+    }
+
+    private static String generate(String s, int n) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < n; i++) {
+            sb.append(s);
+        }
+        return sb.toString();
+    }
 
     private static class SpliteratorDataBuilder<T> {
         List<Object[]> data;
@@ -564,6 +595,60 @@
         }
     }
 
+    private static class SpliteratorOfIntCharDataBuilder {
+        List<Object[]> data;
+
+        String s;
+
+        List<Integer> expChars;
+
+        List<Integer> expCodePoints;
+
+        SpliteratorOfIntCharDataBuilder(List<Object[]> data, String s) {
+            this.data = data;
+            this.s = s;
+            this.expChars = transform(s, false);
+            this.expCodePoints = transform(s, true);
+        }
+
+        static List<Integer> transform(String s, boolean toCodePoints) {
+            List<Integer> l = new ArrayList<>();
+
+            if (!toCodePoints) {
+                for (int i = 0; i < s.length(); i++) {
+                    l.add((int) s.charAt(i));
+                }
+            }
+            else {
+                for (int i = 0; i < s.length();) {
+                    char c1 = s.charAt(i++);
+                    int cp = c1;
+                    if (Character.isHighSurrogate(c1) && i < s.length()) {
+                        char c2 = s.charAt(i);
+                        if (Character.isLowSurrogate(c2)) {
+                            i++;
+                            cp = Character.toCodePoint(c1, c2);
+                        }
+                    }
+                    l.add(cp);
+                }
+            }
+            return l;
+        }
+
+        void add(String description, Function<String, CharSequence> f) {
+            description = description.replace("%s", s);
+            {
+                Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).chars().spliterator();
+                data.add(new Object[]{description + ".chars().spliterator()", expChars, supplier});
+            }
+            {
+                Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).codePoints().spliterator();
+                data.add(new Object[]{description + ".codePoints().spliterator()", expCodePoints, supplier});
+            }
+        }
+    }
+
     static Object[][] spliteratorOfIntDataProvider;
 
     @DataProvider(name = "Spliterator.OfInt")
@@ -615,6 +700,43 @@
                    () -> new IntSpliteratorFromArray(exp));
         }
 
+        // Class for testing default methods
+        class CharSequenceImpl implements CharSequence {
+            final String s;
+
+            public CharSequenceImpl(String s) {
+                this.s = s;
+            }
+
+            @Override
+            public int length() {
+                return s.length();
+            }
+
+            @Override
+            public char charAt(int index) {
+                return s.charAt(index);
+            }
+
+            @Override
+            public CharSequence subSequence(int start, int end) {
+                return s.subSequence(start, end);
+            }
+
+            @Override
+            public String toString() {
+                return s;
+            }
+        }
+
+        for (String string : STRINGS) {
+            SpliteratorOfIntCharDataBuilder cdb = new SpliteratorOfIntCharDataBuilder(data, string);
+            cdb.add("\"%s\"", s -> s);
+            cdb.add("new CharSequenceImpl(\"%s\")", CharSequenceImpl::new);
+            cdb.add("new StringBuilder(\"%s\")", StringBuilder::new);
+            cdb.add("new StringBuffer(\"%s\")", StringBuffer::new);
+        }
+
         return spliteratorOfIntDataProvider = data.toArray(new Object[0][]);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/jaxp/transform/8062923/XslSubstringTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * 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 8062923 8062924
+ * @run testng XslSubstringTest
+ * @summary Test xsl substring function with negative, Inf and
+ * NaN length and few other use cases
+ */
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+public class XslSubstringTest {
+
+    final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test></test>";
+    final String xslPre = "<xsl:stylesheet version='1.0'"
+            + " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>"
+            + "<xsl:output method='xml' indent='yes' omit-xml-declaration='yes'/>"
+            + "<xsl:template match='/'><t>";
+    final String xslPost = "</t></xsl:template></xsl:stylesheet>";
+
+    private String testTransform(String xsl) throws Exception {
+        //Prepare sources for transormation
+        Source src = new StreamSource(new StringReader(xml));
+        Source xslsrc = new StreamSource(new StringReader(xslPre + xsl + xslPost));
+        //Create factory, template and transformer
+        TransformerFactory tf = TransformerFactory.newInstance();
+        Templates tmpl = tf.newTemplates(xslsrc);
+        Transformer t = tmpl.newTransformer();
+        //Prepare output stream
+        StringWriter xmlResultString = new StringWriter();
+        StreamResult xmlResultStream = new StreamResult(xmlResultString);
+        //Transform
+        t.transform(src, xmlResultStream);
+        return xmlResultString.toString().trim();
+    }
+
+    @Test
+    public void test8062923() throws Exception {
+        assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2,-1)\"/>|"),
+                "<t>||</t>");
+    }
+
+    @Test
+    public void test8062924() throws Exception {
+        assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2,-1 div 0)\"/>|"),
+                "<t>||</t>");
+    }
+
+    @Test
+    public void testGeneral1() throws Exception {
+        assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 1)\"/>|"),
+                "<t>|s|</t>");
+    }
+
+    @Test
+    public void testGeneral2() throws Exception {
+        assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 1 div 0)\"/>|"),
+                "<t>|sdf|</t>");
+    }
+
+    @Test
+    public void testGeneral3() throws Exception {
+        assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, -0 div 0)\"/>|"),
+                "<t>||</t>");
+    }
+
+    @Test
+    public void testGeneral4() throws Exception {
+        assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 0 div 0)\"/>|"),
+                "<t>||</t>");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8046817/GenerateEnumSchema.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ *
+ * 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 8046817
+ * @summary schemagen fails to generate xsd for enum types
+ * @run main/othervm GenerateEnumSchema
+ */
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Paths;
+import java.util.Scanner;
+
+public class GenerateEnumSchema {
+
+    private static final String SCHEMA_OUTPUT_FILENAME = "schema1.xsd";
+    private static final File schemaOutputFile = new File(SCHEMA_OUTPUT_FILENAME);
+
+    public static void main(String[] args) throws Exception, IOException {
+        //Check schema generation for class type
+        runSchemaGen("TestClassType.java");
+        checkIfSchemaGenerated();
+        checkSchemaContent("<xs:complexType name=\"testClassType\">");
+        checkSchemaContent("<xs:element name=\"a\" type=\"xs:int\"/>");
+        schemaOutputFile.delete();
+        //Check schema generation for enum type
+        runSchemaGen("TestEnumType.java");
+        checkIfSchemaGenerated();
+        checkSchemaContent("<xs:simpleType name=\"testEnumType\">");
+        checkSchemaContent("<xs:enumeration value=\"ONE\"/>");
+        checkSchemaContent("<xs:enumeration value=\"TWO\"/>");
+        checkSchemaContent("<xs:enumeration value=\"THREE\"/>");
+        schemaOutputFile.delete();
+    }
+
+    private static void checkIfSchemaGenerated() {
+        if (!schemaOutputFile.exists()) {
+            throw new RuntimeException("FAIL:" + SCHEMA_OUTPUT_FILENAME + " was not generated by schemagen tool");
+        }
+    }
+
+    private static void checkSchemaContent(String exp_token) throws FileNotFoundException {
+        System.out.print("Check if generated schema contains '" + exp_token + "' string: ");
+        try (Scanner scanner = new Scanner(schemaOutputFile)) {
+            if (scanner.findWithinHorizon(exp_token, 0) != null) {
+                System.out.println("OK");
+                return;
+            }
+        }
+        System.out.println("FAIL");
+        throw new RuntimeException("The '" + exp_token + "' is not found in generated schema");
+
+    }
+
+    private static String getClassFilePath(String filename) {
+        String testSrc = System.getProperty("test.src");
+        if (testSrc == null) {
+            testSrc = ".";
+        }
+        return Paths.get(testSrc).resolve(filename).toString();
+    }
+
+    private static String getSchemagen() {
+        String javaHome = System.getProperty("java.home");
+        if (javaHome.endsWith("jre")) {
+            javaHome = new File(javaHome).getParent();
+        }
+        String schemagen = javaHome + File.separator + "bin" + File.separator + "schemagen";
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            schemagen = schemagen.concat(".exe");
+        }
+        return schemagen;
+    }
+
+    private static void logOutput(Process p) throws IOException {
+        BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        String s = r.readLine();
+        while (s != null) {
+            System.out.println(s.trim());
+            s = r.readLine();
+        }
+    }
+
+    private static void runSchemaGen(String classFile) {
+        String schemagen = getSchemagen();
+
+        try {
+            System.out.println("Call to schemagen: " + schemagen + " " + classFile);
+            String[] schemagen_args = {
+                schemagen,
+                getClassFilePath(classFile)
+            };
+
+            ProcessBuilder pb = new ProcessBuilder(schemagen_args);
+            pb.redirectErrorStream(true);
+            Process p = pb.start();
+            logOutput(p);
+            int result = p.waitFor();
+            p.destroy();
+
+            if (result != 0) {
+                throw new RuntimeException("schemagen failed");
+            }
+        } catch (IOException | InterruptedException e) {
+            System.err.println("Can't run schemagen tool. Exception:");
+            e.printStackTrace(System.err);
+            throw new RuntimeException("Error launching schemagen tool");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8046817/TestClassType.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public class TestClassType {
+    public int a;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8046817/TestEnumType.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum(String.class)
+public enum TestEnumType {
+    ONE, TWO, THREE
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+package jdk.testlibrary;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+/**
+ * Common library for various test jar file utility functions.
+ */
+public final class JarUtils {
+
+    /**
+     * Create jar file with specified files.
+     */
+    public static void createJar(String dest, String... files)
+            throws IOException {
+        try (JarOutputStream jos = new JarOutputStream(
+                new FileOutputStream(dest), new Manifest())) {
+            for (String file : files) {
+                System.out.println(String.format("Adding %s to %s",
+                        file, dest));
+
+                // add an archive entry, and write a file
+                jos.putNextEntry(new JarEntry(file));
+                try (FileInputStream fis = new FileInputStream(file)) {
+                    fis.transferTo(jos);
+                }
+            }
+        }
+        System.out.println();
+    }
+
+    /**
+     * Add specified files to existing jar file.
+     */
+    public static void updateJar(String src, String dest, String... files)
+            throws IOException {
+        try (JarOutputStream jos = new JarOutputStream(
+                new FileOutputStream(dest))) {
+
+            // copy each old entry into destination unless the entry name
+            // is in the updated list
+            List<String> updatedFiles = new ArrayList<>();
+            try (JarFile srcJarFile = new JarFile(src)) {
+                Enumeration entries = srcJarFile.entries();
+                while (entries.hasMoreElements()) {
+                    JarEntry entry = (JarEntry) entries.nextElement();
+                    String name = entry.getName();
+                    boolean found = false;
+                    for (String file : files) {
+                        if (name.equals(file)) {
+                            updatedFiles.add(file);
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if (found) {
+                        System.out.println(String.format("Updating %s with %s",
+                                dest, name));
+                        jos.putNextEntry(new JarEntry(name));
+                        try (FileInputStream fis = new FileInputStream(name)) {
+                            fis.transferTo(jos);
+                        }
+                    } else {
+                        System.out.println(String.format("Copying %s to %s",
+                                name, dest));
+                        jos.putNextEntry(entry);
+                        srcJarFile.getInputStream(entry).transferTo(jos);
+                    }
+                }
+            }
+
+            // append new files
+            for (String file : files) {
+                if (!updatedFiles.contains(file)) {
+                    System.out.println(String.format("Adding %s with %s",
+                            dest, file));
+                    jos.putNextEntry(new JarEntry(file));
+                    try (FileInputStream fis = new FileInputStream(file)) {
+                        fis.transferTo(jos);
+                    }
+                }
+            }
+        }
+        System.out.println();
+    }
+
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -30,6 +30,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.concurrent.CountDownLatch;
 import java.util.Map;
@@ -378,4 +379,40 @@
         }
         return cmd.toString().trim();
     }
+
+    /**
+     * Executes a process, waits for it to finish, prints the process output
+     * to stdout, and returns the process output.
+     *
+     * The process will have exited before this method returns.
+     *
+     * @param cmds The command line to execute.
+     * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+     */
+    public static OutputAnalyzer executeCommand(String... cmds)
+            throws Throwable {
+        String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
+        System.out.println("Command line: [" + cmdLine + "]");
+        OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
+        System.out.println(analyzer.getOutput());
+        return analyzer;
+    }
+
+    /**
+     * Executes a process, waits for it to finish, prints the process output
+     * to stdout and returns the process output.
+     *
+     * The process will have exited before this method returns.
+     *
+     * @param pb The ProcessBuilder to execute.
+     * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+     */
+    public static OutputAnalyzer executeCommand(ProcessBuilder pb)
+            throws Throwable {
+        String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
+        System.out.println("Command line: [" + cmdLine + "]");
+        OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
+        System.out.println(analyzer.getOutput());
+        return analyzer;
+    }
 }
--- a/jdk/test/sun/security/krb5/auto/Context.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/sun/security/krb5/auto/Context.java	Wed Jul 05 20:17:15 2017 +0200
@@ -23,6 +23,7 @@
 
 import com.sun.security.auth.module.Krb5LoginModule;
 
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
@@ -584,7 +585,12 @@
             out.name = name + " as " + out.cred.getName().toString();
             return out;
         } catch (PrivilegedActionException pae) {
-            throw pae.getException();
+            Exception e = pae.getException();
+            if (e instanceof InvocationTargetException) {
+                throw (Exception)((InvocationTargetException) e).getTargetException();
+            } else {
+                throw e;
+            }
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/ForwardableCheck.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ *
+ * 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 8022582
+ * @summary Relax response flags checking in sun.security.krb5.KrbKdcRep.check.
+ * @compile -XDignore.symbol.file ForwardableCheck.java
+ * @run main/othervm ForwardableCheck
+ */
+
+import org.ietf.jgss.GSSException;
+import sun.security.jgss.GSSUtil;
+
+import java.util.Arrays;
+
+public class ForwardableCheck {
+
+    public static void main(String[] args) throws Exception {
+        OneKDC kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+
+        // USER can impersonate someone else
+        kdc.setOption(KDC.Option.ALLOW_S4U2SELF,
+                Arrays.asList(OneKDC.USER + "@" + OneKDC.REALM));
+        // USER2 is sensitive
+        kdc.setOption(KDC.Option.SENSITIVE_ACCOUNTS,
+                Arrays.asList(OneKDC.USER2 + "@" + OneKDC.REALM));
+
+        Context c;
+
+        // USER2 is sensitive but it's still able to get a normal ticket
+        c = Context.fromUserPass(OneKDC.USER2, OneKDC.PASS2, false);
+
+        // ... and connect to another account
+        c.startAsClient(OneKDC.USER, GSSUtil.GSS_KRB5_MECH_OID);
+        c.x().requestCredDeleg(true);
+        c.x().requestMutualAuth(false);
+
+        c.take(new byte[0]);
+
+        if (!c.x().isEstablished()) {
+            throw new Exception("Context should have been established");
+        }
+
+        // ... but will not be able to delegate itself
+        if (c.x().getCredDelegState()) {
+            throw new Exception("Impossible");
+        }
+
+        // Although USER is allowed to impersonate other people,
+        // it cannot impersonate USER2 coz it's sensitive.
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        try {
+            c.impersonate(OneKDC.USER2);
+            throw new Exception("Should fail");
+        } catch (GSSException e) {
+            e.printStackTrace();
+        }
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/KDC.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java	Wed Jul 05 20:17:15 2017 +0200
@@ -198,6 +198,10 @@
          * Krb5.KDC_ERR_POLICY will be send for S4U2proxy request.
          */
         ALLOW_S4U2PROXY,
+        /**
+         * Sensitive accounts can never be delegated.
+         */
+        SENSITIVE_ACCOUNTS,
     };
 
     static {
@@ -643,7 +647,7 @@
         try {
             System.out.println(realm + "> " + tgsReq.reqBody.cname +
                     " sends TGS-REQ for " +
-                    service);
+                    service + ", " + tgsReq.reqBody.kdcOptions);
             KDCReqBody body = tgsReq.reqBody;
             int[] eTypes = KDCReqBodyDotEType(body);
             int e2 = eTypes[0];     // etype for outgoing session key
@@ -719,7 +723,13 @@
             boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
             if (body.kdcOptions.get(KDCOptions.FORWARDABLE)
                     && allowForwardable) {
-                bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
+                List<String> sensitives = (List<String>)
+                        options.get(Option.SENSITIVE_ACCOUNTS);
+                if (sensitives != null && sensitives.contains(cname.toString())) {
+                    // Cannot make FORWARDABLE
+                } else {
+                    bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
+                }
             }
             if (body.kdcOptions.get(KDCOptions.FORWARDED) ||
                     etp.flags.get(Krb5.TKT_OPTS_FORWARDED)) {
@@ -824,7 +834,8 @@
                     t,
                     edata);
             System.out.println("     Return " + tgsRep.cname
-                    + " ticket for " + tgsRep.ticket.sname);
+                    + " ticket for " + tgsRep.ticket.sname + ", flags "
+                    + tFlags);
 
             DerOutputStream out = new DerOutputStream();
             out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
@@ -869,7 +880,7 @@
         try {
             System.out.println(realm + "> " + asReq.reqBody.cname +
                     " sends AS-REQ for " +
-                    service);
+                    service + ", " + asReq.reqBody.kdcOptions);
 
             KDCReqBody body = asReq.reqBody;
 
@@ -926,7 +937,13 @@
             //body.from
             boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
             if (body.kdcOptions.get(KDCOptions.FORWARDABLE)) {
-                bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
+                List<String> sensitives = (List<String>)
+                        options.get(Option.SENSITIVE_ACCOUNTS);
+                if (sensitives != null && sensitives.contains(body.cname.toString())) {
+                    // Cannot make FORWARDABLE
+                } else {
+                    bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
+                }
             }
             if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
                 bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
@@ -1102,7 +1119,8 @@
                     edata);
 
             System.out.println("     Return " + asRep.cname
-                    + " ticket for " + asRep.ticket.sname);
+                    + " ticket for " + asRep.ticket.sname + ", flags "
+                    + tFlags);
 
             DerOutputStream out = new DerOutputStream();
             out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
--- a/jdk/test/sun/security/krb5/config/ParseConfig.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/sun/security/krb5/config/ParseConfig.java	Wed Jul 05 20:17:15 2017 +0200
@@ -22,7 +22,7 @@
  */
 /*
  * @test
- * @bug 6319046
+ * @bug 6319046 8055045
  * @compile -XDignore.symbol.file ParseConfig.java
  * @run main/othervm ParseConfig
  * @summary Problem with parsing krb5.conf
@@ -32,7 +32,8 @@
 
 public class ParseConfig {
     public static void main(String[] args) throws Exception {
-        System.setProperty("java.security.krb5.conf", System.getProperty("test.src", ".") +"/krb5.conf");
+        System.setProperty("java.security.krb5.conf",
+                System.getProperty("test.src", ".") + "/krb5.conf");
         Config config = Config.getInstance();
         config.listTable();
 
@@ -44,5 +45,11 @@
                         expected + "\"");
             }
         }
+
+        // JDK-8055045: IOOBE when reading an empty value
+        config.get("empty1", "NOVAL.COM");
+        config.get("empty2", "NOVAL.COM");
+        config.get("quote1", "NOVAL.COM");
+        config.get("quote2", "NOVAL.COM");
     }
 }
--- a/jdk/test/sun/security/krb5/config/krb5.conf	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/sun/security/krb5/config/krb5.conf	Wed Jul 05 20:17:15 2017 +0200
@@ -27,3 +27,9 @@
 	}
    }
 
+   NOVAL.COM = {
+        empty1 =
+        empty2 =.
+        quote1 = "
+        quote2 = '
+   }
--- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java	Wed Jul 05 20:17:15 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -58,7 +58,12 @@
 
     static final String defaultPolicyId = "2.3.4.5";
 
-    static class Handler implements HttpHandler {
+    static class Handler implements HttpHandler, AutoCloseable {
+
+        private final HttpServer httpServer;
+        private final String keystore;
+
+        @Override
         public void handle(HttpExchange t) throws IOException {
             int len = 0;
             for (String h: t.getRequestHeaders().keySet()) {
@@ -136,7 +141,9 @@
             // Write TSResponse
             System.err.println("\nResponse\n===================");
             KeyStore ks = KeyStore.getInstance("JKS");
-            ks.load(new FileInputStream(TSKS), "changeit".toCharArray());
+            try (FileInputStream fis = new FileInputStream(keystore)) {
+                ks.load(fis, "changeit".toCharArray());
+            }
 
             String alias = "ts";
             if (path == 6) alias = "tsbad1";
@@ -240,33 +247,74 @@
 
             return out.toByteArray();
         }
+
+        private Handler(HttpServer httpServer, String keystore) {
+            this.httpServer = httpServer;
+            this.keystore = keystore;
+        }
+
+        /**
+         * Initialize TSA instance.
+         *
+         * Extended Key Info extension of certificate that is used for
+         * signing TSA responses should contain timeStamping value.
+         */
+        static Handler init(int port, String keystore) throws IOException {
+            HttpServer httpServer = HttpServer.create(
+                    new InetSocketAddress(port), 0);
+            Handler tsa = new Handler(httpServer, keystore);
+            httpServer.createContext("/", tsa);
+            return tsa;
+        }
+
+        /**
+         * Start TSA service.
+         */
+        void start() {
+            httpServer.start();
+        }
+
+        /**
+         * Stop TSA service.
+         */
+        void stop() {
+            httpServer.stop(0);
+        }
+
+        /**
+         * Return server port number.
+         */
+        int getPort() {
+            return httpServer.getAddress().getPort();
+        }
+
+        @Override
+        public void close() throws Exception {
+            stop();
+        }
     }
 
     public static void main(String[] args) throws Exception {
-
-        Handler h = new Handler();
-        HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
-        int port = server.getAddress().getPort();
-        HttpContext ctx = server.createContext("/", h);
-        server.start();
+        try (Handler tsa = Handler.init(0, TSKS);) {
+            tsa.start();
+            int port = tsa.getPort();
 
-        String cmd = null;
-        // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
-        // nonce generation in timestamping request. Not avaibale on
-        // Windows and defaults to thread seed generator, not too bad.
-        if (System.getProperty("java.home").endsWith("jre")) {
-            cmd = System.getProperty("java.home") + "/../bin/jarsigner";
-        } else {
-            cmd = System.getProperty("java.home") + "/bin/jarsigner";
-        }
+            String cmd;
+            // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
+            // nonce generation in timestamping request. Not avaibale on
+            // Windows and defaults to thread seed generator, not too bad.
+            if (System.getProperty("java.home").endsWith("jre")) {
+                cmd = System.getProperty("java.home") + "/../bin/jarsigner";
+            } else {
+                cmd = System.getProperty("java.home") + "/bin/jarsigner";
+            }
 
-        cmd +=  " " + System.getProperty("test.tool.vm.opts") +
-                " -J-Djava.security.egd=file:/dev/./urandom" +
-                " -debug -keystore " + TSKS + " -storepass changeit" +
-                " -tsa http://localhost:" + port + "/%d" +
-                " -signedjar new_%d.jar " + JAR + " old";
+            cmd += " " + System.getProperty("test.tool.vm.opts")
+                    + " -J-Djava.security.egd=file:/dev/./urandom"
+                    + " -debug -keystore " + TSKS + " -storepass changeit"
+                    + " -tsa http://localhost:" + port + "/%d"
+                    + " -signedjar new_%d.jar " + JAR + " old";
 
-        try {
             if (args.length == 0) {         // Run this test
                 jarsigner(cmd, 0, true);    // Success, normal call
                 jarsigner(cmd, 1, false);   // These 4 should fail
@@ -287,8 +335,6 @@
                 System.err.println("Press Enter to quit server");
                 System.in.read();
             }
-        } finally {
-            server.stop(0);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary The test signs and verifies a jar file with -tsacert option
+ * @library /lib/testlibrary
+ * @run main TsacertOptionTest
+ */
+public class TsacertOptionTest {
+
+    private static final String FS = System.getProperty("file.separator");
+    private static final String JAVA_HOME = System.getProperty("java.home");
+    private static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS
+            + "keytool";
+    private static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS
+            + "jarsigner";
+    private static final String UNSIGNED_JARFILE = "unsigned.jar";
+    private static final String SIGNED_JARFILE = "signed.jar";
+    private static final String FILENAME = TsacertOptionTest.class.getName()
+            + ".txt";
+    private static final String PASSWORD = "changeit";
+    private static final String KEYSTORE = "ks.jks";
+    private static final String SIGNING_KEY_ALIAS = "sign_alias";
+    private static final String TSA_KEY_ALIAS = "ts";
+    private static final String KEY_ALG = "RSA";
+    private static final int KEY_SIZE = 2048;
+    private static final int VALIDITY = 365;
+    private static final String WARNING = "Warning:";
+    private static final String JAR_SIGNED = "jar signed.";
+    private static final String JAR_VERIFIED = "jar verified.";
+
+    /**
+     * The test signs and verifies a jar file with -tsacert option,
+     * and checks that no warning was shown.
+     * A certificate that is addressed in -tsacert option contains URL to TSA
+     * in Subject Information Access extension.
+     */
+    public static void main(String[] args) throws Throwable {
+        TsacertOptionTest test = new TsacertOptionTest();
+        test.start();
+    }
+
+    void start() throws Throwable {
+        // create a jar file that contains one file
+        Utils.createFiles(FILENAME);
+        JarUtils.createJar(UNSIGNED_JARFILE, FILENAME);
+
+        // look for free network port for TSA service
+        int port = jdk.testlibrary.Utils.getFreePort();
+        String host = jdk.testlibrary.Utils.getHostname();
+        String tsaUrl = "http://" + host + ":" + port;
+
+        // create key pair for jar signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", SIGNING_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // create key pair for TSA service
+        // SubjectInfoAccess extension contains URL to TSA service
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-v",
+                "-alias", TSA_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=TSA",
+                "-ext", "ExtendedkeyUsage:critical=timeStamping",
+                "-ext", "SubjectInfoAccess=timeStamping:URI:" + tsaUrl,
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        try (TimestampCheck.Handler tsa = TimestampCheck.Handler.init(port,
+                KEYSTORE);) {
+
+            // start TSA
+            tsa.start();
+
+            // sign jar file
+            // specify -tsadigestalg option because
+            // TSA server uses SHA-1 digest algorithm
+             OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                    "-verbose",
+                    "-keystore", KEYSTORE,
+                    "-storepass", PASSWORD,
+                    "-keypass", PASSWORD,
+                    "-signedjar", SIGNED_JARFILE,
+                    "-tsacert", TSA_KEY_ALIAS,
+                    "-tsadigestalg", "SHA-1",
+                    UNSIGNED_JARFILE,
+                    SIGNING_KEY_ALIAS);
+
+            analyzer.shouldHaveExitValue(0);
+            analyzer.stdoutShouldNotContain(WARNING);
+            analyzer.shouldContain(JAR_SIGNED);
+
+            // verify signed jar
+            analyzer = ProcessTools.executeCommand(JARSIGNER,
+                    "-verbose",
+                    "-verify",
+                    "-keystore", KEYSTORE,
+                    "-storepass", PASSWORD,
+                    SIGNED_JARFILE);
+
+            analyzer.shouldHaveExitValue(0);
+            analyzer.stdoutShouldNotContain(WARNING);
+            analyzer.shouldContain(JAR_VERIFIED);
+        }
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/Utils.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+
+/**
+ * Helper class.
+ */
+public class Utils {
+
+    static void createFiles(String... filenames) throws IOException {
+        for (String filename : filenames) {
+            new File(filename).createNewFile();
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,149 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for aliasNotInStore warning
+ * @library /lib/testlibrary ../
+ * @run main AliasNotInStoreTest
+ */
+public class AliasNotInStoreTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that contains signed entries
+     * that are not signed by any alias in keystore (aliasNotInStore).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        AliasNotInStoreTest test = new AliasNotInStoreTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        Utils.createFiles(FIRST_FILE, SECOND_FILE);
+        System.out.println(String.format("Create a %s that contains %s",
+                new Object[]{UNSIGNED_JARFILE, FIRST_FILE}));
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create first key pair for signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", FIRST_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", BOTH_KEYS_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=First",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // create second key pair for signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", SECOND_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", BOTH_KEYS_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Second",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // sign jar with first key
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", BOTH_KEYS_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                FIRST_KEY_ALIAS);
+
+        checkSigning(analyzer);
+
+        System.out.println(String.format("Copy %s to %s, and add %s",
+                new Object[] {SIGNED_JARFILE, UPDATED_SIGNED_JARFILE,
+                    SECOND_FILE}));
+
+        JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
+
+        // sign jar with second key
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", BOTH_KEYS_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE,
+                SECOND_KEY_ALIAS);
+
+        checkSigning(analyzer);
+
+        // create keystore that contains only first key
+        ProcessTools.executeCommand(KEYTOOL,
+                "-importkeystore",
+                "-srckeystore", BOTH_KEYS_KEYSTORE,
+                "-srcalias", FIRST_KEY_ALIAS,
+                "-srcstorepass", PASSWORD,
+                "-srckeypass", PASSWORD,
+                "-destkeystore", FIRST_KEY_KEYSTORE,
+                "-destalias", FIRST_KEY_ALIAS,
+                "-deststorepass", PASSWORD,
+                "-destkeypass", PASSWORD).shouldHaveExitValue(0);
+
+        // verify jar with keystore that contains only first key in strict mode,
+        // so there is signed entry (FirstClass.class) that is not signed
+        // by any alias in the keystore
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", FIRST_KEY_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING,
+                ALIAS_NOT_IN_STORE_VERIFYING_WARNING);
+
+        // verify jar with keystore that contains only first key in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", FIRST_KEY_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE);
+
+        int expectedExitCode = ALIAS_NOT_IN_STORE_EXIT_CODE
+                + CHAIN_NOT_VALIDATED_EXIT_CODE;
+        checkVerifying(analyzer, expectedExitCode,
+                CHAIN_NOT_VALIDATED_VERIFYING_WARNING,
+                ALIAS_NOT_IN_STORE_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,106 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for badExtendedKeyUsage warning
+ * @library /lib/testlibrary ../
+ * @run main BadExtendedKeyUsageTest
+ */
+public class BadExtendedKeyUsageTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose signer certificate's ExtendedKeyUsage extension
+     * doesn't allow code signing (badExtendedKeyUsage).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        BadExtendedKeyUsageTest test = new BadExtendedKeyUsageTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create a certificate whose signer certificate's
+        // ExtendedKeyUsage extension doesn't allow code signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-ext", "ExtendedkeyUsage=serverAuth",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING);
+
+        // verity signed jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, BAD_EXTENDED_KEY_USAGE_EXIT_CODE,
+                BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for badKeyUsage warning
+ * @library /lib/testlibrary ../
+ * @ignore until 8026393 is fixed
+ * @run main BadKeyUsageTest
+ */
+public class BadKeyUsageTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose signer certificate's KeyUsage extension
+     * doesn't allow code signing (badKeyUsage).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        BadKeyUsageTest test = new BadKeyUsageTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create a certificate whose signer certificate's KeyUsage extension
+        // doesn't allow code signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-ext", "KeyUsage=keyAgreement",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, BAD_KEY_USAGE_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, BAD_KEY_USAGE_VERIFYING_WARNING);
+
+        // verify signed jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, BAD_KEY_USAGE_EXIT_CODE,
+                BAD_KEY_USAGE_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Base64;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for badNetscapeCertType warning
+ * @library /lib/testlibrary ../
+ * @run main BadNetscapeCertTypeTest
+ */
+public class BadNetscapeCertTypeTest extends Test {
+
+    private static final String NETSCAPE_KEYSTORE_BASE64 = TEST_SOURCES + FS
+            + "bad_netscape_cert_type.jks.base64";
+
+    private static final String NETSCAPE_KEYSTORE
+            = "bad_netscape_cert_type.jks";
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose signer certificate's NetscapeCertType extension
+     * doesn't allow code signing (badNetscapeCertType).
+     * Warning message is expected.
+     * Run bad_netscape_cert_type.sh script to create bad_netscape_cert_type.jks
+     */
+    public static void main(String[] args) throws Throwable {
+
+        Files.write(Paths.get(NETSCAPE_KEYSTORE),
+                Base64.getMimeDecoder().decode(
+                    Files.readAllBytes(Paths.get(NETSCAPE_KEYSTORE_BASE64))));
+
+        BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verbose",
+                "-keystore", NETSCAPE_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, BAD_NETSCAPE_CERT_TYPE_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", NETSCAPE_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING);
+
+        // verify signed jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", NETSCAPE_KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, BAD_NETSCAPE_CERT_TYPE_EXIT_CODE,
+                BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,180 @@
+/*
+ * 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 java.io.File;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for chainNotValidated warning
+ * @library /lib/testlibrary ../
+ * @run main ChainNotValidatedTest
+ */
+public class ChainNotValidatedTest extends Test {
+
+    private static final String CHAIN = "chain";
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose cert chain can't be correctly validated (chainNotValidated).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        ChainNotValidatedTest test = new ChainNotValidatedTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create self-signed certificate whose BasicConstraints extension
+        // is set to false, so the certificate may not be used
+        // as a parent certificate (certpath validation should fail)
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkeypair",
+                "-alias", CA_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=CA",
+                "-ext", "BasicConstraints:critical=ca:false",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // create a certificate that is signed by self-signed certificate
+        // despite of it may not be used as a parent certificate
+        // (certpath validation should fail)
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkeypair",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-ext", "BasicConstraints:critical=ca:false",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        ProcessTools.executeCommand(KEYTOOL,
+                "-certreq",
+                "-alias", KEY_ALIAS,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-file", CERT_REQUEST_FILENAME).shouldHaveExitValue(0);
+
+        ProcessTools.executeCommand(KEYTOOL,
+                "-gencert",
+                "-alias", CA_KEY_ALIAS,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-infile", CERT_REQUEST_FILENAME,
+                "-validity", Integer.toString(VALIDITY),
+                "-outfile", CERT_FILENAME).shouldHaveExitValue(0);
+
+        ProcessTools.executeCommand(KEYTOOL,
+                "-importcert",
+                "-alias", KEY_ALIAS,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-file", CERT_FILENAME).shouldHaveExitValue(0);
+
+        ProcessBuilder pb = new ProcessBuilder(KEYTOOL,
+                "-export",
+                "-rfc",
+                "-alias", KEY_ALIAS,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD);
+        pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
+        ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
+
+        pb = new ProcessBuilder(KEYTOOL,
+                "-export",
+                "-rfc",
+                "-alias", CA_KEY_ALIAS,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD);
+        pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
+        ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
+
+        // remove CA certificate
+        ProcessTools.executeCommand(KEYTOOL,
+                "-delete",
+                "-alias", CA_KEY_ALIAS,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD).shouldHaveExitValue(0);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-certchain", CHAIN,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-certchain", CHAIN,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+
+        // verify signed jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-certchain", CHAIN,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
+                CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for hasExpiredCert warning
+ * @library /lib/testlibrary ../
+ * @run main HasExpiredCertTest
+ */
+public class HasExpiredCertTest extends Test {
+
+    static final int SHORT_VALIDITY = 365;
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose signer certificate has expired (hasExpiredCert).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        HasExpiredCertTest test = new HasExpiredCertTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create key pair for jar signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-startdate", "-" + SHORT_VALIDITY * 2 + "d",
+                "-validity", Integer.toString(SHORT_VALIDITY))
+                .shouldHaveExitValue(0);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, HAS_EXPIRED_CERT_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, HAS_EXPIRED_CERT_VERIFYING_WARNING);
+
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE);
+
+        checkVerifying(analyzer, HAS_EXPIRED_CERT_EXIT_CODE,
+                HAS_EXPIRED_CERT_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,107 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for hasExpiringCert warning
+ * @library /lib/testlibrary ../
+ * @run main HasExpiringCertTest
+ */
+public class HasExpiringCertTest extends Test {
+
+    static final int SHORT_VALIDITY = 90; // less than 6 month
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose signer certificate will expire within six months (hasExpiringCert).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        HasExpiringCertTest test = new HasExpiringCertTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create key pair for jar signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-validity", Integer.toString(SHORT_VALIDITY))
+                .shouldHaveExitValue(0);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", KEYSTORE,
+                "-verbose",
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, HAS_EXPIRING_CERT_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkVerifying(analyzer, 0, HAS_EXPIRING_CERT_VERIFYING_WARNING);
+
+        // verify signed jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkVerifying(analyzer, 0, HAS_EXPIRING_CERT_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for hasUnsignedEntry warning
+ * @library /lib/testlibrary ../
+ * @run main HasUnsignedEntryTest
+ */
+public class HasUnsignedEntryTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that contains unsigned entries
+     * which have not been integrity-checked (hasUnsignedEntry).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        HasUnsignedEntryTest test = new HasUnsignedEntryTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        System.out.println(String.format("Create a %s that contains %s",
+                UNSIGNED_JARFILE, FIRST_FILE));
+        Utils.createFiles(FIRST_FILE, SECOND_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create key pair for signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer);
+
+        System.out.println(String.format("Copy %s to %s, and add %s.class, "
+                + "so it contains unsigned entry",
+                new Object[]{SIGNED_JARFILE, UPDATED_SIGNED_JARFILE,
+                    SECOND_FILE}));
+
+        JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
+
+        // verify jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE);
+
+        checkVerifying(analyzer, 0, HAS_UNSIGNED_ENTRY_VERIFYING_WARNING);
+
+        // verify jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE);
+
+        checkVerifying(analyzer, HAS_UNSIGNED_ENTRY_EXIT_CODE,
+                HAS_UNSIGNED_ENTRY_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,169 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Checks if jarsigner prints appropriate warnings
+ * @library /lib/testlibrary ../
+ * @run main MultipleWarningsTest
+ */
+public class MultipleWarningsTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that:
+     *   - contains entries whose signer certificate has expired
+     *   - contains entries whose signer certificate's ExtendedKeyUsage
+     *     extension doesn't allow code signing
+     *   - contains unsigned entries which have not been integrity-checked
+     *   - contains signed entries which are not signed by the specified alias
+     * Warning messages are expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        MultipleWarningsTest test = new MultipleWarningsTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        Utils.createFiles(FIRST_FILE, SECOND_FILE);
+
+        // create a jar file that contains one class file
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create first expired certificate
+        // whose ExtendedKeyUsage extension does not allow code signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", FIRST_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=First",
+                "-ext", "ExtendedkeyUsage=serverAuth",
+                "-startdate", "-" + VALIDITY * 2 + "d",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // create second expired certificate
+        // whose KeyUsage extension does not allow code signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", SECOND_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Second",
+                "-ext", "ExtendedkeyUsage=serverAuth",
+                "-startdate", "-" + VALIDITY * 2 + "d",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // sign jar with first key
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                FIRST_KEY_ALIAS);
+
+        checkSigning(analyzer, HAS_EXPIRED_CERT_SIGNING_WARNING,
+                BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING);
+
+        // add a second class to created jar, so it contains unsigned entry
+        JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
+
+        // verify jar with second key
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE,
+                SECOND_KEY_ALIAS);
+
+        checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+                HAS_EXPIRED_CERT_VERIFYING_WARNING,
+                HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+                NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        // verify jar with second key in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE,
+                SECOND_KEY_ALIAS);
+
+        int expectedExitCode = HAS_EXPIRED_CERT_EXIT_CODE
+                + BAD_EXTENDED_KEY_USAGE_EXIT_CODE
+                + HAS_UNSIGNED_ENTRY_EXIT_CODE
+                + NOT_SIGNED_BY_ALIAS_EXIT_CODE;
+        checkVerifying(analyzer, expectedExitCode,
+                BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+                HAS_EXPIRED_CERT_VERIFYING_WARNING,
+                HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+                NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        // verify jar with non-exisiting alias
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE,
+                "bogus");
+
+        checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+                HAS_EXPIRED_CERT_VERIFYING_WARNING,
+                HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+                NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        // verify jar with non-exisiting alias in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                UPDATED_SIGNED_JARFILE,
+                "bogus");
+
+        checkVerifying(analyzer, expectedExitCode,
+                BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+                HAS_EXPIRED_CERT_VERIFYING_WARNING,
+                HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+                NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,114 @@
+/*
+ * 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 java.util.Date;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Checks warnings if -tsa and -tsacert options are not specified
+ * @library /lib/testlibrary ../
+ * @run main NoTimestampTest
+ */
+public class NoTimestampTest extends Test {
+
+    /**
+     * The test signs and verifies a jar file without -tsa and -tsacert options,
+     * and checks that proper warnings are shown.
+     */
+    public static void main(String[] args) throws Throwable {
+        NoTimestampTest test = new NoTimestampTest();
+        test.start();
+    }
+
+    private void start() throws Throwable {
+        String timezone = System.getProperty("user.timezone");
+        System.out.println(String.format("Timezone = %s", timezone));
+
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // calculate certificate expiration date
+        Date expirationDate = new Date(System.currentTimeMillis() + VALIDITY
+                * 24 * 60 * 60 * 1000L);
+
+        // create key pair
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-validity", Integer.toString(VALIDITY));
+
+        // sign jar file
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-J-Duser.timezone=" + timezone,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        String warning = String.format(NO_TIMESTAMP_SIGNING_WARN_TEMPLATE,
+                expirationDate);
+        checkSigning(analyzer, warning);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-J-Duser.timezone=" + timezone,
+                "-verify",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                KEY_ALIAS);
+
+        warning = String.format(NO_TIMESTAMP_VERIFYING_WARN_TEMPLATE, expirationDate);
+        checkVerifying(analyzer, 0, warning);
+
+        // verify signed jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-J-Duser.timezone=" + timezone,
+                "-verify",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkVerifying(analyzer, 0, warning);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,138 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for notSignedByAlias warning
+ * @library /lib/testlibrary ../
+ * @run main NotSignedByAliasTest
+ */
+public class NotSignedByAliasTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that contains signed entries
+     * which are not signed by the specified alias(es) (notSignedByAlias).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        NotSignedByAliasTest test = new NotSignedByAliasTest();
+        test.start();
+    }
+
+    protected void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create first key pair for signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", FIRST_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=First",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // create first key pair for signing
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", SECOND_KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Second",
+                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+        // sign jar with first key
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                FIRST_KEY_ALIAS);
+
+        checkSigning(analyzer);
+
+        // verify jar with second key
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                SECOND_KEY_ALIAS);
+
+        checkVerifying(analyzer, 0, NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        // verify jar with second key in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                SECOND_KEY_ALIAS);
+
+        checkVerifying(analyzer, NOT_SIGNED_BY_ALIAS_EXIT_CODE,
+                NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        // verify jar with non-existing alias
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                "bogus");
+
+        checkVerifying(analyzer, 0, NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        // verify jar with non-existing alias in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                "bogus");
+
+        checkVerifying(analyzer, NOT_SIGNED_BY_ALIAS_EXIT_CODE,
+                NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for notYetValidCert warning
+ * @library /lib/testlibrary ../
+ * @run main NotYetValidCertTest
+ */
+public class NotYetValidCertTest extends Test {
+
+    /**
+     * The test signs and verifies a jar that contains entries
+     * whose signer certificate is not yet valid (notYetValidCert).
+     * Warning message is expected.
+     */
+    public static void main(String[] args) throws Throwable {
+        NotYetValidCertTest test = new NotYetValidCertTest();
+        test.start();
+    }
+
+    protected void start() throws Throwable {
+        // create a jar file that contains one class file
+        Utils.createFiles(FIRST_FILE);
+        JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+        // create certificate that will be valid only tomorrow
+        ProcessTools.executeCommand(KEYTOOL,
+                "-genkey",
+                "-alias", KEY_ALIAS,
+                "-keyalg", KEY_ALG,
+                "-keysize", Integer.toString(KEY_SIZE),
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-dname", "CN=Test",
+                "-startdate", "+1d",
+                "-validity", Integer.toString(VALIDITY));
+
+        // sign jar
+        OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                "-signedjar", SIGNED_JARFILE,
+                UNSIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkSigning(analyzer, NOT_YET_VALID_CERT_SIGNING_WARNING);
+
+        // verify signed jar
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkVerifying(analyzer, 0, NOT_YET_VALID_CERT_VERIFYING_WARNING);
+
+        // verify jar in strict mode
+        analyzer = ProcessTools.executeCommand(JARSIGNER,
+                "-verify",
+                "-verbose",
+                "-strict",
+                "-keystore", KEYSTORE,
+                "-storepass", PASSWORD,
+                "-keypass", PASSWORD,
+                SIGNED_JARFILE,
+                KEY_ALIAS);
+
+        checkVerifying(analyzer, HAS_EXPIRED_CERT_EXIT_CODE,
+                NOT_YET_VALID_CERT_VERIFYING_WARNING);
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/Test.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,178 @@
+/*
+ * 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 jdk.testlibrary.OutputAnalyzer;
+
+/**
+ * Base class.
+ */
+public abstract class Test {
+
+    static final String TEST_SOURCES = System.getProperty("test.src", ".");
+    static final String TEST_CLASSES = System.getProperty("test.classes");
+    static final String FS = System.getProperty("file.separator");
+    static final String JAVA_HOME = System.getProperty("java.home");
+    static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS + "keytool";
+    static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS + "jarsigner";
+    static final String UNSIGNED_JARFILE = "unsigned.jar";
+    static final String SIGNED_JARFILE = "signed.jar";
+    static final String UPDATED_SIGNED_JARFILE = "updated_signed.jar";
+    static final String FIRST_FILE = "first.txt";
+    static final String SECOND_FILE = "second.txt";
+    static final String PASSWORD = "password";
+    static final String BOTH_KEYS_KEYSTORE = "both_keys.jks";
+    static final String FIRST_KEY_KEYSTORE = "first_key.jks";
+    static final String KEYSTORE = "keystore.jks";
+    static final String FIRST_KEY_ALIAS = "first";
+    static final String SECOND_KEY_ALIAS = "second";
+    static final String KEY_ALG = "RSA";
+    static final String KEY_ALIAS = "alias";
+    static final String CERT_REQUEST_FILENAME = "test.req";
+    static final String CERT_FILENAME = "test.crt";
+    static final String CA_KEY_ALIAS = "ca";
+    static final int KEY_SIZE = 2048;
+    static final int TIMEOUT = 6 * 60 * 1000;   // in millis
+    static final int VALIDITY = 365;
+
+    static final String WARNING = "Warning:";
+
+    static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
+            = "This jar contains entries "
+            + "whose certificate chain is not validated.";
+
+    static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING
+            = "This jar contains signed entries "
+            + "that are not signed by alias in this keystore.";
+
+    static final String BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING
+            = "The signer certificate's ExtendedKeyUsage extension "
+            + "doesn't allow code signing.";
+
+    static final String BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING
+            = "This jar contains entries whose signer certificate's "
+            + "ExtendedKeyUsage extension doesn't allow code signing.";
+
+    static final String BAD_KEY_USAGE_SIGNING_WARNING
+            = "The signer certificate's KeyUsage extension "
+            + "doesn't allow code signing.";
+
+    static final String BAD_KEY_USAGE_VERIFYING_WARNING
+            = "This jar contains entries whose signer certificate's KeyUsage "
+            + "extension doesn't allow code signing.";
+
+    static final String BAD_NETSCAPE_CERT_TYPE_SIGNING_WARNING
+            = "The signer certificate's NetscapeCertType extension "
+            + "doesn't allow code signing.";
+
+    static final String BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING
+            = "This jar contains entries "
+            + "whose signer certificate's NetscapeCertType extension "
+            + "doesn't allow code signing.";
+
+    static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING
+            = "The signer's certificate chain is not validated.";
+
+    static final String HAS_EXPIRING_CERT_SIGNING_WARNING
+            = "The signer certificate will expire within six months.";
+
+    static final String HAS_EXPIRING_CERT_VERIFYING_WARNING
+            = "This jar contains entries "
+            + "whose signer certificate will expire within six months.";
+
+    static final String HAS_EXPIRED_CERT_SIGNING_WARNING
+            = "The signer certificate has expired.";
+
+    static final String HAS_EXPIRED_CERT_VERIFYING_WARNING
+            = "This jar contains entries whose signer certificate has expired.";
+
+    static final String HAS_UNSIGNED_ENTRY_VERIFYING_WARNING
+            = "This jar contains unsigned entries "
+            + "which have not been integrity-checked.";
+
+    static final String NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING
+            = "This jar contains signed entries "
+            + "which are not signed by the specified alias(es).";
+
+    static final String NO_TIMESTAMP_SIGNING_WARN_TEMPLATE
+            = "No -tsa or -tsacert is provided "
+            + "and this jar is not timestamped. "
+            + "Without a timestamp, users may not be able to validate this jar "
+            + "after the signer certificate's expiration date "
+            + "(%1$tY-%1$tm-%1$td) or after any future revocation date.";
+
+    static final String NO_TIMESTAMP_VERIFYING_WARN_TEMPLATE
+            = "This jar contains signatures that does not include a timestamp. "
+            + "Without a timestamp, users may not be able to validate this jar "
+            + "after the signer certificate's expiration date "
+            + "(%1$tY-%1$tm-%1$td) or after any future revocation date.";
+
+    static final String NOT_YET_VALID_CERT_SIGNING_WARNING
+            = "The signer certificate is not yet valid.";
+
+    static final String NOT_YET_VALID_CERT_VERIFYING_WARNING
+            = "This jar contains entries "
+            + "whose signer certificate is not yet valid.";
+
+    static final String JAR_SIGNED = "jar signed.";
+
+    static final String JAR_VERIFIED = "jar verified.";
+
+    static final String JAR_VERIFIED_WITH_SIGNER_ERRORS
+            = "jar verified, with signer errors.";
+
+    static final int CHAIN_NOT_VALIDATED_EXIT_CODE = 4;
+    static final int HAS_EXPIRED_CERT_EXIT_CODE = 4;
+    static final int BAD_KEY_USAGE_EXIT_CODE = 8;
+    static final int BAD_EXTENDED_KEY_USAGE_EXIT_CODE = 8;
+    static final int BAD_NETSCAPE_CERT_TYPE_EXIT_CODE = 8;
+    static final int HAS_UNSIGNED_ENTRY_EXIT_CODE = 16;
+    static final int ALIAS_NOT_IN_STORE_EXIT_CODE = 32;
+    static final int NOT_SIGNED_BY_ALIAS_EXIT_CODE = 32;
+
+    protected void checkVerifying(OutputAnalyzer analyzer, int expectedExitCode,
+            String... warnings) {
+        analyzer.shouldHaveExitValue(expectedExitCode);
+        for (String warning : warnings) {
+            analyzer.shouldContain(warning);
+        }
+        if (warnings.length > 0) {
+            analyzer.shouldContain(WARNING);
+        }
+        if (expectedExitCode == 0) {
+            analyzer.shouldContain(JAR_VERIFIED);
+        } else {
+            analyzer.shouldContain(JAR_VERIFIED_WITH_SIGNER_ERRORS);
+        }
+    }
+
+    protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
+        analyzer.shouldHaveExitValue(0);
+        for (String warning : warnings) {
+            analyzer.shouldContain(warning);
+        }
+        if (warnings.length > 0) {
+            analyzer.shouldContain(WARNING);
+        }
+        analyzer.shouldContain(JAR_SIGNED);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.jks.base64	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,26 @@
+/u3+7QAAAAIAAAABAAAAAQAFYWxpYXMAAAFBpkwW0gAAAr0wggK5MA4GCisGAQQB
+KgIRAQEFAASCAqWkGJ3PPjYmWNKrV23Y1u413RMAkrRZ+1OLWYRcQt4jtxtIyEH5
+Ho5b9dy9XN9FBKlTOD4c2Pc1T43BLKXeuLu3uLLeIxgXFt0z9CLyGwdYZZ751kXr
+DQ99qY6aNQUO6SeE4Wdty0KPAqid6ZJ8bF7T6wsTZSvNhaBRzyFydEfG7bbUYjOl
+mWC44nlsu6VEU3o9RQpcm1gIMwradOaIVT/HoB2bKmAv8gHqI6kreiEZwTdZkSAI
+IRi2vt1RPllXt5hgjDxUfZe8XOYYweR4Vt2/jVuKLJ80DNTu/9SeUD88zQAz53k4
+r3nRhv6TRcPm6tV/Fh92XLHiskL+TAzTfm+bUAudPCCVxN+yRtxvAgA+UhdV/SuM
+Zn5F6nrmP+YJG1hmprgCJIJJaCEXa9RXYC+vIVpO0WVNRuGlGm+/1afnOuQC8Wss
+ShXwjkaqTwAhqBFq7eYmmP8BK3gflYrt2zDLXvhl4ndVvMhMthFJ3ZvLh2LWpqLI
+/n8EMCf8US3lIEFk9DTHBZjffiHkqK2e7+FXEpG3xrgE6ZYLMdbd5Pb3YjZfhQx+
+ZTtiEFzYSaEGhacek/m7dRq1qmwgFsytng2OdWZe2ln8LJY0odr1dGUfJHfgafvi
+tlfbkg/rgjONtwliChDggbkUwnerrj/D/zrdEufUvfyltSshhHXRNDD3fH6spmEk
+hHKgxEc4yvxqJxzdMGtuib355aSfNegyl+GsnsKzXQCVEK2h3BLTQObzaD+8NZ12
+LQHvbrCiaS34vxJ3rEC+a+SW7itZp0aCdXMWdMJNkRKqyLBD3vG3zN05sN3XrhEM
+8BRT020TWY00tbVFbbBFheYLQRgTjrQtr0Yt6UHWBZc4N20crDLcSH5gqcCOVpla
+1Y2uqFEn8yqrGRwn/kgfNgAAAAEABVguNTA5AAABtTCCAbEwggEaoAMCAQICCQDH
+cEuVvzCuqzANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARUZXN0MB4XDTEzMTAx
+MTA2NTUwNloXDTIzMTAwOTA2NTUwNlowDzENMAsGA1UEAwwEVGVzdDCBnzANBgkq
+hkiG9w0BAQEFAAOBjQAwgYkCgYEA8hOfp2Dcnvt//ZZQAja9TRiwKqXVS+TiYE3S
+gngCBjIi+YYdo0DsUeO5MBfE6uvCWOr5lwAR/u1iaJOhIoGJDiGoPasZlt+yIgtR
+LzA7j2q+1q6kcwiVxfikI3aUgHV/QsybTriT4Bf7TQNKtJG23MQa4sD7+PjtCWD7
+p3cHTfkCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgeAMA0GCSqGSIb3DQEBBQUA
+A4GBAKoDlTJ8wLRA7G8XdGm4gv733n1cSQzlkcsjfOO6/mA5Jvu8tyFNq9HTf9AT
+VXbrbGcUYJjhzSSY3w5apXK1kXyqTB1LUNEJ45WnmciqSSecVTpJz9TuegyoX0Zf
+HScSgqfDmjqoiiFiNCgn3ZEJ85ykGvoFYGH+php+BVi3S0bj5E/jRpyV3vNnii/S
+wJDSAXF6bYU=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.sh	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+#!/bin/sh
+
+# This script creates JKS keystore with a certificate
+# that contains Netscape Certificate Type extension
+# that does not allow code signing
+# The keystore is used by BadNetscapeCertTypeTest.java test
+
+rm -rf keystore.jks
+echo "nsCertType = client" > ext.cfg
+
+openssl req -new -out cert.req -keyout key.pem -days 3650 \
+    -passin pass:password -passout pass:password -subj "/CN=Test"
+openssl x509 -in cert.req -out cert.pem -req -signkey key.pem -days 3650 \
+    -passin pass:password -extfile ext.cfg
+openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 \
+    -passin pass:password -passout pass:password -name alias
+
+${JAVA_HOME}/bin/keytool -importkeystore \
+    -srckeystore keystore.p12 -srcstoretype pkcs12 \
+    -srcstorepass password -alias alias \
+    -destkeystore bad_netscape_cert_type.jks -deststoretype jks \
+    -deststorepass password -destalias alias \
+
+openssl base64 < bad_netscape_cert_type.jks > bad_netscape_cert_type.jks.base64
+rm -rf cert.req key.pem cert.pem keystore.p12 ext.cfg bad_netscape_cert_type.jks
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * 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 8042397
+ * @summary Unit test for jmap utility test heap configuration reader
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @build JMapHeapConfigTest LingeredApp TmtoolTestScenario
+ * @run main JMapHeapConfigTest
+ */
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import jdk.testlibrary.Utils;
+
+public class JMapHeapConfigTest {
+
+    static final String expectedJMapValues[] = {
+        "MinHeapFreeRatio",
+        "MaxHeapFreeRatio",
+        "MaxHeapSize",
+        "NewSize",
+        "MaxNewSize",
+        "OldSize",
+        "NewRatio",
+        "SurvivorRatio",
+        "MetaspaceSize",
+        "CompressedClassSpaceSize",
+        "G1HeapRegionSize"};
+
+    // ignoring MaxMetaspaceSize
+
+    private static Map<String, String> parseJMapOutput(List<String> jmapOutput) {
+        Map<String, String> heapConfigMap = new HashMap<String, String>();
+        boolean shouldParse = false;
+
+        for (String line : jmapOutput) {
+            line = line.trim();
+
+            if (line.startsWith("Heap Configuration:")) {
+                shouldParse = true;
+                continue;
+            }
+
+            if (line.startsWith("Heap Usage:")) {
+                shouldParse = false;
+                continue;
+            }
+
+            if (shouldParse && !line.equals("")) {
+                String[] lv = line.split("\\s+");
+                try {
+                    heapConfigMap.put(lv[0], lv[2]);
+                } catch (ArrayIndexOutOfBoundsException ex) {
+                    // Ignore mailformed lines
+                }
+            }
+        }
+        return heapConfigMap;
+    }
+
+    // Compare stored values
+    private static void compareValues(Map<String, String> parsedJMapOutput, Map<String, String> parsedVmOutput) {
+        for (String key : expectedJMapValues) {
+            try {
+                String jmapVal = parsedJMapOutput.get(key);
+                if (jmapVal == null) {
+                    throw new RuntimeException("Key '" + key + "' doesn't exists in jmap output");
+                }
+
+                String vmVal = parsedVmOutput.get(key);
+                if (vmVal == null) {
+                    throw new RuntimeException("Key '" + key + "' doesn't exists in vm output");
+                }
+
+                if (new BigDecimal(jmapVal).compareTo(new BigDecimal(vmVal)) != 0) {
+                    throw new RuntimeException(String.format("Key %s doesn't match %s vs %s", key, vmVal, jmapVal));
+                }
+            } catch (NumberFormatException ex) {
+                throw new RuntimeException("Unexpected key '" + key + "' value", ex);
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        System.out.println("Starting JMapHeapConfigTest");
+
+        // Forward vm options to LingeredApp
+        ArrayList<String> cmd = new ArrayList();
+        cmd.addAll(Utils.getVmOptions());
+        cmd.add("-XX:+PrintFlagsFinal");
+
+        TmtoolTestScenario tmt = TmtoolTestScenario.create("jmap", "-heap");
+        int exitcode = tmt.launch(cmd);
+        if (exitcode != 0) {
+            throw new RuntimeException("Test FAILED jmap exits with non zero exit code " + exitcode);
+        }
+
+        Map<String,String> parsedJmapOutput = parseJMapOutput(tmt.getToolOutput());
+        Map<String,String> parsedVMOutput = tmt.parseFlagsFinal();
+
+        compareValues(parsedJmapOutput, parsedVMOutput);
+
+        // If test fails it throws RuntimeException
+        System.out.println("Test PASSED");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,402 @@
+/*
+ * 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.
+ */
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * This is a framework to launch an app that could be synchronized with caller
+ * to make further attach actions reliable across supported platforms
+
+ * Caller example:
+ *   SmartTestApp a = SmartTestApp.startApp(cmd);
+ *     // do something
+ *   a.stopApp();
+ *
+ *   or fine grained control
+ *
+ *   a = new SmartTestApp("MyLock.lck");
+ *   a.createLock();
+ *   a.runApp();
+ *   a.waitAppReady();
+ *     // do something
+ *   a.deleteLock();
+ *   a.waitAppTerminate();
+ *
+ *  Then you can work with app output and process object
+ *
+ *   output = a.getAppOutput();
+ *   process = a.getProcess();
+ *
+ */
+public class LingeredApp {
+
+    private static final long spinDelay = 1000;
+
+    private final String lockFileName;
+    private long lockCreationTime;
+    private Process appProcess;
+    private final ArrayList<String> storedAppOutput;
+
+    /*
+     * Drain child process output, store it into string array
+     */
+    class InputGobbler extends Thread {
+
+        InputStream is;
+        List<String> astr;
+
+        InputGobbler(InputStream is, List<String> astr) {
+            this.is = is;
+            this.astr = astr;
+        }
+
+        public void run() {
+            try {
+                InputStreamReader isr = new InputStreamReader(is);
+                BufferedReader br = new BufferedReader(isr);
+                String line = null;
+                while ((line = br.readLine()) != null) {
+                    astr.add(line);
+                }
+            } catch (IOException ex) {
+                // pass
+            }
+        }
+    }
+
+    /**
+     * Create LingeredApp object on caller side. Lock file have be a valid filename
+     * at writable location
+     *
+     * @param lockFileName - the name of lock file
+     */
+    public LingeredApp(String lockFileName) {
+        this.lockFileName = lockFileName;
+        this.storedAppOutput = new ArrayList();
+    }
+
+    /**
+     *
+     * @return name of lock file
+     */
+    public String getLockFileName() {
+        return this.lockFileName;
+    }
+
+    /**
+     *
+     * @return name of testapp
+     */
+    public String getAppName() {
+        return this.getClass().getName();
+    }
+
+    /**
+     *
+     *  @return pid of java process running testapp
+     */
+    public long getPid() {
+        if (appProcess == null) {
+            throw new RuntimeException("Process is not alive");
+        }
+        return appProcess.getPid();
+    }
+
+    /**
+     *
+     * @return process object
+     */
+    public Process getProcess() {
+        return appProcess;
+    }
+
+    /**
+     *
+     * @return application output as string array. Empty array if application produced no output
+     */
+    List<String> getAppOutput() {
+        if (appProcess.isAlive()) {
+            throw new RuntimeException("Process is still alive. Can't get its output.");
+        }
+        return storedAppOutput;
+    }
+
+    /* Make sure all part of the app use the same method to get dates,
+     as different methods could produce different results
+     */
+    private static long epoch() {
+        return new Date().getTime();
+    }
+
+    private static long lastModified(String fileName) throws IOException {
+        Path path = Paths.get(fileName);
+        BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
+        return attr.lastModifiedTime().toMillis();
+    }
+
+    private static void setLastModified(String fileName, long newTime) throws IOException {
+        Path path = Paths.get(fileName);
+        FileTime fileTime = FileTime.fromMillis(newTime);
+        Files.setLastModifiedTime(path, fileTime);
+    }
+
+    /**
+     * create lock
+     *
+     * @throws IOException
+     */
+    public void createLock() throws IOException {
+        Path path = Paths.get(lockFileName);
+        // Files.deleteIfExists(path);
+        Files.createFile(path);
+        lockCreationTime = lastModified(lockFileName);
+    }
+
+    /**
+     * Delete lock
+     *
+     * @throws IOException
+     */
+    public void deleteLock() throws IOException {
+        try {
+            Path path = Paths.get(lockFileName);
+            Files.delete(path);
+        } catch (NoSuchFileException ex) {
+            // Lock already deleted. Ignore error
+        }
+    }
+
+    public void waitAppTerminate() {
+        while (true) {
+            try {
+                appProcess.waitFor();
+                break;
+            } catch (InterruptedException ex) {
+                // pass
+            }
+        }
+    }
+
+    /**
+     * The app touches the lock file when it's started
+     * wait while it happens. Caller have to delete lock on wait error.
+     *
+     * @param timeout
+     * @throws java.io.IOException
+     */
+    public void waitAppReady(long timeout) throws IOException {
+        long here = epoch();
+        while (true) {
+            long epoch = epoch();
+            if (epoch - here > (timeout * 1000)) {
+                throw new IOException("App waiting timeout");
+            }
+
+            // Live process should touch lock file every second
+            long lm = lastModified(lockFileName);
+            if (lm > lockCreationTime) {
+                break;
+            }
+
+            // Make sure process didn't already exit
+            if (!appProcess.isAlive()) {
+                throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
+            }
+
+            try {
+                Thread.sleep(spinDelay);
+            } catch (InterruptedException ex) {
+                // pass
+            }
+        }
+    }
+
+    /**
+     * Run the app
+     *
+     * @param vmArguments
+     * @throws IOException
+     */
+    public void runApp(List<String> vmArguments)
+            throws IOException {
+
+        // We should always use testjava or throw an exception,
+        // so we can't use JDKToolFinder.getJDKTool("java");
+        // that falls back to compile java on error
+        String jdkPath = System.getProperty("test.jdk");
+        if (jdkPath == null) {
+            // we are not under jtreg, try env
+            Map<String, String> env = System.getenv();
+            jdkPath = env.get("TESTJAVA");
+        }
+
+        if (jdkPath == null) {
+            throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
+        }
+
+        String osname = System.getProperty("os.name");
+        String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
+
+        List<String> cmd = new ArrayList();
+        cmd.add(javapath);
+
+
+        if (vmArguments == null) {
+            // Propagate test.vm.options to LingeredApp, filter out possible empty options
+            String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+            for (String s : testVmOpts) {
+                if (!s.equals("")) {
+                    cmd.add(s);
+                }
+            }
+        }
+        else{
+            // Lets user manage LingerApp options
+            cmd.addAll(vmArguments);
+        }
+
+        // Make sure we set correct classpath to run the app
+        cmd.add("-cp");
+        String classpath = System.getProperty("test.class.path");
+        cmd.add((classpath == null) ? "." : classpath);
+
+        cmd.add(this.getAppName());
+        cmd.add(lockFileName);
+
+        // Reporting
+        StringBuilder cmdLine = new StringBuilder();
+        for (String strCmd : cmd) {
+            cmdLine.append("'").append(strCmd).append("' ");
+        }
+
+        // A bit of verbosity
+        System.out.println("Command line: [" + cmdLine.toString() + "]");
+
+        ProcessBuilder pb = new ProcessBuilder(cmd);
+        // we don't expect any error output but make sure we are not stuck on pipe
+        // pb.redirectErrorStream(false);
+        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+        appProcess = pb.start();
+
+        // Create pipe reader for process, and read stdin and stderr to array of strings
+        InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
+        gb.start();
+    }
+
+    /**
+     *  High level interface for test writers
+     */
+    /**
+     * Factory method that creates SmartAppTest object with ready to use application
+     * lock name is autogenerated, wait timeout is hardcoded
+     * @param cmd - vm options, could be null to auto add testvm.options
+     * @return LingeredApp object
+     * @throws IOException
+     */
+    public static LingeredApp startApp(List<String> cmd) throws IOException {
+        final String lockName = UUID.randomUUID().toString() + ".lck";
+        final int waitTime = 10;
+
+        LingeredApp a = new LingeredApp(lockName);
+        a.createLock();
+        try {
+            a.runApp(cmd);
+            a.waitAppReady(waitTime);
+        } catch (Exception ex) {
+            a.deleteLock();
+            throw ex;
+        }
+
+        return a;
+    }
+
+    public static LingeredApp startApp() throws IOException {
+        return startApp(null);
+    }
+
+    /**
+     * Delete lock file that signal app to terminate, then
+     * waits until app is actually terminated.
+     * @throws IOException
+     */
+    public void stopApp() throws IOException {
+        deleteLock();
+        waitAppTerminate();
+        int exitcode = appProcess.exitValue();
+        if (exitcode != 0) {
+            throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
+        }
+    }
+
+    /**
+     * This part is the application it self
+     */
+    public static void main(String args[]) {
+
+        if (args.length != 1) {
+            System.err.println("Lock file name is not specified");
+            System.exit(7);
+        }
+
+        String theLockFileName = args[0];
+
+        try {
+            Path path = Paths.get(theLockFileName);
+
+            while (Files.exists(path)) {
+                long lm = lastModified(theLockFileName);
+                long now = epoch();
+
+                // A bit of paranoja, don't allow test app to run more than an hour
+                if (now - lm > 3600) {
+                    throw new IOException("Lock is too old. Aborting");
+                }
+
+                // Touch lock to indicate our rediness
+                setLastModified(theLockFileName, now);
+                Thread.sleep(spinDelay);
+            }
+
+        } catch (Exception ex) {
+            System.err.println("LingeredApp ERROR: " + ex);
+            // Leave exit_code = 1 to Java launcher
+            System.exit(3);
+        }
+
+        System.exit(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jmap/heapconfig/LingeredAppTest.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * 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 Unit test for LingeredApp
+ * @compile LingeredAppTest.java
+ * @compile LingeredApp.java
+ * @run main LingeredAppTest
+ */
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class LingeredAppTest {
+
+    public static void main(String[] args) {
+        try {
+            System.out.println("Starting LingeredApp with default parameters");
+
+            ArrayList<String> cmd = new ArrayList();
+
+            // Propagate test.vm.options to LingeredApp, filter out possible empty options
+            String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+            for (String s : testVmOpts) {
+                if (!s.equals("")) {
+                    cmd.add(s);
+                }
+            }
+
+            cmd.add("-XX:+PrintFlagsFinal");
+
+            LingeredApp a = LingeredApp.startApp(cmd);
+            System.out.printf("App pid: %d\n", a.getPid());
+            a.stopApp();
+
+            System.out.println("App output:");
+            int count = 0;
+            for (String line : a.getAppOutput()) {
+                count += 1;
+            }
+            System.out.println("Found " + count + " lines in VM output");
+            System.out.println("Test PASSED");
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            System.out.println("Test ERROR");
+            System.exit(3);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import jdk.testlibrary.JDKToolLauncher;
+import jdk.testlibrary.Utils;
+
+public class TmtoolTestScenario {
+
+    private final ArrayList<String> toolOutput = new ArrayList();
+    private LingeredApp theApp = null;
+    private final String toolName;
+    private final String[] toolArgs;
+
+    /**
+     *  @param toolName - name of tool to test
+     *  @param toolArgs - tool arguments
+     *  @return the object
+     */
+    public static TmtoolTestScenario create(String toolName, String... toolArgs) {
+        return new TmtoolTestScenario(toolName, toolArgs);
+    }
+
+    /**
+     * @return STDOUT of tool
+     */
+    public List<String> getToolOutput() {
+        return toolOutput;
+    }
+
+    /**
+     *
+     * @return STDOUT of test app
+     */
+    public List<String> getAppOutput() {
+        return theApp.getAppOutput();
+    }
+
+    /**
+     * @return Value of the app output with -XX:+PrintFlagsFinal as a map.
+     */
+    public Map<String, String>  parseFlagsFinal() {
+        List<String> astr = theApp.getAppOutput();
+        Map<String, String> vmMap = new HashMap();
+
+        for (String line : astr) {
+            String[] lv = line.trim().split("\\s+");
+            try {
+                vmMap.put(lv[1], lv[3]);
+            } catch (ArrayIndexOutOfBoundsException ex) {
+                // ignore mailformed lines
+            }
+        }
+        return vmMap;
+    }
+
+    /**
+     *
+     * @param vmArgs  - vm and java arguments to launch test app
+     * @return exit code of tool
+     */
+    public int launch(List<String> vmArgs) {
+        System.out.println("Starting LingeredApp");
+        try {
+            try {
+                theApp = LingeredApp.startApp(vmArgs);
+
+                System.out.println("Starting " + toolName + " against " + theApp.getPid());
+                JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName);
+
+                for (String cmd : toolArgs) {
+                    launcher.addToolArg(cmd);
+                }
+                launcher.addToolArg(Long.toString(theApp.getPid()));
+
+                ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+                processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
+                Process toolProcess = processBuilder.start();
+
+                // By default child process output stream redirected to pipe, so we are reading it in foreground.
+                BufferedReader reader = new BufferedReader(new InputStreamReader(toolProcess.getInputStream()));
+
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    toolOutput.add(line.trim());
+                }
+
+                toolProcess.waitFor();
+
+                return toolProcess.exitValue();
+            } finally {
+                theApp.stopApp();
+            }
+        } catch (IOException | InterruptedException ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        }
+    }
+
+    public void launch(String... appArgs) throws IOException {
+        launch(Arrays.asList(appArgs));
+    }
+
+    private TmtoolTestScenario(String toolName, String[] toolArgs) {
+        this.toolName = toolName;
+        this.toolArgs = toolArgs;
+    }
+
+}
--- a/make/Images.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/Images.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -111,14 +111,16 @@
 # Use this file inside the image as target for make rule
 JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX)
 
-$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+    $(call DependOnVariable, JDK_MODULES_LIST)
 	$(ECHO) Creating jdk jimage
 	$(RM) -r $(JDK_IMAGE_DIR) $(JDK_SORTED_MODULES)
 	$(JIMAGE_TOOL) --mods $(JDK_MODULES_LIST) --output $(JDK_IMAGE_DIR) \
 	    $(MODULES_XML) > $(JDK_SORTED_MODULES)
 	$(TOUCH) $@
 
-$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+    $(call DependOnVariable, JRE_MODULES_LIST)
 	$(ECHO) Creating jre jimage
 	$(RM) -r $(JRE_IMAGE_DIR) $(JRE_SORTED_MODULES)
 	$(JIMAGE_TOOL) --mods $(JRE_MODULES_LIST) --output $(JRE_IMAGE_DIR) \
@@ -131,7 +133,8 @@
 
 COMPACT_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec
 
-$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+    $(call DependOnVariable, JRE_COMPACT1_MODULES_LIST)
 	$(ECHO) Creating jre compact1 jimage
 	$(RM) -r $(JRE_COMPACT1_IMAGE_DIR) $(JRE_COMPACT1_SORTED_MODULES)
 	$(JIMAGE_TOOL) \
@@ -140,7 +143,8 @@
 	    $(MODULES_XML) > $(JRE_COMPACT1_SORTED_MODULES)
 	$(TOUCH) $@
 
-$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+    $(call DependOnVariable, JRE_COMPACT2_MODULES_LIST)
 	$(ECHO) Creating jre compact2 jimage
 	$(RM) -r $(JRE_COMPACT2_IMAGE_DIR) $(JRE_COMPACT2_SORTED_MODULES)
 	$(JIMAGE_TOOL) \
@@ -149,7 +153,8 @@
 	    $(MODULES_XML) > $(JRE_COMPACT2_SORTED_MODULES)
 	$(TOUCH) $@
 
-$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+    $(call DependOnVariable, JRE_COMPACT3_MODULES_LIST)
 	$(ECHO) Creating jre compact3 jimage
 	$(RM) -r $(JRE_COMPACT3_IMAGE_DIR) $(JRE_COMPACT3_SORTED_MODULES)
 	$(JIMAGE_TOOL) \
@@ -368,45 +373,59 @@
 
 # Common way to emit a line into the release or info file
 define info-file-item # name value
-	$(PRINTF) '%s="%s"\n' $1 $2 >> $@
+  $(PRINTF) '%s="%s"\n' $1 $2 >> $@
 endef
 
 # Param 1 - The file containing the MODULES list
 define create-info-file
-	$(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(call info-file-item, "JAVA_VERSION", "$(JDK_VERSION)")
-	$(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)")
-	$(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)")
-	$(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)")
-	$(if $(JDK_ARCH_ABI_PROP_NAME), \
-	  $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
-	$(call info-file-item, "SOURCE", "$(ALL_SOURCE_TIPS)")
-	$(call info-file-item, "MODULES", "`$(CAT) $1`")
+  $(call info-file-item, "JAVA_VERSION", "$(JDK_VERSION)")
+  $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)")
+  $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)")
+  $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)")
+  $(if $(JDK_ARCH_ABI_PROP_NAME), \
+    $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
+  $(call info-file-item, "SOURCE", "$(ALL_SOURCE_TIPS)")
+  $(call info-file-item, "MODULES", "`$(CAT) $1`")
 endef
 
+# Param 1 - The file containing the MODULES list
+define prepare-info-file
+  $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
+  $(MKDIR) -p $(@D)
+  $(RM) $@
+endef
+
+define info-file
+  $(call prepare-info-file, $1)
+  $(call create-info-file, $1)
+endef
+
+# Create a variable dependency file common for all release info files. The
+# sorted module list will only change if the image is regenerated, which will
+# trigger a rebuild of these files anyway.
+INFO_FILE_VARDEPS := $(call DependOnVariable, create-info-file)
+
 ALL_SOURCE_TIPS = $(shell \
     if [ -f $(SUPPORT_OUTPUTDIR)/source_tips ] ; then \
       $(CAT) $(SUPPORT_OUTPUTDIR)/source_tips ; \
     fi)
 
-$(JRE_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call create-info-file, $(JRE_SORTED_MODULES))
+$(JRE_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+	$(call info-file, $(JRE_SORTED_MODULES))
 
-$(JDK_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call create-info-file, $(JDK_SORTED_MODULES))
+$(JDK_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+	$(call info-file, $(JDK_SORTED_MODULES))
 
-$(JRE_COMPACT1_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call create-info-file, $(JRE_COMPACT1_SORTED_MODULES))
+$(JRE_COMPACT1_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+	$(call info-file, $(JRE_COMPACT1_SORTED_MODULES))
 	$(call info-file-item, "JAVA_PROFILE", "compact1")
 
-$(JRE_COMPACT2_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call create-info-file, $(JRE_COMPACT2_SORTED_MODULES))
+$(JRE_COMPACT2_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+	$(call info-file, $(JRE_COMPACT2_SORTED_MODULES))
 	$(call info-file-item, "JAVA_PROFILE", "compact2")
 
-$(JRE_COMPACT3_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call create-info-file, $(JRE_COMPACT3_SORTED_MODULES))
+$(JRE_COMPACT3_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+	$(call info-file, $(JRE_COMPACT3_SORTED_MODULES))
 	$(call info-file-item, "JAVA_PROFILE", "compact3")
 
 JRE_TARGETS += $(JRE_INFO_FILE)
--- a/make/Main.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/Main.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -402,6 +402,8 @@
 
   verify-modules: exploded-image
 
+  test-make: clean-test-make
+
 endif
 
 ################################################################################
@@ -446,7 +448,7 @@
 # alias for ease of use.
 jdk: exploded-image
 
-images: test-image jimages demos samples zip-security
+images: test-image jimages demos samples zip-security verify-modules
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
   images: mac-bundles
@@ -477,7 +479,7 @@
 # file.
 
 CLEAN_DIRS += hotspot jdk bootcycle-build test buildtools support \
-    images make-support
+    images make-support test-make
 CLEAN_DIR_TARGETS := $(addprefix clean-, $(CLEAN_DIRS))
 CLEAN_PHASES := gensrc java native include
 CLEAN_PHASE_TARGETS := $(addprefix clean-, $(CLEAN_PHASES))
--- a/make/ZipSource.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/ZipSource.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -71,7 +71,7 @@
         $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjli/java_md*)))
 
 # This dir needs to exist before macro is evaluated to avoid warning from find.
-$(eval $(call MakeDir, $(SUPPORT_OUTPUTDIR)/src))
+$(call MakeDir, $(SUPPORT_OUTPUTDIR)/src)
 $(eval $(call SetupZipArchive,BUILD_SRC_ZIP, \
     SRC := $(SRC_ZIP_SRCS) $(SUPPORT_OUTPUTDIR)/src, \
     INCLUDES := $(SRC_ZIP_INCLUDES) launcher, \
--- a/make/common/IdlCompilation.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/common/IdlCompilation.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -99,7 +99,7 @@
   $(if $(16),$(error Internal makefile error: Too many arguments to SetupIdlCompilation, please update IdlCompilation.gmk))
 
   # Find all existing java files and existing class files.
-  $$(eval $$(call MakeDir,$$($1_BIN)))
+  $$(call MakeDir,$$($1_BIN))
   $1_SRCS := $$(shell find $$($1_SRC) -name "*.idl")
   $1_BINS := $$(shell find $$($1_BIN) -name "*.java")
   # Prepend the source/bin path to the filter expressions.
--- a/make/common/JavaCompilation.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/common/JavaCompilation.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -126,17 +126,20 @@
   $1_FIND_PATTERNS:=$(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
   # On windows, a lot of includes/excludes risk making the command line too long, so
   # writing the grep patterns to files.
+  # Grep returns 1 if nothing is matched. Do not fail the build for this.
   ifneq (,$$($1_INCLUDES))
     $1_GREP_INCLUDE_PATTERNS:=$$(call EscapeDollar, \
         $$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
     # If there are a lot of include patterns, output to file to shorten command lines
     ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
-      $1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
+      $1_GREP_INCLUDES:=| ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
+          || test "$$$$?" = "1" )
     else
       $1_GREP_INCLUDE_OUTPUT:=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include $$(NEWLINE) \
           $$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS,\n, \
           >> $$($1_BIN)/_the.$$($1_JARNAME)_include)
-      $1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
+      $1_GREP_INCLUDES:=| ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
+          || test "$$$$?" = "1" )
     endif
   endif
   ifneq (,$$($1_EXCLUDES)$$($1_EXCLUDE_FILES))
@@ -145,12 +148,14 @@
         $$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
     # If there are a lot of include patterns, output to file to shorten command lines
     ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
-      $1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
+      $1_GREP_EXCLUDES:=| ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
+          || test "$$$$?" = "1" )
     else
       $1_GREP_EXCLUDE_OUTPUT=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude $$(NEWLINE) \
           $$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS,\n, \
           >> $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
-      $1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
+      $1_GREP_EXCLUDES:=| ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
+          || test "$$$$?" = "1" )
     endif
   endif
 
@@ -222,9 +227,11 @@
       $$($1_CAPTURE_EXTRA_FILES)
 
   # The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
+  # Find returns non zero if the META-INF dir does not exist, ignore this.
   ifeq (,$$($1_SKIP_METAINF))
     $1_CAPTURE_METAINF =$$(foreach src,$$($1_SRCS), \
-        ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+        ( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
+            | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
         $$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
   endif
   # The capture deletes macro finds all deleted files and concatenates them. The resulting file
@@ -248,9 +255,11 @@
             >> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
       $$($1_CAPTURE_EXTRA_FILES)
 
+  # Find returns non zero if the META-INF dir does not exist, ignore this.
   ifeq (,$$($1_SKIP_METAINF))
     $1_SCAPTURE_METAINF=$$(foreach src,$$($1_SRCS), \
-        ( $(FIND) $$(src)/META-INF -type f 2> /dev/null | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+        ( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
+            | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
         $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
   endif
   $1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
@@ -270,19 +279,37 @@
     $1_JAR_UPDATE_OPTIONS := uf
   endif
 
+  # Include all variables of significance in the vardeps file
+  $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) $(RELEASE) $(COMPANY_NAME) \
+      $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR)
+  $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
+
   # Here is the rule that creates/updates the jar file.
-  $$($1_JAR) : $$($1_DEPS)
+  $$($1_JAR) : $$($1_DEPS) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
 	$(MKDIR) -p $$($1_BIN)
 	$$($1_GREP_INCLUDE_OUTPUT)
 	$$($1_GREP_EXCLUDE_OUTPUT)
-	$$(if $$($1_MANIFEST), \
-	  $(SED) -e "s#@@RELEASE@@#$(RELEASE)#" \
-	      -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $$($1_MANIFEST) > $$($1_MANIFEST_FILE) \
+        # If the vardeps file is part of the newer prereq list, it means that
+        # either the jar file does not exist, or we need to recreate it from
+        # from scratch anyway since a simple update will not catch all the 
+        # potential changes.
+	$$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
+	  $$(if $$($1_MANIFEST), \
+	    $(SED) -e "s#@@RELEASE@@#$(RELEASE)#" \
+	        -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
+	  , \
+	    $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+	  $$(if $$($1_JARMAIN), \
+	    $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+	  $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+	    $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+	  $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
+	  $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+	  $$($1_SCAPTURE_CONTENTS) \
+	  $$($1_SCAPTURE_METAINF) \
+	  $$($1_SUPDATE_CONTENTS) \
+	  $$($1_JARINDEX) && true \
 	, \
-	  $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE))
-	$$(if $$($1_JARMAIN),$(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE))
-	$$(if $$($1_EXTRA_MANIFEST_ATTR),$(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE))
-	$$(if $$(wildcard $$@), \
 	  $(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
 	  $$($1_CAPTURE_CONTENTS) \
 	  $$($1_CAPTURE_METAINF) \
@@ -294,12 +321,6 @@
 	    $(ZIP) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
 	  fi $$(NEWLINE) \
 	  $$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
-	  $$($1_JARINDEX) && true \
-	, \
-	  $(ECHO) Creating $$($1_NAME) && $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
-	  $$($1_SCAPTURE_CONTENTS) \
-	  $$($1_SCAPTURE_METAINF) \
-	  $$($1_SUPDATE_CONTENTS) \
 	  $$($1_JARINDEX) && true )
 
   # Add jar to target list
@@ -431,7 +452,7 @@
   $1_SRC:=$$(call ADD_SRCS,$$($1_SRC))
   # Make sure the dirs exist.
   $$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupJavaCompilation $1 contains missing directory $$d)))
-  $$(eval $$(call MakeDir,$$($1_BIN)))
+  $$(call MakeDir,$$($1_BIN))
   # Add all source roots to the find cache since we are likely going to run find
   # on these more than once. The cache will only be updated if necessary.
   $$(eval $$(call FillCacheFind,$$($1_SRC)))
@@ -475,23 +496,23 @@
     $1_ALL_COPIES += $$(filter $$(addprefix %,$$($1_COPY)),$$($1_ALL_SRCS))
     # Copy these explicitly
     $1_ALL_COPIES += $$($1_COPY_FILES)
-    # Copy must also respect filters.
-    ifneq (,$$($1_INCLUDES))
-      $1_ALL_COPIES := $$(filter $$($1_SRC_INCLUDES),$$($1_ALL_COPIES))
-    endif
-    ifneq (,$$($1_EXCLUDES))
-      $1_ALL_COPIES := $$(filter-out $$($1_SRC_EXCLUDES),$$($1_ALL_COPIES))
-    endif
-    ifneq (,$$($1_EXCLUDE_FILES))
-      $1_ALL_COPIES := $$(filter-out $$($1_EXCLUDE_FILES_PATTERN),$$($1_ALL_COPIES))
-    endif
+  endif
+  # Copy must also respect filters.
+  ifneq (,$$($1_INCLUDES))
+    $1_ALL_COPIES := $$(filter $$($1_SRC_INCLUDES),$$($1_ALL_COPIES))
+  endif
+  ifneq (,$$($1_EXCLUDES))
+    $1_ALL_COPIES := $$(filter-out $$($1_SRC_EXCLUDES),$$($1_ALL_COPIES))
   endif
-    ifneq (,$$($1_ALL_COPIES))
-      # Yep, there are files to be copied!
-      $1_ALL_COPY_TARGETS:=
-          $$(foreach i,$$($1_ALL_COPIES),$$(eval $$(call add_file_to_copy,$1,$$i)))
-      # Now we can depend on $$($1_ALL_COPY_TARGETS) to copy all files!
-    endif
+  ifneq (,$$($1_EXCLUDE_FILES))
+    $1_ALL_COPIES := $$(filter-out $$($1_EXCLUDE_FILES_PATTERN),$$($1_ALL_COPIES))
+  endif
+  ifneq (,$$($1_ALL_COPIES))
+    # Yep, there are files to be copied!
+    $1_ALL_COPY_TARGETS:=
+        $$(foreach i,$$($1_ALL_COPIES),$$(eval $$(call add_file_to_copy,$1,$$i)))
+    # Now we can depend on $$($1_ALL_COPY_TARGETS) to copy all files!
+  endif
 
   # Find all property files to be copied and cleaned from source to bin.
   ifneq (,$$($1_CLEAN)$$($1_CLEAN_FILES))
@@ -535,9 +556,14 @@
     $1_SJAVAC:=$$(subst com.sun.tools.javac.Main,com.sun.tools.sjavac.Main,$$($1_JAVAC))
 
     # Set the $1_REMOTE to spawn a background javac server.
-    $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
+    $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst \
+        $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
 
-    $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS)
+    $1_VARDEPS := $$($1_JVM) $$($1_SJAVAC) $$($1_SJAVAC_ARGS) $$($1_FLAGS) \
+        $$($1_HEADERS_ARG) $$($1_BIN)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
+
+    $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
 	$(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE))
         # As a workaround for sjavac not tracking api changed from the classpath, force full
         # recompile if an external dependency, which is something other than a source
@@ -592,8 +618,11 @@
       $1_HEADER_TARGETS := $$($1_HEADERS)/_the.$1_headers
     endif
 
+    $1_VARDEPS := $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) $$($1_BIN) $$($1_HEADERS_ARG)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
+
     # When not using sjavac, pass along all sources to javac using an @file.
-    $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS)
+    $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
 	$(MKDIR) -p $$(@D)
 	$(RM) $$($1_BIN)/_the.$1_batch $$($1_BIN)/_the.$1_batch.tmp
 	$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
@@ -659,4 +688,5 @@
   $(if $(findstring yes, $(ENABLE_SJAVAC)), $(strip $2)/_the.$(strip $1)_pubapi, \
       $(strip $2)/_the.$(strip $1)_batch)
 endef
-endif
+
+endif # _JAVA_COMPILATION_GMK
--- a/make/common/MakeBase.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/common/MakeBase.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -349,7 +349,7 @@
     # (and causing a crash on Cygwin).
     # Default shell seems to always be /bin/sh. Must override with bash to get this to work on Solaris.
     # Only use time if it's GNU time which supports format and output file.
-    WRAPPER_SHELL:=$$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(BASH)
+    WRAPPER_SHELL:=$$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(SHELL)
     SHELL=$$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL)
   endif
   # Never remove warning messages; this is just for completeness
@@ -392,11 +392,9 @@
 endef
 
 # Make directory without forking mkdir if not needed
-define MakeDir
-  ifneq ($$(wildcard $1 $2 $3 $4 $5 $6 $7 $8 $9),$$(strip $1 $2 $3 $4 $5 $6 $7 $8 $9))
-    $$(shell $(MKDIR) -p $1 $2 $3 $4 $5 $6 $7 $8 $9)
-  endif
-endef
+MakeDir = \
+    $(strip $(if $(subst $(wildcard $1 $2 $3 $4 $5 $6 $7 $8 $9),,$(strip $1 $2 $3 $4 $5 $6 $7 $8 $9)),\
+      $(shell $(MKDIR) -p $1 $2 $3 $4 $5 $6 $7 $8 $9)))
 
 ifeq ($(OPENJDK_TARGET_OS),solaris)
   # On Solaris, if the target is a symlink and exists, cp won't overwrite.
@@ -446,6 +444,11 @@
 # Filter out duplicate sub strings while preserving order. Keeps the first occurance.
 uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
 
+# String equals
+equals = \
+    $(and $(findstring $(strip $1),$(strip $2)),\
+        $(findstring $(strip $2),$(strip $1)))
+
 ifneq ($(DISABLE_CACHE_FIND), true)
   ################################################################################
   # In Cygwin, finds are very costly, both because of expensive forks and because
@@ -543,6 +546,80 @@
 endef
 
 ################################################################################
+# ShellQuote
+#
+# Quotes a string with single quotes and replaces single quotes with '\'' so 
+# that the contents survives being given to the shell.
+
+ShellQuote = \
+    $(SQUOTE)$(subst $(SQUOTE),$(SQUOTE)\$(SQUOTE)$(SQUOTE),$(strip $1))$(SQUOTE)
+
+################################################################################
+# Write to and read from file
+
+# Param 1 - File to read
+ReadFile = \
+    $(shell $(CAT) $1)
+
+# Param 1 - Text to write
+# Param 2 - File to write to
+# Use printf to get consistent behavior on all platforms.
+WriteFile = \
+    $(shell $(PRINTF) "%s" $(call ShellQuote, $1) > $2)
+
+################################################################################
+# DependOnVariable
+#
+# This macro takes a variable name and puts the value in a file only if the 
+# value has changed since last. The name of the file is returned. This can be 
+# used to create rule dependencies on make variable values. The following
+# example would get rebuilt if the value of SOME_VAR was changed:
+#
+# path/to/some-file: $(call DependOnVariable, SOME_VAR)
+#         echo $(SOME_VAR) > $@
+#
+# Note that leading and trailing white space in the value is ignored.
+#
+
+# Defines the sub directory structure to store variable value file in
+DependOnVariableDirName = \
+    $(strip $(subst $(SRC_ROOT)/,,\
+        $(if $(filter /%, $(firstword $(MAKEFILE_LIST))), \
+          $(firstword $(MAKEFILE_LIST)), \
+          $(CURDIR)/$(firstword $(MAKEFILE_LIST)))))
+
+# Defines the name of the file to store variable value in. Generates a name
+# unless parameter 2 is given.
+# Param 1 - Name of variable
+# Param 2 - (optional) name of file to store value in
+DependOnVariableFileName = \
+    $(strip $(if $(strip $2), $2, \
+      $(MAKESUPPORT_OUTPUTDIR)/vardeps/$(DependOnVariableDirName)/$(strip $1).vardeps))
+
+# Does the actual work with parameters stripped.
+# If the file exists AND the contents is the same as the variable, do nothing
+# else print a new file.
+# Always returns the name of the file where the value was printed.
+# Param 1 - Name of variable
+# Param 2 - (optional) name of file to store value in
+DependOnVariableHelper = \
+    $(strip $(if $(and $(wildcard $(call DependOnVariableFileName, $1, $2)),\
+        $(call equals, $(strip $($1)), \
+            $(call ReadFile, $(call DependOnVariableFileName, $1, $2)))),,\
+      $(call MakeDir, $(dir $(call DependOnVariableFileName, $1, $2))) \
+      $(if $(findstring $(LOG_LEVEL), trace), \
+          $(info Variable $1: >$(strip $($1))<) \
+          $(info File: >$(call ReadFile, $(call DependOnVariableFileName, $1, $2))<)) \
+      $(call WriteFile, $($1), $(call DependOnVariableFileName, $1, $2))) \
+    $(call DependOnVariableFileName, $1, $2))
+
+# Main macro
+# Param 1 - Name of variable
+# Param 2 - (optional) name of file to store value in
+DependOnVariable = \
+    $(call DependOnVariableHelper,$(strip $1),$(strip $2))
+
+################################################################################
 
 # Hook to include the corresponding custom file, if present.
 $(eval $(call IncludeCustomExtension, , common/MakeBase.gmk))
--- a/make/common/NativeCompilation.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/common/NativeCompilation.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -114,7 +114,7 @@
       endif
     endif
 
-    $$($1_$2_OBJ) : $2 | $$($1_BUILD_INFO)
+    $$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) | $$($1_BUILD_INFO)
 	$(ECHO) $(LOG_INFO) "Compiling $$(notdir $2) (for $$(notdir $$($1_TARGET)))"
         ifneq ($(TOOLCHAIN_TYPE), microsoft)
           # The Solaris studio compiler doesn't output the full path to the object file in the
@@ -133,7 +133,8 @@
 	  ($$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \
 	      $(CC_OUT_OPTION)$$($1_$2_OBJ) $2 ; echo $$$$? > $$($1_$2_DEP).exitvalue) \
 	      | $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \
-	      -e "^$(notdir $2)$$$$" ; exit `cat $$($1_$2_DEP).exitvalue`
+	      -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \
+	      exit `cat $$($1_$2_DEP).exitvalue`
 	  $(RM) $$($1_$2_DEP).exitvalue
 	  ($(ECHO) $$@: \\ \
 	  && $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) > $$($1_$2_DEP)
@@ -306,7 +307,7 @@
   endif
 
   # Make sure the dirs exist.
-  $$(eval $$(call MakeDir,$$($1_OBJECT_DIR) $$($1_OUTPUT_DIR)))
+  $$(call MakeDir,$$($1_OBJECT_DIR) $$($1_OUTPUT_DIR))
   $$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d)))
 
   # Find all files in the source trees. Sort to remove duplicates.
@@ -426,15 +427,16 @@
 
   $1_BUILD_INFO := $$($1_OBJECT_DIR)/_build-info.marker
 
-  # Setup rule for printing progress info when compiling source files.
-  # This is a rough heuristic and may not always print accurate information.
-  $$($1_BUILD_INFO): $$($1_SRCS)
-        ifeq ($$(wildcard $$($1_TARGET)),)
-	  $(ECHO) 'Creating $$($1_BASENAME) from $$(words $$?) file(s)'
-        else
-	  $(ECHO) 'Updating $$($1_BASENAME) from $$(words $$?) file(s)'
-        endif
-	$(TOUCH) $$@
+  # Track variable changes for all variables that affect the compilation command
+  # lines for all object files in this setup. This includes at least all the 
+  # variables used in the call to add_native_source below.
+  $1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $(SYSROOT_CFLAGS) \
+      $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) \
+      $$($1_CC) $$($1_CXX) $$($1_OBJC) $$($1_ASFLAGS) \
+      $$(foreach s, $$($1_SRCS), \
+          $$($1_$$(notdir $$s)_CFLAGS) $$($1_$$(notdir $$s)_CXXFLAGS))
+  $1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \
+      $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps)
 
   # Now call add_native_source for each source file we are going to compile.
   $$(foreach p,$$($1_SRCS), \
@@ -444,13 +446,28 @@
           $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $(SYSROOT_CFLAGS), \
           $$($1_CXX),$$($1_OBJC),$$($1_ASFLAGS))))
 
+  # Setup rule for printing progress info when compiling source files.
+  # This is a rough heuristic and may not always print accurate information.
+  $$($1_BUILD_INFO): $$($1_SRCS) $$($1_COMPILE_VARDEPS_FILE)
+        ifeq ($$(wildcard $$($1_TARGET)),)
+	  $(ECHO) 'Creating $$($1_BASENAME) from $$(words $$(filter-out %.vardeps, $$?)) file(s)'
+        else
+	  $(ECHO) 'Updating $$($1_BASENAME) from $$(words $$(filter-out %.vardeps, $$?)) file(s)'
+        endif
+	$(TOUCH) $$@
+
   # On windows we need to create a resource file
   ifeq ($(OPENJDK_TARGET_OS), windows)
     ifneq (,$$($1_VERSIONINFO_RESOURCE))
       $1_RES:=$$($1_OBJECT_DIR)/$$($1_BASENAME).res
       $1_RES_DEP:=$$($1_RES).d
       -include $$($1_RES_DEP)
-      $$($1_RES): $$($1_VERSIONINFO_RESOURCE)
+
+      $1_RES_VARDEPS := $(RC) $$($1_RC_FLAGS)
+      $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \
+          $$($1_RES).vardeps)
+
+      $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
 		$(ECHO) $(LOG_INFO) "Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET)))"
 		$(RC) $$($1_RC_FLAGS) $(CC_OUT_OPTION)$$@ $$($1_VERSIONINFO_RESOURCE)
                 # Windows RC compiler does not support -showIncludes, so we mis-use CL for this.
@@ -462,7 +479,9 @@
     ifneq (,$$($1_MANIFEST))
       $1_GEN_MANIFEST:=$$($1_OBJECT_DIR)/$$($1_PROGRAM).manifest
       IMVERSIONVALUE:=$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VERSION).$(COOKED_BUILD_NUMBER)
-      $$($1_GEN_MANIFEST): $$($1_MANIFEST)
+      $1_MANIFEST_VARDEPS_FILE := $$(call DependOnVariable, IMVERSIONVALUE, \
+          $$($1_GEN_MANIFEST).vardeps)
+      $$($1_GEN_MANIFEST): $$($1_MANIFEST) $$($1_MANIFEST_VARDEPS_FILE)
 		$(SED) 's%IMVERSION%$$(IMVERSIONVALUE)%g;s%PROGRAM%$$($1_PROGRAM)%g' $$< > $$@
     endif
   endif
@@ -575,8 +594,13 @@
 
     $1_EXTRA_LDFLAGS_SUFFIX += $(GLOBAL_LDFLAGS_SUFFIX)
 
+    $1_VARDEPS := $$($1_LD) $(SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
+        $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+        $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
     $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \
-        $$($1_DEBUGINFO_EXTRA_DEPS)
+        $$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE)
 		$(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)"
 		$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $(SYSROOT_LDFLAGS) \
 		    $(LD_OUT_OPTION)$$@ \
@@ -592,8 +616,12 @@
   endif
 
   ifneq (,$$($1_STATIC_LIBRARY))
+    $1_VARDEPS := $(AR) $$($1_ARFLAGS) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+        $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
     # Generating a static library, ie object file archive.
-    $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES)
+    $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
 	$(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)"
 	$(AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
 	    $$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
@@ -603,8 +631,13 @@
     # A executable binary has been specified, setup the target for it.
     $1_EXTRA_LDFLAGS_SUFFIX += $(GLOBAL_LDFLAGS_SUFFIX)
 
+    $1_VARDEPS := $$($1_LDEXE) $(SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
+        $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+        $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
     $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_GEN_MANIFEST) \
-        $$($1_DEBUGINFO_EXTRA_DEPS)
+        $$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE)
 		$(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)"
 		$$($1_LDEXE) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $(SYSROOT_LDFLAGS) \
 		    $(EXE_OUT_OPTION)$$($1_TARGET) \
--- a/make/common/TextFileProcessing.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/make/common/TextFileProcessing.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -34,7 +34,7 @@
 # param 3 = the target base directory
 # param 4 = the target file name (possibly with a partial path)
 define SetupSingleTextFileForProcessing
-  $(strip $3)/$(strip $4): $2
+  $(strip $3)/$(strip $4): $2 $$($1_VARDEPS_FILE)
 	$(ECHO) $(LOG_INFO) "Processing $(strip $4)"
 	$(MKDIR) -p '$$(@D)'
 	$(RM) '$$@' '$$@.includes.tmp' '$$@.replacements.tmp'
@@ -193,6 +193,9 @@
     $1_INCLUDES_COMMAND_LINE := $(CAT)
   endif
 
+  $1_VARDEPS := $$($1_INCLUDES_COMMAND_LINE) $$($1_REPLACEMENTS_COMMAND_LINE)
+  $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS)
+
   # Reset target list before populating it
   $1 :=
 
--- a/nashorn/.hgtags	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/.hgtags	Wed Jul 05 20:17:15 2017 +0200
@@ -281,3 +281,4 @@
 3c2bbeda038aef7061455fec604db7d8a342fac5 jdk9-b45
 2ecf0a617f0f9af1ffd278a0c70e76f1946ce773 jdk9-b46
 29046d42a95e5b9f105ab086a628bbd7f81c915d jdk9-b47
+f08660f30051ba0b38ad00e692979b37d107c9c4 jdk9-b48
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Wed Jul 05 20:17:15 2017 +0200
@@ -926,9 +926,7 @@
     @Override
     public Node leaveTryNode(final TryNode tryNode) {
         tryNode.setException(exceptionSymbol());
-        if (tryNode.getFinallyBody() != null) {
-            tryNode.setFinallyCatchAll(exceptionSymbol());
-        }
+        assert tryNode.getFinallyBody() == null;
 
         end(tryNode);
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 20:17:15 2017 +0200
@@ -85,7 +85,6 @@
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
-import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
@@ -102,6 +101,7 @@
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
@@ -1110,7 +1110,14 @@
 
     @Override
     public boolean enterBlock(final Block block) {
-        method.label(block.getEntryLabel());
+        final Label entryLabel = block.getEntryLabel();
+        if (entryLabel.isBreakTarget()) {
+            // Entry label is a break target only for an inlined finally block.
+            assert !method.isReachable();
+            method.breakLabel(entryLabel, lc.getUsedSlotCount());
+        } else {
+            method.label(entryLabel);
+        }
         if(!method.isReachable()) {
             return false;
         }
@@ -1240,6 +1247,11 @@
         return enterJumpStatement(breakNode);
     }
 
+    @Override
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return enterJumpStatement(jumpToInlinedFinally);
+    }
+
     private boolean enterJumpStatement(final JumpStatement jump) {
         if(!method.isReachable()) {
             return false;
@@ -1247,9 +1259,8 @@
         enterStatement(jump);
 
         method.beforeJoinPoint(jump);
-        final BreakableNode target = jump.getTarget(lc);
-        popScopesUntil(target);
-        final Label targetLabel = jump.getTargetLabel(target);
+        popScopesUntil(jump.getPopScopeLimit(lc));
+        final Label targetLabel = jump.getTargetLabel(lc);
         targetLabel.markAsBreakTarget();
         method._goto(targetLabel);
 
@@ -3053,6 +3064,14 @@
         if (method.isReachable()) {
             method._goto(skip);
         }
+
+        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+            TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
+            // All inlined finallies end with a jump or a return
+            assert !method.isReachable();
+        }
+
+
         method._catch(recovery);
         method.store(vmException, EXCEPTION_TYPE);
 
@@ -3112,15 +3131,14 @@
             catchBody.accept(this);
             leaveBlock(catchBlock);
             lc.pop(catchBlock);
-            if(method.isReachable()) {
-                method._goto(afterCatch);
-            }
             if(nextCatch != null) {
+                if(method.isReachable()) {
+                    method._goto(afterCatch);
+                }
                 method.breakLabel(nextCatch, lc.getUsedSlotCount());
             }
         }
 
-        assert !method.isReachable();
         // afterCatch could be the same as skip, except that we need to establish that the vmException is dead.
         method.label(afterCatch);
         if(method.isReachable()) {
@@ -3129,6 +3147,8 @@
         method.label(skip);
 
         // Finally body is always inlined elsewhere so it doesn't need to be emitted
+        assert tryNode.getFinallyBody() == null;
+
         return false;
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java	Wed Jul 05 20:17:15 2017 +0200
@@ -74,7 +74,7 @@
     /** size of next free slot vector */
     private int nextFreeSlotsSize;
 
-    private boolean isWithBoundary(final LexicalContextNode node) {
+    private boolean isWithBoundary(final Object node) {
         return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
     }
 
@@ -102,7 +102,7 @@
     }
 
     @Override
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         final T popped = super.pop(node);
         if (isWithBoundary(node)) {
             dynamicScopeCount--;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Wed Jul 05 20:17:15 2017 +0200
@@ -62,6 +62,7 @@
 import jdk.nashorn.internal.ir.JoinPredecessor;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
@@ -529,8 +530,7 @@
             return false;
         }
         assertTypeStackIsEmpty();
-        final BreakableNode target = jump.getTarget(lc);
-        jumpToLabel(jump, jump.getTargetLabel(target), getBreakTargetTypes(target));
+        jumpToLabel(jump, jump.getTargetLabel(lc), getBreakTargetTypes(jump.getPopScopeLimit(lc)));
         doesNotContinueSequentially();
         return false;
     }
@@ -784,6 +784,11 @@
     }
 
     @Override
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return enterJumpStatement(jumpToInlinedFinally);
+    }
+
+    @Override
     public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
         if (literalNode instanceof ArrayLiteralNode) {
             final List<Expression> expressions = ((ArrayLiteralNode)literalNode).getElementExpressions();
@@ -1042,6 +1047,17 @@
         }
         doesNotContinueSequentially();
 
+        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+            final Block finallyBody = TryNode.getLabelledInlinedFinallyBlock(inlinedFinally);
+            joinOnLabel(finallyBody.getEntryLabel());
+            // NOTE: the jump to inlined finally can end up in dead code, so it is not necessarily reachable.
+            if (reachable) {
+                finallyBody.accept(this);
+                // All inlined finallies end with a jump or a return
+                assert !reachable;
+            }
+        }
+
         joinOnLabel(catchLabel);
         for(final CatchNode catchNode: tryNode.getCatches()) {
             final IdentNode exception = catchNode.getException();
@@ -1125,7 +1141,7 @@
         return false;
     };
 
-    private Map<Symbol, LvarType> getBreakTargetTypes(final BreakableNode target) {
+    private Map<Symbol, LvarType> getBreakTargetTypes(final LexicalContextNode target) {
         // Remove symbols defined in the the blocks that are being broken out of.
         Map<Symbol, LvarType> types = localVariableTypes;
         for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
@@ -1380,7 +1396,11 @@
                 if(node instanceof JoinPredecessor) {
                     final JoinPredecessor original = joinPredecessors.pop();
                     assert original.getClass() == node.getClass() : original.getClass().getName() + "!=" + node.getClass().getName();
-                    return (Node)setLocalVariableConversion(original, (JoinPredecessor)node);
+                    final JoinPredecessor newNode = setLocalVariableConversion(original, (JoinPredecessor)node);
+                    if (newNode instanceof LexicalContextNode) {
+                        lc.replace((LexicalContextNode)node, (LexicalContextNode)newNode);
+                    }
+                    return (Node)newNode;
                 }
                 return node;
             }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Wed Jul 05 20:17:15 2017 +0200
@@ -56,9 +56,11 @@
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ReturnNode;
@@ -115,7 +117,7 @@
                 for (final Statement statement : statements) {
                     if (!terminated) {
                         newStatements.add(statement);
-                        if (statement.isTerminal() || statement instanceof BreakNode || statement instanceof ContinueNode) { //TODO hasGoto? But some Loops are hasGoto too - why?
+                        if (statement.isTerminal() || statement instanceof JumpStatement) { //TODO hasGoto? But some Loops are hasGoto too - why?
                             terminated = true;
                         }
                     } else {
@@ -183,6 +185,12 @@
     }
 
     @Override
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        addStatement(jumpToInlinedFinally);
+        return false;
+    }
+
+    @Override
     public boolean enterEmptyNode(final EmptyNode emptyNode) {
         return false;
     }
@@ -318,8 +326,8 @@
         return addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
     }
 
-    private static Node ensureUniqueNamesIn(final Node node) {
-        return node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+    private static <T extends Node> T ensureUniqueNamesIn(final T node) {
+        return (T)node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public Node leaveFunctionNode(final FunctionNode functionNode) {
                 final String name = functionNode.getName();
@@ -333,15 +341,15 @@
         });
     }
 
-    private static List<Statement> copyFinally(final Block finallyBody) {
+    private static Block createFinallyBlock(final Block finallyBody) {
         final List<Statement> newStatements = new ArrayList<>();
         for (final Statement statement : finallyBody.getStatements()) {
-            newStatements.add((Statement)ensureUniqueNamesIn(statement));
+            newStatements.add(statement);
             if (statement.hasTerminalFlags()) {
-                return newStatements;
+                break;
             }
         }
-        return newStatements;
+        return finallyBody.setStatements(null, newStatements);
     }
 
     private Block catchAllBlock(final TryNode tryNode) {
@@ -367,28 +375,24 @@
         return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName());
     }
 
-    private static boolean isTerminal(final List<Statement> statements) {
-        return !statements.isEmpty() && statements.get(statements.size() - 1).hasTerminalFlags();
+    private static boolean isTerminalFinally(final Block finallyBlock) {
+        return finallyBlock.getLastStatement().hasTerminalFlags();
     }
 
     /**
      * Splice finally code into all endpoints of a trynode
      * @param tryNode the try node
-     * @param rethrows list of rethrowing throw nodes from synthetic catch blocks
+     * @param rethrow the rethrowing throw nodes from the synthetic catch block
      * @param finallyBody the code in the original finally block
      * @return new try node after splicing finally code (same if nop)
      */
-    private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
+    private TryNode spliceFinally(final TryNode tryNode, final ThrowNode rethrow, final Block finallyBody) {
         assert tryNode.getFinallyBody() == null;
 
+        final Block finallyBlock = createFinallyBlock(finallyBody);
+        final ArrayList<Block> inlinedFinallies = new ArrayList<>();
+        final FunctionNode fn = lc.getCurrentFunction();
         final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            final List<Node> insideTry = new ArrayList<>();
-
-            @Override
-            public boolean enterDefault(final Node node) {
-                insideTry.add(node);
-                return true;
-            }
 
             @Override
             public boolean enterFunctionNode(final FunctionNode functionNode) {
@@ -398,12 +402,8 @@
 
             @Override
             public Node leaveThrowNode(final ThrowNode throwNode) {
-                if (rethrows.contains(throwNode)) {
-                    final List<Statement> newStatements = copyFinally(finallyBody);
-                    if (!isTerminal(newStatements)) {
-                        newStatements.add(throwNode);
-                    }
-                    return BlockStatement.createReplacement(throwNode, newStatements);
+                if (rethrow == throwNode) {
+                    return new BlockStatement(prependFinally(finallyBlock, throwNode));
                 }
                 return throwNode;
             }
@@ -419,58 +419,94 @@
             }
 
             private Node leaveJumpStatement(final JumpStatement jump) {
-                return copy(jump, (Node)jump.getTarget(Lower.this.lc));
+                // NOTE: leaveJumpToInlinedFinally deliberately does not delegate to this method, only break and
+                // continue are edited. JTIF nodes should not be changed, rather the surroundings of
+                // break/continue/return that were moved into the inlined finally block itself will be changed.
+
+                // If this visitor's lc doesn't find the target of the jump, it means it's external to the try block.
+                if (jump.getTarget(lc) == null) {
+                    return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, jump));
+                }
+                return jump;
             }
 
             @Override
             public Node leaveReturnNode(final ReturnNode returnNode) {
-                final Expression expr  = returnNode.getExpression();
-                final List<Statement> newStatements = new ArrayList<>();
-
-                final Expression resultNode;
-                if (expr != null) {
-                    //we need to evaluate the result of the return in case it is complex while
-                    //still in the try block, store it in a result value and return it afterwards
-                    resultNode = new IdentNode(Lower.this.compilerConstant(RETURN));
-                    newStatements.add(new ExpressionStatement(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+                final Expression expr = returnNode.getExpression();
+                if (isTerminalFinally(finallyBlock)) {
+                    if (expr == null) {
+                        // Terminal finally; no return expression.
+                        return createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock));
+                    }
+                    // Terminal finally; has a return expression.
+                    final List<Statement> newStatements = new ArrayList<>(2);
+                    final int retLineNumber = returnNode.getLineNumber();
+                    final long retToken = returnNode.getToken();
+                    // Expression is evaluated for side effects.
+                    newStatements.add(new ExpressionStatement(retLineNumber, retToken, returnNode.getFinish(), expr));
+                    newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock)));
+                    return new BlockStatement(retLineNumber, new Block(retToken, finallyBlock.getFinish(), newStatements));
+                } else if (expr == null || expr instanceof PrimitiveLiteralNode<?> || (expr instanceof IdentNode && RETURN.symbolName().equals(((IdentNode)expr).getName()))) {
+                    // Nonterminal finally; no return expression, or returns a primitive literal, or returns :return.
+                    // Just move the return expression into the finally block.
+                    return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode));
                 } else {
-                    resultNode = null;
+                    // We need to evaluate the result of the return in case it is complex while still in the try block,
+                    // store it in :return, and return it afterwards.
+                    final List<Statement> newStatements = new ArrayList<>();
+                    final int retLineNumber = returnNode.getLineNumber();
+                    final long retToken = returnNode.getToken();
+                    final int retFinish = returnNode.getFinish();
+                    final Expression resultNode = new IdentNode(expr.getToken(), expr.getFinish(), RETURN.symbolName());
+                    // ":return = <expr>;"
+                    newStatements.add(new ExpressionStatement(retLineNumber, retToken, retFinish, new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+                    // inline finally and end it with "return :return;"
+                    newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode.setExpression(resultNode))));
+                    return new BlockStatement(retLineNumber, new Block(retToken, retFinish, newStatements));
                 }
-
-                newStatements.addAll(copyFinally(finallyBody));
-                if (!isTerminal(newStatements)) {
-                    newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
-                }
-
-                return BlockStatement.createReplacement(returnNode, lc.getCurrentBlock().getFinish(), newStatements);
-            }
-
-            private Node copy(final Statement endpoint, final Node targetNode) {
-                if (!insideTry.contains(targetNode)) {
-                    final List<Statement> newStatements = copyFinally(finallyBody);
-                    if (!isTerminal(newStatements)) {
-                        newStatements.add(endpoint);
-                    }
-                    return BlockStatement.createReplacement(endpoint, tryNode.getFinish(), newStatements);
-                }
-                return endpoint;
             }
         });
-
-        addStatement(newTryNode);
-        for (final Node statement : finallyBody.getStatements()) {
-            addStatement((Statement)statement);
-        }
+        addStatement(inlinedFinallies.isEmpty() ? newTryNode : newTryNode.setInlinedFinallies(lc, inlinedFinallies));
+        // TODO: if finallyStatement is terminal, we could just have sites of inlined finallies jump here.
+        addStatement(new BlockStatement(finallyBlock));
 
         return newTryNode;
     }
 
+    private static JumpToInlinedFinally createJumpToInlinedFinally(final FunctionNode fn, final List<Block> inlinedFinallies, final Block finallyBlock) {
+        final String labelName = fn.uniqueName(":finally");
+        final long token = finallyBlock.getToken();
+        final int finish = finallyBlock.getFinish();
+        inlinedFinallies.add(new Block(token, finish, new LabelNode(finallyBlock.getFirstStatementLineNumber(),
+                token, finish, labelName, finallyBlock)));
+        return new JumpToInlinedFinally(labelName);
+    }
+
+    private static Block prependFinally(final Block finallyBlock, final Statement statement) {
+        final Block inlinedFinally = ensureUniqueNamesIn(finallyBlock);
+        if (isTerminalFinally(finallyBlock)) {
+            return inlinedFinally;
+        }
+        final List<Statement> stmts = inlinedFinally.getStatements();
+        final List<Statement> newStmts = new ArrayList<>(stmts.size() + 1);
+        newStmts.addAll(stmts);
+        newStmts.add(statement);
+        return new Block(inlinedFinally.getToken(), statement.getFinish(), newStmts);
+    }
+
     @Override
     public Node leaveTryNode(final TryNode tryNode) {
         final Block finallyBody = tryNode.getFinallyBody();
+        TryNode newTryNode = tryNode.setFinallyBody(lc, null);
 
-        if (finallyBody == null) {
-            return addStatement(ensureUnconditionalCatch(tryNode));
+        // No finally or empty finally
+        if (finallyBody == null || finallyBody.getStatementCount() == 0) {
+            final List<CatchNode> catches = newTryNode.getCatches();
+            if (catches == null || catches.isEmpty()) {
+                // A completely degenerate try block: empty finally, no catches. Replace it with try body.
+                return addStatement(new BlockStatement(tryNode.getBody()));
+            }
+            return addStatement(ensureUnconditionalCatch(newTryNode));
         }
 
         /*
@@ -496,11 +532,9 @@
          *   now splice in finally code wherever needed
          *
          */
-        TryNode newTryNode;
-
         final Block catchAll = catchAllBlock(tryNode);
 
-        final List<ThrowNode> rethrows = new ArrayList<>();
+        final List<ThrowNode> rethrows = new ArrayList<>(1);
         catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterThrowNode(final ThrowNode throwNode) {
@@ -510,20 +544,18 @@
         });
         assert rethrows.size() == 1;
 
-        if (tryNode.getCatchBlocks().isEmpty()) {
-            newTryNode = tryNode.setFinallyBody(null);
-        } else {
-            final Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), ensureUnconditionalCatch(tryNode.setFinallyBody(null)));
-            newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
+        if (!tryNode.getCatchBlocks().isEmpty()) {
+            final Block outerBody = new Block(newTryNode.getToken(), newTryNode.getFinish(), ensureUnconditionalCatch(newTryNode));
+            newTryNode = newTryNode.setBody(lc, outerBody).setCatchBlocks(lc, null);
         }
 
-        newTryNode = newTryNode.setCatchBlocks(Arrays.asList(catchAll)).setFinallyBody(null);
+        newTryNode = newTryNode.setCatchBlocks(lc, Arrays.asList(catchAll));
 
         /*
          * Now that the transform is done, we have to go into the try and splice
          * the finally block in front of any statement that is outside the try
          */
-        return spliceFinally(newTryNode, rethrows, finallyBody);
+        return (TryNode)lc.replace(tryNode, spliceFinally(newTryNode, rethrows.get(0), finallyBody));
     }
 
     private TryNode ensureUnconditionalCatch(final TryNode tryNode) {
@@ -535,7 +567,7 @@
         final List<Block> newCatchBlocks = new ArrayList<>(tryNode.getCatchBlocks());
 
         newCatchBlocks.add(catchAllBlock(tryNode));
-        return tryNode.setCatchBlocks(newCatchBlocks);
+        return tryNode.setCatchBlocks(lc, newCatchBlocks);
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Wed Jul 05 20:17:15 2017 +0200
@@ -52,6 +52,7 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ReturnNode;
@@ -359,6 +360,11 @@
         return leaveJumpNode(continueNode);
     }
 
+    @Override
+    public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return leaveJumpNode(jumpToInlinedFinally);
+    }
+
     private JumpStatement leaveJumpNode(final JumpStatement jump) {
         if (inSplitNode()) {
             final SplitState splitState = getCurrentSplitState();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java	Wed Jul 05 20:17:15 2017 +0200
@@ -40,6 +40,7 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
@@ -197,6 +198,12 @@
         return indexNode;
     }
 
+    @Override
+    public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        weight += BREAK_WEIGHT;
+        return jumpToInlinedFinally;
+    }
+
     @SuppressWarnings("rawtypes")
     @Override
     public boolean enterLiteralNode(final LiteralNode literalNode) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java	Wed Jul 05 20:17:15 2017 +0200
@@ -322,6 +322,14 @@
     }
 
     /**
+     * Returns the last statement in the block.
+     * @return the last statement in the block, or null if the block has no statements.
+     */
+    public Statement getLastStatement() {
+        return statements.isEmpty() ? null : statements.get(statements.size() - 1);
+    }
+
+    /**
      * Reset the statement list for this block
      *
      * @param lc lexical context
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockLexicalContext.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockLexicalContext.java	Wed Jul 05 20:17:15 2017 +0200
@@ -74,7 +74,7 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         T expected = node;
         if (node instanceof Block) {
             final List<Statement> newStatements = popStatements();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockStatement.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockStatement.java	Wed Jul 05 20:17:15 2017 +0200
@@ -40,6 +40,15 @@
     /**
      * Constructor
      *
+     * @param block the block to execute
+     */
+    public BlockStatement(final Block block) {
+        this(block.getFirstStatementLineNumber(), block);
+    }
+
+    /**
+     * Constructor
+     *
      * @param lineNumber line number
      * @param block the block to execute
      */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BreakNode.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BreakNode.java	Wed Jul 05 20:17:15 2017 +0200
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public Label getTargetLabel(final BreakableNode target) {
+    Label getTargetLabel(final BreakableNode target) {
         return target.getBreakLabel();
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ContinueNode.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ContinueNode.java	Wed Jul 05 20:17:15 2017 +0200
@@ -78,7 +78,7 @@
     }
 
     @Override
-    public Label getTargetLabel(final BreakableNode target) {
+    Label getTargetLabel(final BreakableNode target) {
         return ((LoopNode)target).getContinueLabel();
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpStatement.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpStatement.java	Wed Jul 05 20:17:15 2017 +0200
@@ -101,7 +101,26 @@
      * @throws ClassCastException if invoked on the kind of breakable node that this jump statement is not prepared to
      * handle.
      */
-    public abstract Label getTargetLabel(final BreakableNode target);
+    abstract Label getTargetLabel(final BreakableNode target);
+
+    /**
+     * Returns the label this jump statement targets.
+     * @param lc the lexical context
+     * @return the label this jump statement targets.
+     */
+    public Label getTargetLabel(final LexicalContext lc) {
+        return getTargetLabel(getTarget(lc));
+    }
+
+    /**
+     * Returns the limit node for popping scopes when this jump statement is effected.
+     * @param lc the current lexical context
+     * @return the limit node for popping scopes when this jump statement is effected.
+     */
+    public LexicalContextNode getPopScopeLimit(final LexicalContext lc) {
+        // In most cases (break and continue) this is equal to the target.
+        return getTarget(lc);
+    }
 
     @Override
     public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpToInlinedFinally.java	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.Objects;
+import jdk.nashorn.internal.codegen.Label;
+import jdk.nashorn.internal.ir.annotations.Immutable;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR representation for synthetic jump into an inlined finally statement.
+ */
+@Immutable
+public final class JumpToInlinedFinally extends JumpStatement {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructor
+     *
+     * @param labelName  label name for inlined finally block
+     */
+    public JumpToInlinedFinally(final String labelName) {
+        super(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH, Objects.requireNonNull(labelName));
+    }
+
+    private JumpToInlinedFinally(final JumpToInlinedFinally breakNode, final LocalVariableConversion conversion) {
+        super(breakNode, conversion);
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterJumpToInlinedFinally(this)) {
+            return visitor.leaveJumpToInlinedFinally(this);
+        }
+
+        return this;
+    }
+
+    @Override
+    JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+        return new JumpToInlinedFinally(this, conversion);
+    }
+
+    @Override
+    String getStatementName() {
+        return ":jumpToInlinedFinally";
+    }
+
+    @Override
+    public Block getTarget(final LexicalContext lc) {
+        return lc.getInlinedFinally(getLabelName());
+    }
+
+    @Override
+    public TryNode getPopScopeLimit(final LexicalContext lc) {
+        // Returns the try node to which this jump's target belongs. This will make scope popping also pop the scope
+        // for the body of the try block, if it needs scope.
+        return lc.getTryNodeForInlinedFinally(getLabelName());
+    }
+
+    @Override
+    Label getTargetLabel(final BreakableNode target) {
+        assert target != null;
+        // We're jumping to the entry of the inlined finally block
+        return ((Block)target).getEntryLabel();
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java	Wed Jul 05 20:17:15 2017 +0200
@@ -190,7 +190,7 @@
      * @return the node that was popped
      */
     @SuppressWarnings("unchecked")
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         --sp;
         final LexicalContextNode popped = stack[sp];
         stack[sp] = null;
@@ -469,7 +469,7 @@
      * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode
      * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location
      * and the break/continue target.
-     * @param until node to stop counting at. Must be within the current  function
+     * @param until node to stop counting at. Must be within the current function
      * @return number of with scopes encountered in the context
      */
     public int getScopeNestingLevelTo(final LexicalContextNode until) {
@@ -565,11 +565,41 @@
     }
 
     /**
+     * Find the inlined finally block node corresponding to this label.
+     * @param labelName label name to search for. Must not be null.
+     * @return closest inlined finally block with the given label
+     */
+    public Block getInlinedFinally(final String labelName) {
+        for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
+            final Block inlinedFinally = iter.next().getInlinedFinally(labelName);
+            if (inlinedFinally != null) {
+                return inlinedFinally;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find the try node for an inlined finally block corresponding to this label.
+     * @param labelName label name to search for. Must not be null.
+     * @return the try node to which the labelled inlined finally block belongs.
+     */
+    public TryNode getTryNodeForInlinedFinally(final String labelName) {
+        for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
+            final TryNode tryNode = iter.next();
+            if (tryNode.getInlinedFinally(labelName) != null) {
+                return tryNode;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Check the lexical context for a given label node by name
      * @param name name of the label
      * @return LabelNode if found, null otherwise
      */
-    public LabelNode findLabel(final String name) {
+    private LabelNode findLabel(final String name) {
         for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) {
             final LabelNode next = iter.next();
             if (next.getLabelName().equals(name)) {
@@ -592,6 +622,12 @@
                 return true;
             } else if (next == target) {
                 return false;
+            } else if (next instanceof TryNode) {
+                for(final Block inlinedFinally: ((TryNode)next).getInlinedFinallies()) {
+                    if (TryNode.getLabelledInlinedFinallyBlock(inlinedFinally) == target) {
+                        return false;
+                    }
+                }
             }
         }
         throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContextNode.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContextNode.java	Wed Jul 05 20:17:15 2017 +0200
@@ -54,8 +54,8 @@
         static Node accept(final LexicalContextNode node, final NodeVisitor<? extends LexicalContext> visitor) {
             final LexicalContext lc = visitor.getLexicalContext();
             lc.push(node);
-            final LexicalContextNode newNode = (LexicalContextNode)node.accept(lc, visitor);
-            return (Node)lc.pop(newNode);
+            final Node newNode = node.accept(lc, visitor);
+            return lc.pop(newNode);
         }
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/OptimisticLexicalContext.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/OptimisticLexicalContext.java	Wed Jul 05 20:17:15 2017 +0200
@@ -115,7 +115,7 @@
     }
 
     @Override
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         final T popped = super.pop(node);
         if (isEnabled) {
             if(node instanceof FunctionNode) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java	Wed Jul 05 20:17:15 2017 +0200
@@ -27,7 +27,9 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -35,7 +37,7 @@
  * IR representation of a TRY statement.
  */
 @Immutable
-public final class TryNode extends Statement implements JoinPredecessor {
+public final class TryNode extends LexicalContextStatement implements JoinPredecessor {
     private static final long serialVersionUID = 1L;
 
     /** Try statements. */
@@ -47,12 +49,24 @@
     /** Finally clause. */
     private final Block finallyBody;
 
+    /**
+     * List of inlined finally blocks. The structure of every inlined finally is:
+     * Block(LabelNode(label, Block(finally-statements, (JumpStatement|ReturnNode)?))).
+     * That is, the block has a single LabelNode statement with the label and a block containing the
+     * statements of the inlined finally block with the jump or return statement appended (if the finally
+     * block was not terminal; the original jump/return is simply ignored if the finally block itself
+     * terminates). The reason for this somewhat strange arrangement is that we didn't want to create a
+     * separate class for the (label, BlockStatement pair) but rather reused the already available LabelNode.
+     * However, if we simply used List<LabelNode> without wrapping the label nodes in an additional Block,
+     * that would've thrown off visitors relying on BlockLexicalContext -- same reason why we never use
+     * Statement as the type of bodies of e.g. IfNode, WhileNode etc. but rather blockify them even when they're
+     * single statements.
+     */
+    private final List<Block> inlinedFinallies;
+
     /** Exception symbol. */
     private Symbol exception;
 
-    /** Catchall exception for finally expansion, where applicable */
-    private Symbol finallyCatchAll;
-
     private final LocalVariableConversion conversion;
 
     /**
@@ -71,21 +85,23 @@
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
         this.conversion  = null;
+        this.inlinedFinallies = Collections.emptyList();
     }
 
-    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion) {
+    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies) {
         super(tryNode);
         this.body        = body;
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
         this.conversion  = conversion;
+        this.inlinedFinallies = inlinedFinallies;
         this.exception = tryNode.exception;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
         //try nodes are never in lex context
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
     }
 
     @Override
@@ -106,16 +122,16 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+    public Node accept(final LexicalContext lc, NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTryNode(this)) {
             // Need to do finallybody first for termination analysis. TODO still necessary?
             final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
             final Block newBody        = (Block)body.accept(visitor);
             return visitor.leaveTryNode(
-                setBody(newBody).
-                setFinallyBody(newFinallyBody).
-                setCatchBlocks(Node.accept(visitor, catchBlocks)).
-                setFinallyCatchAll(finallyCatchAll));
+                setBody(lc, newBody).
+                setFinallyBody(lc, newFinallyBody).
+                setCatchBlocks(lc, Node.accept(visitor, catchBlocks)).
+                setInlinedFinallies(lc, Node.accept(visitor, inlinedFinallies)));
         }
 
         return this;
@@ -136,14 +152,15 @@
 
     /**
      * Reset the body of this try block
+     * @param lc current lexical context
      * @param body new body
      * @return new TryNode or same if unchanged
      */
-    public TryNode setBody(final Block body) {
+    public TryNode setBody(final LexicalContext lc, final Block body) {
         if (this.body == body) {
             return this;
         }
-        return new TryNode(this,  body, catchBlocks, finallyBody, conversion);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this,  body, catchBlocks, finallyBody, conversion, inlinedFinallies));
     }
 
     /**
@@ -172,14 +189,15 @@
 
     /**
      * Set the catch blocks of this try
+     * @param lc current lexical context
      * @param catchBlocks list of catch blocks
      * @return new TryNode or same if unchanged
      */
-    public TryNode setCatchBlocks(final List<Block> catchBlocks) {
+    public TryNode setCatchBlocks(final LexicalContext lc, final List<Block> catchBlocks) {
         if (this.catchBlocks == catchBlocks) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
     }
 
     /**
@@ -200,27 +218,6 @@
     }
 
     /**
-     * Get the catch all symbol for this try block
-     * @return catch all symbol
-     */
-    public Symbol getFinallyCatchAll() {
-        return this.finallyCatchAll;
-    }
-
-    /**
-     * If a finally block exists, the synthetic catchall needs another symbol to
-     * store its throwable
-     * @param finallyCatchAll a symbol for the finally catch all exception
-     * @return new TryNode or same if unchanged
-     *
-     * TODO can this still be stateful?
-     */
-    public TryNode setFinallyCatchAll(final Symbol finallyCatchAll) {
-        this.finallyCatchAll = finallyCatchAll;
-        return this;
-    }
-
-    /**
      * Get the body of the finally clause for this try
      * @return finally body, or null if no finally
      */
@@ -229,15 +226,87 @@
     }
 
     /**
+     * Get the inlined finally block with the given label name. This returns the actual finally block in the
+     * {@link LabelNode}, not the outer wrapper block for the {@link LabelNode}.
+     * @param labelName the name of the inlined finally's label
+     * @return the requested finally block, or null if no finally block's label matches the name.
+     */
+    public Block getInlinedFinally(final String labelName) {
+        for(final Block inlinedFinally: inlinedFinallies) {
+            final LabelNode labelNode = getInlinedFinallyLabelNode(inlinedFinally);
+            if (labelNode.getLabelName().equals(labelName)) {
+                return labelNode.getBody();
+            }
+        }
+        return null;
+    }
+
+    private static LabelNode getInlinedFinallyLabelNode(final Block inlinedFinally) {
+        return (LabelNode)inlinedFinally.getStatements().get(0);
+    }
+
+    /**
+     * Given an outer wrapper block for the {@link LabelNode} as returned by {@link #getInlinedFinallies()},
+     * returns its actual inlined finally block.
+     * @param inlinedFinally the outer block for inlined finally, as returned as an element of
+     * {@link #getInlinedFinallies()}.
+     * @return the block contained in the {@link LabelNode} contained in the passed block.
+     */
+    public static Block getLabelledInlinedFinallyBlock(final Block inlinedFinally) {
+        return getInlinedFinallyLabelNode(inlinedFinally).getBody();
+    }
+
+    /**
+     * Returns a list of inlined finally blocks. Note that this returns a list of {@link Block}s such that each one of
+     * them has a single {@link LabelNode}, which in turn contains the label name for the finally block and the
+     * actual finally block. To safely extract the actual finally block, use
+     * {@link #getLabelledInlinedFinallyBlock(Block)}.
+     * @return a list of inlined finally blocks.
+     */
+    public List<Block> getInlinedFinallies() {
+        return Collections.unmodifiableList(inlinedFinallies);
+    }
+
+    /**
      * Set the finally body of this try
+     * @param lc current lexical context
      * @param finallyBody new finally body
      * @return new TryNode or same if unchanged
      */
-    public TryNode setFinallyBody(final Block finallyBody) {
+    public TryNode setFinallyBody(final LexicalContext lc, final Block finallyBody) {
         if (this.finallyBody == finallyBody) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+    }
+
+    /**
+     * Set the inlined finally blocks of this try. Each element should be a block with a single statement that is a
+     * {@link LabelNode} with a unique label, and the block within the label node should contain the actual inlined
+     * finally block.
+     * @param lc current lexical context
+     * @param inlinedFinallies list of inlined finally blocks
+     * @return new TryNode or same if unchanged
+     */
+    public TryNode setInlinedFinallies(final LexicalContext lc, final List<Block> inlinedFinallies) {
+        if (this.inlinedFinallies == inlinedFinallies) {
+            return this;
+        }
+        assert checkInlinedFinallies(inlinedFinallies);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+    }
+
+    private static boolean checkInlinedFinallies(final List<Block> inlinedFinallies) {
+        if (!inlinedFinallies.isEmpty()) {
+            final Set<String> labels = new HashSet<>();
+            for (final Block inlinedFinally : inlinedFinallies) {
+                final List<Statement> stmts = inlinedFinally.getStatements();
+                assert stmts.size() == 1;
+                final LabelNode ln = getInlinedFinallyLabelNode(inlinedFinally);
+                assert labels.add(ln.getLabelName()); // unique label
+            }
+        }
+        return true;
     }
 
     @Override
@@ -245,7 +314,7 @@
         if(this.conversion == conversion) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
     }
 
     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java	Wed Jul 05 20:17:15 2017 +0200
@@ -391,6 +391,9 @@
             finallyBody.accept(this);
         }
 
+        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+            inlinedFinally.accept(this);
+        }
         return false;
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Thu Jan 29 15:36:12 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Wed Jul 05 20:17:15 2017 +0200
@@ -43,6 +43,7 @@
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
@@ -473,6 +474,26 @@
     }
 
     /**
+     * Callback for entering a JumpToInlinedFinally
+     *
+     * @param  jumpToInlinedFinally the node
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return enterDefault(jumpToInlinedFinally);
+    }
+
+    /**
+     * Callback for leaving a JumpToInlinedFinally
+     *
+     * @param  jumpToInlinedFinally the node
+     * @return processed node, which will replace the original one, or the original node
+     */
+    public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return leaveDefault(jumpToInlinedFinally);
+    }
+
+    /**
      * Callback for entering a LabelNode
      *
      * @param  labelNode the node
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8067139.js	Wed Jul 05 20:17:15 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8067139: Finally blocks inlined incorrectly
+ *
+ * @test
+ * @run
+ */
+
+// Test case for JDK-8067139
+// as well as for JDK-8030198 which is a duplicate.
+(function(){
+    var catchCount = 0; 
+    try {
+        (function (){
+            try { 
+                return; 
+            } catch(x) { 
+                ++catchCount;
+            } finally { 
+                throw 0; 
+            } 
+        })();
+        Assert.fail(); // must throw
+    } catch(e) {
+        Assert.assertEquals(e, 0); // threw 0
+        Assert.assertEquals(catchCount, 0); // inner catch never executed
+    }
+})();
+
+// Test case for JDK-8048862 which is a duplicate of this bug
+var ret = (function(o) { 
+    try{
+        with(o) {
+            return x;
+        }
+    } finally {
+        try { 
+            return x;
+        } catch(e) {
+            Assert.assertTrue(e instanceof ReferenceError);
+            return 2;
+        }
+    }
+})({x: 1});
+Assert.assertEquals(ret, 2); // executed the catch block
+
+// Test cases for JDK-8066231 that is a duplicate of this bug
+// Case 1
+(function (){ try { Object; } catch(x if x >>>=0) { throw x2; } finally { } })();
+// Case 2
+try {
+    (function (){ try { return; } catch(x) { return x ^= 0; } finally { throw 0; } })();
+    Assert.fail();
+} catch(e) {
+    Assert.assertEquals(e, 0); // threw 0
+}
+// Case 3
+try {
+    (function (){ try { return; } catch(x) { return x ^= Object; } finally { throw Object; } })();
+    Assert.fail();
+} catch(e) {
+    Assert.assertEquals(e, Object); // threw Object
+}
+// Case from comment
+try {
+    (function () { try { Object } catch(x) { (x=y); return; } finally { throw Object; } })();
+    Assert.fail();
+} catch(e) {
+    Assert.assertEquals(e, Object); // threw Object
+}
--- a/test/make/TestJavaCompilation.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/test/make/TestJavaCompilation.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -50,6 +50,9 @@
 clean-jar1:
 	$(RM) -r $(OUTPUT_DIR)/_jar1* $(OUTPUT_DIR)/jar1*
 
+$(JAR1_MANIFEST): | $(OUTPUT_DIR)/_jar1_created
+	$(ECHO) "Test-Attribute: value" > $(JAR1_MANIFEST)
+
 $(OUTPUT_DIR)/_jar1_created: $(DEPS)
 	$(RM) -r $(JAR1_SRC_ROOT)
 	$(RM) $(JAR1_FILE)
@@ -61,7 +64,6 @@
 	$(TOUCH) $(JAR1_SRC_ROOT)/dir1/file1.class
 	$(TOUCH) $(JAR1_SRC_ROOT)/dir2/file2.class
 	$(TOUCH) $(JAR1_SRC_ROOT)/META-INF/metafile
-	$(ECHO) "Test-Attribute: value" > $(JAR1_MANIFEST)
 	$(TOUCH) $@
 
 $(eval $(call SetupArchive,BUILD_JAR1, \
@@ -77,7 +79,7 @@
 	$(DIFF) -r $(JAR1_SRC_ROOT)/dir1 $(JAR1_UNZIP)/dir1
 	$(DIFF) -r $(JAR1_SRC_ROOT)/dir2 $(JAR1_UNZIP)/dir2
 	$(DIFF) -r $(JAR1_SRC_ROOT)/META-INF/metafile $(JAR1_UNZIP)/META-INF/metafile
-	if [ "`$(GREP) 'Test-Attribute: value' $(JAR1_MANIFEST)`" = "" ]; then \
+	if [ "`$(GREP) 'Test-Attribute: value' $(JAR1_UNZIP)/META-INF/MANIFEST.MF`" = "" ]; then \
 	  $(ECHO) "Could not find Test-Attribute in manifest of $(JAR1_FILE)"; \
 	  exit 1; \
 	fi
@@ -88,7 +90,7 @@
 
 # Change a source file and call this makefile again to force the jar to be 
 # updated. 
-$(OUTPUT_DIR)_jar1_updated: $(OUTPUT_DIR)/_jar1_verified
+$(OUTPUT_DIR)/_jar1_updated: $(OUTPUT_DIR)/_jar1_verified
 	$(ECHO) updated > $(JAR1_SRC_ROOT)/dir1/file1.class
 	$(ECHO) updated > $(JAR1_SRC_ROOT)/META-INF/metafile
 	$(TOUCH) $(OUTPUT_DIR)/_jar1_created
@@ -96,9 +98,26 @@
 	$(TOUCH) $@
 
 update-jar1: $(OUTPUT_DIR)_jar1_updated
-TEST_TARGETS += $(OUTPUT_DIR)_jar1_updated
 
-.PHONY: clean-jar1 create-jar1 update-jar1
+# Change the manifest file and call this makefile again to force the jar
+# to be updated
+$(OUTPUT_DIR)/_jar1_updated_manifest: $(OUTPUT_DIR)/_jar1_updated
+	$(ECHO) "Test-Attribute: foobar" > $(JAR1_MANIFEST)
+	+$(MAKE) -f $(THIS_FILE) $(BUILD_JAR1)
+	$(RM) -r $(JAR1_UNZIP)
+	$(MKDIR) -p $(JAR1_UNZIP)
+	$(CD) $(JAR1_UNZIP) && $(UNZIP) $(JAR1_FILE) $(LOG_DEBUG)
+	if [ "`$(GREP) 'Test-Attribute: foobar' $(JAR1_UNZIP)/META-INF/MANIFEST.MF`" = "" ]; then \
+	  $(ECHO) "Could not find Test-Attribute in manifest of $(JAR1_FILE)"; \
+	  exit 1; \
+	fi
+	$(TOUCH) $@
+
+update-jar1-manifest: $(OUTPUT_DIR)/_jar1_updated_manifest
+
+TEST_TARGETS += $(OUTPUT_DIR)/_jar1_updated $(OUTPUT_DIR)/_jar1_updated_manifest
+
+.PHONY: clean-jar1 create-jar1 update-jar1 update-jar1-manifest
 
 ################################################################################
 # Test: jar2
@@ -139,14 +158,14 @@
 create-jar2: $(OUTPUT_DIR)/_jar2_verified
 TEST_TARGETS += $(OUTPUT_DIR)/_jar2_verified
 
-$(OUTPUT_DIR)_jar2_updated: $(OUTPUT_DIR)/_jar2_verified
+$(OUTPUT_DIR)/_jar2_updated: $(OUTPUT_DIR)/_jar2_verified
 	$(ECHO) updated > $(JAR2_SRC_ROOT1)/dir1/file1.class
 	$(TOUCH) $(OUTPUT_DIR)/_jar2_created
 	+$(MAKE) -f $(THIS_FILE) $(OUTPUT_DIR)/_jar2_verified
 	$(TOUCH) $@
 
-update-jar2: $(OUTPUT_DIR)_jar2_updated
-TEST_TARGETS += $(OUTPUT_DIR)_jar2_updated
+update-jar2: $(OUTPUT_DIR)/_jar2_updated
+TEST_TARGETS += $(OUTPUT_DIR)/_jar2_updated
 
 .PHONY: clean-jar2 create-jar2 update-jar2
 
@@ -200,14 +219,14 @@
 create-jar3: $(OUTPUT_DIR)/_jar3_verified
 TEST_TARGETS += $(OUTPUT_DIR)/_jar3_verified
 
-$(OUTPUT_DIR)_jar3_updated: $(OUTPUT_DIR)/_jar3_verified
+$(OUTPUT_DIR)/_jar3_updated: $(OUTPUT_DIR)/_jar3_verified
 	$(ECHO) updated > $(JAR3_SRC_ROOT2)/extra-file
 	$(TOUCH) $(OUTPUT_DIR)/_jar3_created
 	+$(MAKE) -f $(THIS_FILE) $(OUTPUT_DIR)/_jar3_verified
 	$(TOUCH) $@
 
-update-jar3: $(OUTPUT_DIR)_jar3_updated
-TEST_TARGETS += $(OUTPUT_DIR)_jar3_updated
+update-jar3: $(OUTPUT_DIR)/_jar3_updated
+TEST_TARGETS += $(OUTPUT_DIR)/_jar3_updated
 
 .PHONY: clean-jar3 create-jar3 update-jar3
 
--- a/test/make/TestMakeBase.gmk	Thu Jan 29 15:36:12 2015 -0800
+++ b/test/make/TestMakeBase.gmk	Wed Jul 05 20:17:15 2017 +0200
@@ -33,7 +33,14 @@
     $(SRC_ROOT)/make/common/MakeBase.gmk \
     #
 
+# On macosx, file system timestamps only have 1 second resultion so must add
+# sleeps to properly test dependencies.
+ifeq ($(OPENJDK_BUILD_OS), macosx)
+  SLEEP_ON_MAC := sleep 1
+endif
+
 OUTPUT_DIR := $(TESTMAKE_OUTPUTDIR)/make-base
+$(call MakeDir, $(OUTPUT_DIR))
 
 ################################################################################
 # Escape $
@@ -56,5 +63,124 @@
 TEST_TARGETS += $(ESCAPE_DOLLAR_DIR)/_escape_dollar
 
 ################################################################################
+# Test Equals
+
+EQUALS_VALUE1 := value1$(SPACE)
+EQUALS_VALUE2 := value2
+
+ifneq ($(call equals, $(EQUALS_VALUE1), $(EQUALS_VALUE2)), )
+  $(error The strings >$(EQUALS_VALUE1)< and >$(EQUALS_VALUE2)< are equal)
+endif
+
+ifeq ($(call equals, $(EQUALS_VALUE1), $(EQUALS_VALUE1)), )
+  $(error The strings >$(EQUALS_VALUE1)< and >$(EQUALS_VALUE1)< are not equal)
+endif
+
+################################################################################
+# Test ShellQuote
+
+SHELL_QUOTE_VALUE := foo '""' "''" bar
+SHELL_QUOTE_RESULT := $(shell $(ECHO) $(call ShellQuote, \
+    $(SHELL_QUOTE_VALUE)))
+
+ifneq ($(SHELL_QUOTE_VALUE), $(SHELL_QUOTE_RESULT))
+  $(error Expected: >$(SHELL_QUOTE_VALUE)< - Result: >$(SHELL_QUOTE_RESULT)<)
+endif
+
+################################################################################
+# Test read and write to file
+
+READ_WRITE_FILE := $(OUTPUT_DIR)/read-write
+READ_WRITE_VALUE := foo '""' "''" \t\n\\ bar
+$(call WriteFile, $(READ_WRITE_VALUE), $(READ_WRITE_FILE))
+READ_WRITE_RESULT := $(call ReadFile, $(READ_WRITE_FILE))
+
+ifneq ($(READ_WRITE_VALUE), $(READ_WRITE_RESULT))
+  $(error Expected: >$(READ_WRITE_VALUE)< - Result: >$(READ_WRITE_RESULT)<)
+endif
+
+################################################################################
+# Test creating dependencies on make variables
+
+VARDEP_DIR := $(OUTPUT_DIR)/vardep
+VARDEP_SRC_FILE := $(VARDEP_DIR)/src-file
+VARDEP_TARGET_FILE := $(VARDEP_DIR)/target-file
+VARDEP_FLAG_FILE := $(VARDEP_DIR)/flag-file
+
+$(VARDEP_DIR)/src-file:
+	$(MKDIR) -p $(@D)
+	$(ECHO) "some string XXX" > $@
+
+$(VARDEP_TARGET_FILE): $(VARDEP_DIR)/src-file \
+    $(call DependOnVariable, VARDEP_TEST_VAR)
+	$(MKDIR) -p $(@D)
+	$(SED) -e 's/XXX/$(VARDEP_TEST_VAR)/g' $< > $@
+	$(TOUCH) $(VARDEP_FLAG_FILE)
+
+test-vardep:
+	$(RM) $(VARDEP_SRC_FILE) $(VARDEP_TARGET_FILE) $(VARDEP_FLAG_FILE)
+        #
+        # Simply create the target file and verify that it has the correct value
+        #
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=value1 $(VARDEP_TARGET_FILE)
+	$(PRINTF) "Expecting value1: %s\n" "`$(CAT) $(VARDEP_DIR)/target-file`"
+	test "some string value1" = "`$(CAT) $(VARDEP_DIR)/target-file`"
+	test -e $(VARDEP_FLAG_FILE)
+        #
+        # Make the target file again and verify that the value is updated with 
+        # the new value
+        #
+	$(SLEEP_ON_MAC)
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=value2 $(VARDEP_TARGET_FILE)
+	$(PRINTF) "Expecting value2: %s\n" "`$(CAT) $(VARDEP_DIR)/target-file`"
+	test "some string value2" = "`$(CAT) $(VARDEP_DIR)/target-file`"
+	test -e $(VARDEP_FLAG_FILE)
+        #
+        # Make the target again with the same value and verify that the recipe
+        # was never run by checking that the flag file was not recreated
+        #
+	$(SLEEP_ON_MAC)
+	$(RM) $(VARDEP_FLAG_FILE)
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=value2 $(VARDEP_TARGET_FILE)
+	$(PRINTF) "Expecting value2: %s\n" "`$(CAT) $(VARDEP_DIR)/target-file`"
+	test "some string value2" = "`$(CAT) $(VARDEP_DIR)/target-file`"
+	test ! -e $(VARDEP_FLAG_FILE)
+        #
+        # Test running with spaces at the end and the middle of the value
+        # and verify that the file isn't rewritten the second time
+        #
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR="value3  foo " $(VARDEP_TARGET_FILE)
+	$(RM) $(VARDEP_FLAG_FILE)
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR="value3 foo" $(VARDEP_TARGET_FILE)
+	test ! -e $(VARDEP_FLAG_FILE)
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=" value3  foo" $(VARDEP_TARGET_FILE)
+	test ! -e $(VARDEP_FLAG_FILE)
+
+# Test specifying a specific value file to store variable in
+VARDEP_VALUE_FILE := $(VARDEP_DIR)/value-file
+VARDEP_TEST_VAR2 := value3
+
+VARDEP_RETURN_VALUE := $(call DependOnVariable, VARDEP_TEST_VAR2, $(VARDEP_VALUE_FILE))
+ifneq ($(VARDEP_VALUE_FILE), $(VARDEP_RETURN_VALUE))
+  $(error Expected: $(VARDEP_VALUE_FILE) - DependOnVariable: $(VARDEP_RETURN_VALUE))
+endif
+VARDEP_FILE_CONTENTS := $(shell $(CAT) $(VARDEP_VALUE_FILE))
+ifneq ($(VARDEP_TEST_VAR2), $(VARDEP_FILE_CONTENTS))
+  $(error Expected: $(VARDEP_TEST_VAR2) - DependOnVariable file contained: \
+      $(VARDEP_FILE_CONTENTS))
+endif
+
+# Test with a variable value containing some problematic characters
+VARDEP_TEST_VAR3 := foo '""' "''" bar
+VARDEP_VALUE_FILE := $(call DependOnVariable, VARDEP_TEST_VAR3)
+VARDEP_FILE_CONTENTS := $(shell $(CAT) $(VARDEP_VALUE_FILE))
+ifneq ($(VARDEP_TEST_VAR3), $(VARDEP_FILE_CONTENTS))
+  $(error Expected: >$(VARDEP_TEST_VAR3)< - DependOnVariable file contained: \
+      >$(VARDEP_FILE_CONTENTS)<)
+endif
+
+TEST_TARGETS += test-vardep
+
+################################################################################
 
 all: $(TEST_TARGETS)